refactor(pipelock): prepare_proxy returns a ProxyPlan

Add a frozen ProxyPlan dataclass to pipelock.py (currently one field:
yaml_path; kept as a class so future proxy-level state has a home).

  - prepare_proxy(spec, stage_dir) now returns pipelock.ProxyPlan
    instead of a raw Path.
  - DockerBottlePlan replaces pipelock_yaml_path + pipelock_yaml_filename
    with a single proxy: ProxyPlan field.
  - launch reads plan.proxy.yaml_path.parent / .name when calling
    pipelock_start. Eventually pipelock_start should just take a Path
    but that's a separate change.
This commit is contained in:
2026-05-11 01:26:38 -04:00
parent 1b8d3bbb94
commit c2cdb7777d
3 changed files with 21 additions and 11 deletions
+9 -9
View File
@@ -101,7 +101,7 @@ class DockerBottleBackend(BottleBackend):
prompt_file.write_text("") prompt_file.write_text("")
prompt_file.chmod(0o600) prompt_file.chmod(0o600)
pipelock_yaml = self.prepare_proxy(spec, stage_dir) proxy_plan = self.prepare_proxy(spec, stage_dir)
env_resolve(manifest, spec.agent_name, env_file, args_file) env_resolve(manifest, spec.agent_name, env_file, args_file)
prompt_file.write_text(agent.prompt) prompt_file.write_text(agent.prompt)
@@ -120,20 +120,20 @@ class DockerBottleBackend(BottleBackend):
env_file=env_file, env_file=env_file,
args_file=args_file, args_file=args_file,
prompt_file=prompt_file, prompt_file=prompt_file,
pipelock_yaml_path=pipelock_yaml, proxy_plan=proxy_plan,
pipelock_yaml_filename=pipelock_yaml.name,
allowlist_summary=allowlist_summary, allowlist_summary=allowlist_summary,
use_runsc=use_runsc, use_runsc=use_runsc,
) )
def prepare_proxy(self, spec: BottleSpec, stage_dir: Path) -> Path: def prepare_proxy(self, spec: BottleSpec, stage_dir: Path) -> pipelock.ProxyPlan:
"""Decide where the pipelock yaml lives in `stage_dir`, delegate """Decide where the pipelock yaml lives in `stage_dir`, delegate
to PipelockProxy to write it, and return the resolved path. to PipelockProxy to write it, and return the resolved ProxyPlan
Stage-only: no Docker resources created yet.""" for the launch step to consume. Stage-only: no Docker resources
created yet."""
yaml_path = stage_dir / "pipelock.yaml" yaml_path = stage_dir / "pipelock.yaml"
bottle_name = spec.manifest.agents[spec.agent_name].bottle bottle_name = spec.manifest.agents[spec.agent_name].bottle
self._proxy.prepare(spec.manifest, bottle_name, yaml_path) self._proxy.prepare(spec.manifest, bottle_name, yaml_path)
return yaml_path return pipelock.ProxyPlan(yaml_path=yaml_path)
@contextmanager @contextmanager
def launch(self, plan: BottlePlan) -> Iterator[DockerBottle]: def launch(self, plan: BottlePlan) -> Iterator[DockerBottle]:
@@ -186,8 +186,8 @@ class DockerBottleBackend(BottleBackend):
plan.slug, plan.slug,
state["internal_network"], state["internal_network"],
state["egress_network"], state["egress_network"],
plan.stage_dir, plan.proxy_plan.yaml_path.parent,
plan.pipelock_yaml_filename, plan.proxy_plan.yaml_path.name,
) )
container = self._run_agent_container(plan, state["internal_network"]) container = self._run_agent_container(plan, state["internal_network"])
+2 -2
View File
@@ -12,6 +12,7 @@ from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from ...log import info from ...log import info
from ...pipelock import ProxyPlan
from .. import BottlePlan from .. import BottlePlan
@@ -30,8 +31,7 @@ class DockerBottlePlan(BottlePlan):
env_file: Path env_file: Path
args_file: Path args_file: Path
prompt_file: Path prompt_file: Path
pipelock_yaml_path: Path proxy_plan: ProxyPlan
pipelock_yaml_filename: str
allowlist_summary: str allowlist_summary: str
use_runsc: bool use_runsc: bool
+10
View File
@@ -15,6 +15,7 @@ from __future__ import annotations
import os import os
import re import re
import subprocess import subprocess
from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from .log import die, info, warn from .log import die, info, warn
@@ -123,6 +124,15 @@ def pipelock_allowlist_summary(manifest: Manifest, bottle_name: str) -> str:
# --- Proxy class ----------------------------------------------------------- # --- Proxy class -----------------------------------------------------------
@dataclass(frozen=True)
class ProxyPlan:
"""Output of a proxy's prepare step; consumed by launch when the
proxy needs to be brought up. Currently single-field (the on-host
yaml path); kept as a dataclass so future proxy state has a home."""
yaml_path: Path
class PipelockProxy: class PipelockProxy:
"""The pipelock egress proxy. Encapsulates the YAML-config """The pipelock egress proxy. Encapsulates the YAML-config
generation (and is the natural home for any future proxy-level generation (and is the natural home for any future proxy-level