ac8c7ba696
End-to-end provisioning parity with the docker backend. After this
chunk a smolmachines bottle has a working trust store, git-gate
gitconfig, and supervise MCP registration — same shape as docker,
dispatched via `smolvm machine cp` / `smolvm machine exec` instead
of `docker cp` / `docker exec`.
Adds three new provision modules:
- ca.py: select egress vs pipelock CA (same logic as
docker), machine cp + update-ca-certificates,
log sha256 fingerprint.
- git.py: copy host .git when --cwd was passed; render
~/.gitconfig with insteadOf URLs. URL prefix is
`git://<bundle_ip>:9418/...` (no DNS in the
TSI-allowlisted guest) vs docker's
`git://git-gate/...`.
- supervise.py: `claude mcp add` via machine_exec; URL is
`http://<bundle_ip>:9100/`. Failure is logged but
non-fatal (matches docker).
Shared render: `render_git_gate_gitconfig` moves out of
backend/docker/provision/git.py into the platform-neutral
claude_bottle/git_gate.py (renamed to git_gate_render_gitconfig
for consistency with the existing git_gate_render_* helpers),
parameterized on a `gate_host` argument so both backends use the
same logic with different addresses.
Path/user fixups for the post-chunk-4c agent image (real
claude-bottle image, USER node, $HOME=/home/node):
- prompt.py default path moves from /root/... to
/home/node/.claude-bottle-prompt.txt; chown + chmod after
machine cp.
- skills.py default skills dir moves from /root/.claude/skills to
/home/node/.claude/skills; chown -R per skill.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
82 lines
2.5 KiB
Python
82 lines
2.5 KiB
Python
"""SmolmachinesBottleBackend — the smolmachines implementation of
|
|
BottleBackend (PRD 0023)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from contextlib import contextmanager
|
|
from pathlib import Path
|
|
from typing import Generator
|
|
|
|
from .. import BottleBackend, BottleSpec
|
|
from . import launch as _launch
|
|
from . import prepare as _prepare
|
|
from .bottle import SmolmachinesBottle
|
|
from .bottle_cleanup_plan import SmolmachinesBottleCleanupPlan
|
|
from .bottle_plan import SmolmachinesBottlePlan
|
|
from .provision import ca as _ca
|
|
from .provision import git as _git
|
|
from .provision import prompt as _prompt
|
|
from .provision import skills as _skills
|
|
from .provision import supervise as _supervise
|
|
|
|
|
|
class SmolmachinesBottleBackend(
|
|
BottleBackend["SmolmachinesBottlePlan", "SmolmachinesBottleCleanupPlan"]
|
|
):
|
|
"""smolmachines backend. Selected by
|
|
`CLAUDE_BOTTLE_BACKEND=smolmachines`."""
|
|
|
|
name = "smolmachines"
|
|
|
|
def _resolve_plan(
|
|
self, spec: BottleSpec, *, stage_dir: Path
|
|
) -> SmolmachinesBottlePlan:
|
|
return _prepare.resolve_plan(spec, stage_dir=stage_dir)
|
|
|
|
@contextmanager
|
|
def launch(
|
|
self, plan: SmolmachinesBottlePlan
|
|
) -> Generator[SmolmachinesBottle, None, None]:
|
|
with _launch.launch(plan, provision=self.provision) as bottle:
|
|
yield bottle
|
|
|
|
def provision_ca(
|
|
self, plan: SmolmachinesBottlePlan, target: str
|
|
) -> None:
|
|
_ca.provision_ca(plan, target)
|
|
|
|
def provision_prompt(
|
|
self, plan: SmolmachinesBottlePlan, target: str
|
|
) -> str | None:
|
|
return _prompt.provision_prompt(plan, target)
|
|
|
|
def provision_skills(
|
|
self, plan: SmolmachinesBottlePlan, target: str
|
|
) -> None:
|
|
_skills.provision_skills(plan, target)
|
|
|
|
def provision_git(
|
|
self, plan: SmolmachinesBottlePlan, target: str
|
|
) -> None:
|
|
_git.provision_git(plan, target)
|
|
|
|
def provision_supervise(
|
|
self, plan: SmolmachinesBottlePlan, target: str
|
|
) -> None:
|
|
_supervise.provision_supervise(plan, target)
|
|
|
|
def prepare_cleanup(self) -> SmolmachinesBottleCleanupPlan:
|
|
return SmolmachinesBottleCleanupPlan()
|
|
|
|
def cleanup(self, plan: SmolmachinesBottleCleanupPlan) -> None:
|
|
del plan
|
|
# Nothing to clean in chunks 1-3 — see
|
|
# SmolmachinesBottleCleanupPlan docstring.
|
|
|
|
def list_active(self) -> None:
|
|
from ...log import info
|
|
info(
|
|
"smolmachines list_active: not implemented (chunk 4 wires "
|
|
"it to `smolvm machine ls --json`)"
|
|
)
|