c08b09dc9f
Assisted-by: Codex
68 lines
2.5 KiB
Python
68 lines
2.5 KiB
Python
"""Supervise sidecar provisioning inside a running smolmachines
|
|
bottle (PRD 0023 chunk 4d; PRD 0013 supervise plane).
|
|
|
|
Registers the per-bottle supervise sidecar as an HTTP MCP server
|
|
in the agent's claude-code config so the agent discovers the
|
|
stuck-recovery MCP tools (pipelock-block, capability-block) at
|
|
startup.
|
|
|
|
Mirrors `backend.docker.provision.supervise` — same `claude mcp
|
|
add` call, just dispatched via `smolvm machine exec` instead of
|
|
`docker exec`, and against `<bundle_ip>:<port>` instead of the
|
|
short `supervise` alias (no DNS in the TSI-allowlisted guest)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from ....log import info, warn
|
|
from .. import smolvm as _smolvm
|
|
from ..bottle_plan import SmolmachinesBottlePlan
|
|
|
|
|
|
_SUPERVISE_MCP_NAME = "supervise"
|
|
|
|
|
|
def provision_supervise(plan: SmolmachinesBottlePlan, target: str) -> None:
|
|
"""Run `claude mcp add` inside the guest to register the
|
|
supervise sidecar in claude-code's user config. No-op when
|
|
bottle.supervise is False.
|
|
|
|
The URL is the agent-side endpoint launch.py populated after
|
|
bundle bringup — `http://127.0.0.1:<host port>/` rather than
|
|
the bundle's docker bridge IP, because that bridge isn't
|
|
reachable from the smolvm guest on macOS.
|
|
|
|
Failure is logged but not fatal: the bottle still works (you
|
|
just can't call supervise tools from the agent until the entry
|
|
is added manually). The operator sees the warning at launch."""
|
|
if plan.supervise_plan is None:
|
|
return
|
|
url = plan.agent_supervise_url
|
|
info(f"registering supervise MCP server in agent claude config → {url}")
|
|
# `claude mcp add --scope user` writes to ~/.claude.json. The
|
|
# agent is the `node` user; smolvm machine_exec runs as root
|
|
# by default, so we have to switch user explicitly and set
|
|
# HOME so the config lands in /home/node/.claude.json (where
|
|
# the agent's claude actually reads it from).
|
|
r = _smolvm.machine_exec(
|
|
target,
|
|
[
|
|
"runuser", "-u", "node", "--",
|
|
"env", "HOME=/home/node",
|
|
"claude", "mcp", "add",
|
|
"--scope", "user",
|
|
"--transport", "http",
|
|
_SUPERVISE_MCP_NAME,
|
|
url,
|
|
],
|
|
)
|
|
if r.returncode != 0:
|
|
warn(
|
|
f"`claude mcp add supervise` failed (exit {r.returncode}): "
|
|
f"{(r.stderr or r.stdout or '').strip()}. Inside the bottle, "
|
|
f"register manually with: "
|
|
f"claude mcp add --scope user --transport http supervise {url}"
|
|
)
|
|
|
|
|
|
__all__ = ["provision_supervise"]
|