2aca9e609a
Addresses PR #62 review comments on claude_bottle/backend/smolmachines/bottle_plan.py: - Lift the multi-value label printer (was a nested helper inside DockerBottlePlan.print) into a new module claude_bottle/backend/print_util.py:print_multi. Both backends use it for env / skills / git / egress lines. - Strip the three smolmachines-preflight lines the review flagged: the gvproxy subnet line, the smolfile path line, and the gvproxy-config path line. Internal detail — operators see the agent / env / skills / bottle / git / egress that already matter on the docker side, and nothing else. - Add `git → upstream` to the smolmachines git output to match what's useful at preflight time (the docker version shows upstream_host:port; this is similar shape). Leaves the slug=spec.identity-or-mint pattern alone pending a reply on PR comment #432 — the docker backend uses the same pattern to preserve identity across `resume`, so dropping it would silently break the resume path once smolmachines launch lands. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
62 lines
2.0 KiB
Python
62 lines
2.0 KiB
Python
"""SmolmachinesBottlePlan — concrete BottlePlan for the smolmachines
|
|
backend (PRD 0023).
|
|
|
|
Chunk 1 fields: slug, smolfile_path, gvproxy_config_path, gvproxy
|
|
subnet + socket, and the per-bottle port map. VM lifecycle fields
|
|
(machine name, OCI archive path, etc.) land in later chunks as the
|
|
launch flow grows."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
|
|
from ...log import info
|
|
from .. import BottlePlan
|
|
from ..print_util import print_multi
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class SmolmachinesBottlePlan(BottlePlan):
|
|
"""Resolved fields the launch step needs to bring up the bottle.
|
|
|
|
Inherits `spec` and `stage_dir` from BottlePlan."""
|
|
|
|
slug: str
|
|
smolfile_path: Path
|
|
gvproxy_config_path: Path
|
|
gvproxy_socket: Path
|
|
gvproxy_subnet: str
|
|
gvproxy_gateway: str
|
|
# Daemon name → host-side loopback port the bundle binds.
|
|
# Always includes "pipelock"; "git-gate" and "supervise"
|
|
# conditional on the bottle's manifest.
|
|
host_port_map: dict[str, int]
|
|
|
|
def print(self, *, remote_control: bool) -> None:
|
|
"""Compact y/N preflight. Same shape as the Docker
|
|
backend's so operators see one format across backends."""
|
|
del remote_control # not surfaced in the compact summary
|
|
spec = self.spec
|
|
manifest = spec.manifest
|
|
agent = manifest.agents[spec.agent_name]
|
|
bottle = manifest.bottle_for(spec.agent_name)
|
|
|
|
env_names = sorted(bottle.env.keys())
|
|
upstreams = [
|
|
f"{g.Name} → {g.Upstream}" for g in bottle.git
|
|
]
|
|
routes = [r.host for r in bottle.egress.routes]
|
|
|
|
print(file=sys.stderr)
|
|
info(f"agent : {spec.agent_name}")
|
|
print_multi("env ", env_names)
|
|
print_multi("skills ", list(agent.skills))
|
|
info(f"bottle : {agent.bottle}")
|
|
if upstreams:
|
|
print_multi(" git gate ", upstreams)
|
|
if routes:
|
|
print_multi(" egress ", routes)
|
|
print(file=sys.stderr)
|