feat(zeroclaw): support native live runtime

This commit is contained in:
Clément SAILLANT
2026-03-09 01:59:00 +01:00
parent c4568d56c2
commit 67b27f7fd1
5 changed files with 45 additions and 20 deletions
+9
View File
@@ -74,6 +74,15 @@ zeroclaw --version
Les launchers `tools/ai/zeroclaw_*.sh` resolvent maintenant la racine du repo
dynamiquement et retombent sur `command -v zeroclaw` si besoin.
Posture operateur retenue:
- `zeroclaw.saillant.cc` = surface live du runtime natif quand la stack est
demarree
- `zeroclaw-docs.saillant.cc` = runbook ZeroClaw statique
- `langgraph.saillant.cc` = runbook LangGraph statique
- la stack native reste demarrable a la demande via `tools/ai/zeroclaw_stack_up.sh`
- le fallback provider `OpenRouter` est supporte et valide sur un appel webhook
reel
Chemin operateur supporte:
```bash
+3 -1
View File
@@ -11,7 +11,9 @@
Posture operateur retenue:
- `ZeroClaw` reste un runtime local demarrable a la demande.
- `LangGraph`, `AutoGen` et `n8n` restent des overlays/runbooks autour de ce runtime.
- les surfaces publiques `zeroclaw.saillant.cc` et `langgraph.saillant.cc` servent les runbooks operateur, pas un service coeur always-on.
- `zeroclaw.saillant.cc` sert la surface live du runtime natif quand il est demarre.
- `zeroclaw-docs.saillant.cc` et `langgraph.saillant.cc` servent les runbooks operateur derriere le proxy.
- Le fallback provider `OpenRouter` est valide en runtime sur le gateway natif.
Le repo fournit :
- `specs/` pour la source de vérité
+7 -4
View File
@@ -18,10 +18,13 @@ not required for the canonical repo-local stable path.
Operator posture:
- `ZeroClaw` runtime is started on demand via `tools/ai/zeroclaw_stack_up.sh`.
- `zeroclaw.saillant.cc` and `langgraph.saillant.cc` are expected to serve these
runbooks behind the authenticated `edge-proxy`.
- The static runbooks remain available even when the local `ZeroClaw` runtime is
stopped.
- `zeroclaw.saillant.cc` is the live runtime surface when the native stack is up.
- `zeroclaw-docs.saillant.cc` serves the ZeroClaw runbooks behind the
authenticated `edge-proxy`.
- `langgraph.saillant.cc` serves the LangGraph runbook behind the authenticated
`edge-proxy`.
- When the local `ZeroClaw` runtime is stopped, `zeroclaw.saillant.cc` should
present an operator-friendly offline page instead of raw proxy errors.
Available runbooks:
+1 -1
View File
@@ -84,7 +84,7 @@
<a class="card" href="/integrations/zeroclaw/">
<div class="label">Operator runtime</div>
<div class="title">ZeroClaw</div>
<div class="small">Local gateway, pairing, follow UI and operator loops.</div>
<div class="small">Runbook surface for the live runtime on `zeroclaw.saillant.cc`.</div>
</a>
<a class="card" href="/integrations/langgraph/">
<div class="label">Orchestration overlay</div>
+25 -14
View File
@@ -19,6 +19,7 @@ ART_DIR="${ZEROCLAW_ART_DIR:-$ROOT_DIR/artifacts/zeroclaw}"
ZEROCLAW_BIN="${ZEROCLAW_BIN:-$ROOT_DIR/zeroclaw/target/release/zeroclaw}"
GATEWAY_HOST="${ZEROCLAW_GATEWAY_HOST:-127.0.0.1}"
GATEWAY_PORT="${ZEROCLAW_GATEWAY_PORT:-3000}"
FOLLOW_HOST="${ZEROCLAW_FOLLOW_HOST:-$GATEWAY_HOST}"
FOLLOW_PORT="${ZEROCLAW_FOLLOW_PORT:-8788}"
PROM_MODE="${ZEROCLAW_PROM_MODE:-auto}"
PROM_HOST="${ZEROCLAW_PROM_HOST:-127.0.0.1}"
@@ -31,7 +32,7 @@ PROM_READY_WAIT_SECS="${ZEROCLAW_PROM_READY_WAIT_SECS:-15}"
AUTO_REPAIR_ON_INVALID_TOKEN="${ZEROCLAW_AUTO_REPAIR_ON_INVALID_TOKEN:-1}"
OPENAI_CODEX_MODEL="${ZEROCLAW_OPENAI_CODEX_MODEL:-gpt-5.3-codex}"
OPENROUTER_MODEL="${ZEROCLAW_OPENROUTER_MODEL:-openrouter/auto}"
PREFER_LOCAL_AI="${ZEROCLAW_PREFER_LOCAL_AI:-0}"
PREFER_LOCAL_AI="${ZEROCLAW_PREFER_LOCAL_AI:-1}"
OLLAMA_MODEL="${ZEROCLAW_OLLAMA_MODEL:-llama3.2:1b}"
OLLAMA_AUTO_PULL="${ZEROCLAW_OLLAMA_AUTO_PULL:-0}"
OLLAMA_WARMUP="${ZEROCLAW_OLLAMA_WARMUP:-1}"
@@ -58,6 +59,7 @@ Environment overrides:
ZEROCLAW_ART_DIR
ZEROCLAW_BIN
ZEROCLAW_GATEWAY_HOST / ZEROCLAW_GATEWAY_PORT
ZEROCLAW_FOLLOW_HOST / ZEROCLAW_FOLLOW_PORT
ZEROCLAW_FOLLOW_PORT
ZEROCLAW_PROM_MODE
USAGE
@@ -148,7 +150,7 @@ ensure_preferred_provider_config() {
sleep 1
fi
if ! ollama list >/dev/null 2>&1; then
nohup ollama serve >"$ART_DIR/ollama.log" 2>&1 &
start_detached "$ART_DIR/ollama.log" ollama serve >/dev/null
sleep 1
fi
fi
@@ -379,6 +381,19 @@ listener_pid_on_port() {
lsof -nP -iTCP:"$port" -sTCP:LISTEN -t 2>/dev/null | head -n 1
}
start_detached() {
local log_file="$1"
shift
if command -v setsid >/dev/null 2>&1; then
nohup setsid "$@" >>"$log_file" 2>&1 < /dev/null &
else
nohup "$@" >>"$log_file" 2>&1 < /dev/null &
fi
local pid="$!"
disown "$pid" >/dev/null 2>&1 || true
printf '%s\n' "$pid"
}
ensure_docker_daemon() {
if ! command -v docker >/dev/null 2>&1; then
return 1
@@ -662,8 +677,7 @@ ensure_gateway_pairing() {
fi
fi
nohup "$ZEROCLAW_BIN" gateway --port "$GATEWAY_PORT" --host "$GATEWAY_HOST" >"$GW_LOG" 2>&1 &
echo "$!" >"$GW_PID_FILE"
start_detached "$GW_LOG" "$ZEROCLAW_BIN" gateway --port "$GATEWAY_PORT" --host "$GATEWAY_HOST" >"$GW_PID_FILE"
wait_for_gateway_health || true
for _ in $(seq 1 40); do
@@ -690,8 +704,7 @@ elif [[ -n "$(listener_pid_on_port "$GATEWAY_PORT")" ]]; then
printf '%s\n' "$existing_gateway_pid" >"$GW_PID_FILE"
rm -f "$GW_MANAGED_FILE"
else
nohup "$ZEROCLAW_BIN" gateway --port "$GATEWAY_PORT" --host "$GATEWAY_HOST" >"$GW_LOG" 2>&1 &
echo "$!" >"$GW_PID_FILE"
start_detached "$GW_LOG" "$ZEROCLAW_BIN" gateway --port "$GATEWAY_PORT" --host "$GATEWAY_HOST" >"$GW_PID_FILE"
printf '%s\n' "1" >"$GW_MANAGED_FILE"
fi
@@ -704,18 +717,16 @@ elif [[ -n "$(listener_pid_on_port "$FOLLOW_PORT")" ]]; then
rm -f "$FW_MANAGED_FILE"
else
if [[ -f "$ORCHESTRATOR_SERVER" ]]; then
nohup python3 "$ORCHESTRATOR_SERVER" \
--host 127.0.0.1 \
start_detached "$FW_LOG" python3 "$ORCHESTRATOR_SERVER" \
--host "$FOLLOW_HOST" \
--port "$FOLLOW_PORT" \
--directory "$ART_DIR" \
--root-dir "$ROOT_DIR" \
--gateway-url "http://$GATEWAY_HOST:$GATEWAY_PORT" \
--prom-url "http://$PROM_HOST:$PROM_PORT" \
>"$FW_LOG" 2>&1 &
--prom-url "http://$PROM_HOST:$PROM_PORT" >"$FW_PID_FILE"
else
nohup python3 -m http.server "$FOLLOW_PORT" --bind 127.0.0.1 --directory "$ART_DIR" >"$FW_LOG" 2>&1 &
start_detached "$FW_LOG" python3 -m http.server "$FOLLOW_PORT" --bind "$FOLLOW_HOST" --directory "$ART_DIR" >"$FW_PID_FILE"
fi
echo "$!" >"$FW_PID_FILE"
printf '%s\n' "1" >"$FW_MANAGED_FILE"
fi
@@ -2287,9 +2298,9 @@ if [[ -x "$WATCHER_SCRIPT" ]]; then
fi
echo "Gateway: http://$GATEWAY_HOST:$GATEWAY_PORT/health"
echo "Follow : http://127.0.0.1:$FOLLOW_PORT/"
echo "Follow : http://$FOLLOW_HOST:$FOLLOW_PORT/"
echo "Prom : http://$PROM_HOST:$PROM_PORT/targets ($PROM_STATUS)"
echo "RT 1m : http://127.0.0.1:$FOLLOW_PORT/realtime_1min.log"
echo "RT 1m : http://$FOLLOW_HOST:$FOLLOW_PORT/realtime_1min.log"
echo "Logs : $GW_LOG"
echo "Token : $TOKEN_FILE"
if [[ ! -s "$TOKEN_FILE" ]]; then