refactor(types): move loaded manifest from BottleSpec to BottlePlan
test / integration (pull_request) Successful in 21s
test / unit (pull_request) Successful in 49s
lint / lint (push) Successful in 2m15s
test / unit (push) Successful in 56s
test / integration (push) Successful in 27s
Update Quality Badges / update-badges (push) Successful in 2m37s
test / integration (pull_request) Successful in 21s
test / unit (pull_request) Successful in 49s
lint / lint (push) Successful in 2m15s
test / unit (push) Successful in 56s
test / integration (push) Successful in 27s
Update Quality Badges / update-badges (push) Successful in 2m37s
BottleSpec.manifest was ManifestIndex | Manifest — a union encoding two lifecycle stages in one field. The union was unjustifiable: it forced a type-narrowing workaround (loaded_manifest property) on every consumer. Clean split: - BottleSpec.manifest: ManifestIndex (always; CLI-supplied intent) - BottlePlan.manifest: Manifest (always; loaded by _validate()) _validate() returns the loaded Manifest directly. prepare() passes it to _resolve_plan(), which stores it on the plan. All provisioner code now reads plan.manifest.agent / plan.manifest.bottle — no union, no asserts, no type: ignore.
This commit was merged in pull request #239.
This commit is contained in:
@@ -240,7 +240,7 @@ class AgentProvider(ABC):
|
|||||||
BottleBackend.provision_workspace against the running bottle."""
|
BottleBackend.provision_workspace against the running bottle."""
|
||||||
from .log import info
|
from .log import info
|
||||||
|
|
||||||
manifest_bottle = plan.spec.loaded_manifest.bottle
|
manifest_bottle = plan.manifest.bottle
|
||||||
if manifest_bottle.git:
|
if manifest_bottle.git:
|
||||||
from .git_gate import GIT_GATE_HOSTNAME, git_gate_render_gitconfig
|
from .git_gate import GIT_GATE_HOSTNAME, git_gate_render_gitconfig
|
||||||
gate_host = getattr(plan, "git_gate_insteadof_host", GIT_GATE_HOSTNAME)
|
gate_host = getattr(plan, "git_gate_insteadof_host", GIT_GATE_HOSTNAME)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import shlex
|
|||||||
import sys
|
import sys
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from contextlib import AbstractContextManager
|
from contextlib import AbstractContextManager
|
||||||
from dataclasses import dataclass, replace
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Generic, Sequence, TypeVar
|
from typing import Any, Generic, Sequence, TypeVar
|
||||||
|
|
||||||
@@ -61,17 +61,10 @@ class BottleSpec:
|
|||||||
Resolved values (image names, container name, scratch paths, runsc
|
Resolved values (image names, container name, scratch paths, runsc
|
||||||
availability) live on the plan, not the spec."""
|
availability) live on the plan, not the spec."""
|
||||||
|
|
||||||
manifest: ManifestIndex | Manifest
|
manifest: ManifestIndex
|
||||||
agent_name: str
|
agent_name: str
|
||||||
copy_cwd: bool
|
copy_cwd: bool
|
||||||
user_cwd: str
|
user_cwd: str
|
||||||
|
|
||||||
@property
|
|
||||||
def loaded_manifest(self) -> Manifest:
|
|
||||||
assert isinstance(self.manifest, Manifest), (
|
|
||||||
"spec.manifest is still a ManifestIndex — call _validate() first"
|
|
||||||
)
|
|
||||||
return self.manifest
|
|
||||||
# PRD 0016 follow-up: when set, the backend's prepare step uses
|
# PRD 0016 follow-up: when set, the backend's prepare step uses
|
||||||
# this identity instead of minting a fresh one — the resume path
|
# this identity instead of minting a fresh one — the resume path
|
||||||
# (`cli.py resume <identity>`) sets this to continue an existing
|
# (`cli.py resume <identity>`) sets this to continue an existing
|
||||||
@@ -87,6 +80,7 @@ class BottlePlan(ABC):
|
|||||||
(e.g. DockerBottlePlan) add backend-specific resolved fields."""
|
(e.g. DockerBottlePlan) add backend-specific resolved fields."""
|
||||||
|
|
||||||
spec: BottleSpec
|
spec: BottleSpec
|
||||||
|
manifest: Manifest
|
||||||
stage_dir: Path
|
stage_dir: Path
|
||||||
git_gate_plan: GitGatePlan
|
git_gate_plan: GitGatePlan
|
||||||
|
|
||||||
@@ -119,7 +113,7 @@ class BottlePlan(ABC):
|
|||||||
"""Render the y/N preflight summary to stderr."""
|
"""Render the y/N preflight summary to stderr."""
|
||||||
del remote_control
|
del remote_control
|
||||||
spec = self.spec
|
spec = self.spec
|
||||||
manifest = spec.loaded_manifest
|
manifest = self.manifest
|
||||||
agent = manifest.agent
|
agent = manifest.agent
|
||||||
bottle = manifest.bottle
|
bottle = manifest.bottle
|
||||||
|
|
||||||
@@ -296,11 +290,10 @@ class BottleBackend(ABC, Generic[PlanT, CleanupT]):
|
|||||||
write_launch_metadata,
|
write_launch_metadata,
|
||||||
)
|
)
|
||||||
|
|
||||||
spec = self._validate(spec)
|
manifest = self._validate(spec)
|
||||||
|
|
||||||
self._preflight()
|
self._preflight()
|
||||||
|
|
||||||
manifest = spec.loaded_manifest
|
|
||||||
manifest_bottle = manifest.bottle
|
manifest_bottle = manifest.bottle
|
||||||
manifest_agent_provider = manifest_bottle.agent_provider
|
manifest_agent_provider = manifest_bottle.agent_provider
|
||||||
agent_provider = get_provider(manifest_agent_provider.template)
|
agent_provider = get_provider(manifest_agent_provider.template)
|
||||||
@@ -320,7 +313,7 @@ class BottleBackend(ABC, Generic[PlanT, CleanupT]):
|
|||||||
else:
|
else:
|
||||||
agent_dockerfile_path = str(agent_provider.dockerfile)
|
agent_dockerfile_path = str(agent_provider.dockerfile)
|
||||||
|
|
||||||
agent_dir, prompt_file = prepare_agent_state_dir(slug, spec)
|
agent_dir, prompt_file = prepare_agent_state_dir(slug, manifest)
|
||||||
|
|
||||||
agent_provision_plan = build_agent_provision_plan(
|
agent_provision_plan = build_agent_provision_plan(
|
||||||
template=manifest_agent_provider.template,
|
template=manifest_agent_provider.template,
|
||||||
@@ -344,6 +337,7 @@ class BottleBackend(ABC, Generic[PlanT, CleanupT]):
|
|||||||
|
|
||||||
return self._resolve_plan(
|
return self._resolve_plan(
|
||||||
spec,
|
spec,
|
||||||
|
manifest=manifest,
|
||||||
slug=slug,
|
slug=slug,
|
||||||
resolved_env=resolved_env,
|
resolved_env=resolved_env,
|
||||||
agent_provision_plan=agent_provision_plan,
|
agent_provision_plan=agent_provision_plan,
|
||||||
@@ -362,24 +356,18 @@ class BottleBackend(ABC, Generic[PlanT, CleanupT]):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _validate(self, spec: BottleSpec) -> BottleSpec:
|
def _validate(self, spec: BottleSpec) -> Manifest:
|
||||||
"""Cross-backend pre-launch checks. Parses the selected agent and
|
"""Cross-backend pre-launch checks. Parses the selected agent and
|
||||||
its bottle (raising ManifestError on invalid content), confirms
|
its bottle (raising ManifestError on invalid content), confirms
|
||||||
skills are present on the host, and every git IdentityFile resolves.
|
skills are present on the host, and every git IdentityFile resolves.
|
||||||
|
|
||||||
Returns a new BottleSpec whose manifest is fully loaded for the
|
Returns the loaded Manifest for the selected agent. Subclasses with
|
||||||
selected agent. Subclasses with additional preconditions should
|
additional preconditions should override and call
|
||||||
override and call `super()._validate(spec)` first, using the
|
`super()._validate(spec)` first."""
|
||||||
returned spec for further checks."""
|
|
||||||
assert isinstance(spec.manifest, ManifestIndex), (
|
|
||||||
"_validate() called on a spec whose manifest is already loaded"
|
|
||||||
)
|
|
||||||
manifest = spec.manifest.load_for_agent(spec.agent_name)
|
manifest = spec.manifest.load_for_agent(spec.agent_name)
|
||||||
spec = replace(spec, manifest=manifest)
|
self._validate_skills(manifest.agent.skills)
|
||||||
agent = manifest.agent
|
self._validate_agent_provider_dockerfile(spec, manifest)
|
||||||
self._validate_skills(agent.skills)
|
return manifest
|
||||||
self._validate_agent_provider_dockerfile(spec)
|
|
||||||
return spec
|
|
||||||
|
|
||||||
def _validate_skills(self, skills: Sequence[str]) -> None:
|
def _validate_skills(self, skills: Sequence[str]) -> None:
|
||||||
"""Each named skill must be a directory under the host's
|
"""Each named skill must be a directory under the host's
|
||||||
@@ -393,8 +381,7 @@ class BottleBackend(ABC, Generic[PlanT, CleanupT]):
|
|||||||
f"Create it under ~/.claude/skills/, then re-run."
|
f"Create it under ~/.claude/skills/, then re-run."
|
||||||
)
|
)
|
||||||
|
|
||||||
def _validate_agent_provider_dockerfile(self, spec: BottleSpec) -> None:
|
def _validate_agent_provider_dockerfile(self, spec: BottleSpec, manifest: Manifest) -> None:
|
||||||
manifest = spec.loaded_manifest
|
|
||||||
bottle = manifest.bottle
|
bottle = manifest.bottle
|
||||||
dockerfile = bottle.agent_provider.dockerfile
|
dockerfile = bottle.agent_provider.dockerfile
|
||||||
if not dockerfile:
|
if not dockerfile:
|
||||||
@@ -412,6 +399,7 @@ class BottleBackend(ABC, Generic[PlanT, CleanupT]):
|
|||||||
def _resolve_plan(self,
|
def _resolve_plan(self,
|
||||||
spec: BottleSpec,
|
spec: BottleSpec,
|
||||||
*,
|
*,
|
||||||
|
manifest: Manifest,
|
||||||
slug: str,
|
slug: str,
|
||||||
resolved_env: ResolvedEnv,
|
resolved_env: ResolvedEnv,
|
||||||
agent_provision_plan: AgentProvisionPlan,
|
agent_provision_plan: AgentProvisionPlan,
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ from ...egress import EgressPlan
|
|||||||
from ...env import ResolvedEnv
|
from ...env import ResolvedEnv
|
||||||
from ...git_gate import GitGatePlan
|
from ...git_gate import GitGatePlan
|
||||||
from ...supervise import SupervisePlan
|
from ...supervise import SupervisePlan
|
||||||
|
from ...manifest import Manifest
|
||||||
from .. import ActiveAgent, BottleBackend, BottleSpec
|
from .. import ActiveAgent, BottleBackend, BottleSpec
|
||||||
from . import cleanup as _cleanup
|
from . import cleanup as _cleanup
|
||||||
from . import enumerate as _enumerate
|
from . import enumerate as _enumerate
|
||||||
@@ -63,6 +64,7 @@ class DockerBottleBackend(BottleBackend["DockerBottlePlan", "DockerBottleCleanup
|
|||||||
self,
|
self,
|
||||||
spec: BottleSpec,
|
spec: BottleSpec,
|
||||||
*,
|
*,
|
||||||
|
manifest: Manifest,
|
||||||
slug: str,
|
slug: str,
|
||||||
resolved_env: ResolvedEnv,
|
resolved_env: ResolvedEnv,
|
||||||
agent_provision_plan: AgentProvisionPlan,
|
agent_provision_plan: AgentProvisionPlan,
|
||||||
@@ -73,6 +75,7 @@ class DockerBottleBackend(BottleBackend["DockerBottlePlan", "DockerBottleCleanup
|
|||||||
) -> DockerBottlePlan:
|
) -> DockerBottlePlan:
|
||||||
return _resolve_plan.resolve_plan(
|
return _resolve_plan.resolve_plan(
|
||||||
spec,
|
spec,
|
||||||
|
manifest=manifest,
|
||||||
slug=slug,
|
slug=slug,
|
||||||
resolved_env=resolved_env,
|
resolved_env=resolved_env,
|
||||||
agent_provision_plan=agent_provision_plan,
|
agent_provision_plan=agent_provision_plan,
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ def launch(
|
|||||||
Teardown on exit."""
|
Teardown on exit."""
|
||||||
stack = ExitStack()
|
stack = ExitStack()
|
||||||
|
|
||||||
_bottle_for_revoke = plan.spec.loaded_manifest.bottle
|
_bottle_for_revoke = plan.manifest.bottle
|
||||||
_git_gate_dir_for_revoke = git_gate_state_dir(plan.slug)
|
_git_gate_dir_for_revoke = git_gate_state_dir(plan.slug)
|
||||||
|
|
||||||
def teardown() -> None:
|
def teardown() -> None:
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ from .. import BottleSpec
|
|||||||
from ...env import ResolvedEnv
|
from ...env import ResolvedEnv
|
||||||
from ...agent_provider import AgentProvisionPlan
|
from ...agent_provider import AgentProvisionPlan
|
||||||
from ...egress import EgressPlan
|
from ...egress import EgressPlan
|
||||||
|
from ...manifest import Manifest
|
||||||
from ...supervise import SupervisePlan
|
from ...supervise import SupervisePlan
|
||||||
from ...git_gate import GitGatePlan
|
from ...git_gate import GitGatePlan
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ def build_guest_env(resolved_env: ResolvedEnv) -> dict[str, str]:
|
|||||||
|
|
||||||
def resolve_plan(
|
def resolve_plan(
|
||||||
spec: BottleSpec,
|
spec: BottleSpec,
|
||||||
|
manifest: Manifest,
|
||||||
slug: str,
|
slug: str,
|
||||||
resolved_env: ResolvedEnv,
|
resolved_env: ResolvedEnv,
|
||||||
agent_provision_plan: AgentProvisionPlan,
|
agent_provision_plan: AgentProvisionPlan,
|
||||||
@@ -48,6 +50,7 @@ def resolve_plan(
|
|||||||
|
|
||||||
return DockerBottlePlan(
|
return DockerBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=manifest,
|
||||||
stage_dir=stage_dir,
|
stage_dir=stage_dir,
|
||||||
slug=slug,
|
slug=slug,
|
||||||
forwarded_env=dict(resolved_env.forwarded),
|
forwarded_env=dict(resolved_env.forwarded),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from ...egress import EgressPlan
|
|||||||
from ...env import ResolvedEnv
|
from ...env import ResolvedEnv
|
||||||
from ...git_gate import GitGatePlan
|
from ...git_gate import GitGatePlan
|
||||||
from ...supervise import SupervisePlan
|
from ...supervise import SupervisePlan
|
||||||
|
from ...manifest import Manifest
|
||||||
from .. import ActiveAgent, BottleBackend, BottleSpec
|
from .. import ActiveAgent, BottleBackend, BottleSpec
|
||||||
from . import cleanup as _cleanup
|
from . import cleanup as _cleanup
|
||||||
from . import enumerate as _enumerate
|
from . import enumerate as _enumerate
|
||||||
@@ -45,6 +46,7 @@ class MacosContainerBottleBackend(
|
|||||||
self,
|
self,
|
||||||
spec: BottleSpec,
|
spec: BottleSpec,
|
||||||
*,
|
*,
|
||||||
|
manifest: Manifest,
|
||||||
slug: str,
|
slug: str,
|
||||||
resolved_env: ResolvedEnv,
|
resolved_env: ResolvedEnv,
|
||||||
agent_provision_plan: AgentProvisionPlan,
|
agent_provision_plan: AgentProvisionPlan,
|
||||||
@@ -55,6 +57,7 @@ class MacosContainerBottleBackend(
|
|||||||
) -> MacosContainerBottlePlan:
|
) -> MacosContainerBottlePlan:
|
||||||
return _resolve_plan.resolve_plan(
|
return _resolve_plan.resolve_plan(
|
||||||
spec,
|
spec,
|
||||||
|
manifest=manifest,
|
||||||
slug=slug,
|
slug=slug,
|
||||||
resolved_env=resolved_env,
|
resolved_env=resolved_env,
|
||||||
agent_provision_plan=agent_provision_plan,
|
agent_provision_plan=agent_provision_plan,
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ def launch(
|
|||||||
) -> Generator[MacosContainerBottle, None, None]:
|
) -> Generator[MacosContainerBottle, None, None]:
|
||||||
"""Build, run, provision, and yield an Apple Container bottle."""
|
"""Build, run, provision, and yield an Apple Container bottle."""
|
||||||
stack = ExitStack()
|
stack = ExitStack()
|
||||||
bottle_for_revoke = plan.spec.loaded_manifest.bottle
|
bottle_for_revoke = plan.manifest.bottle
|
||||||
git_gate_dir_for_revoke = git_gate_state_dir(plan.slug)
|
git_gate_dir_for_revoke = git_gate_state_dir(plan.slug)
|
||||||
|
|
||||||
def teardown() -> None:
|
def teardown() -> None:
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from ...egress import EgressPlan
|
|||||||
from ...env import ResolvedEnv
|
from ...env import ResolvedEnv
|
||||||
from ...git_gate import GitGatePlan
|
from ...git_gate import GitGatePlan
|
||||||
from ...supervise import SupervisePlan
|
from ...supervise import SupervisePlan
|
||||||
|
from ...manifest import Manifest
|
||||||
from .. import BottleSpec
|
from .. import BottleSpec
|
||||||
from . import util as container_mod
|
from . import util as container_mod
|
||||||
from .bottle_plan import MacosContainerBottlePlan
|
from .bottle_plan import MacosContainerBottlePlan
|
||||||
@@ -24,6 +25,7 @@ def build_guest_env(resolved_env: ResolvedEnv) -> dict[str, str]:
|
|||||||
|
|
||||||
def resolve_plan(
|
def resolve_plan(
|
||||||
spec: BottleSpec,
|
spec: BottleSpec,
|
||||||
|
manifest: Manifest,
|
||||||
slug: str,
|
slug: str,
|
||||||
resolved_env: ResolvedEnv,
|
resolved_env: ResolvedEnv,
|
||||||
agent_provision_plan: AgentProvisionPlan,
|
agent_provision_plan: AgentProvisionPlan,
|
||||||
@@ -34,6 +36,7 @@ def resolve_plan(
|
|||||||
) -> MacosContainerBottlePlan:
|
) -> MacosContainerBottlePlan:
|
||||||
return MacosContainerBottlePlan(
|
return MacosContainerBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=manifest,
|
||||||
stage_dir=stage_dir,
|
stage_dir=stage_dir,
|
||||||
slug=slug,
|
slug=slug,
|
||||||
forwarded_env=dict(resolved_env.forwarded),
|
forwarded_env=dict(resolved_env.forwarded),
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ from ..bottle_state import (
|
|||||||
)
|
)
|
||||||
from ..egress import Egress, EgressPlan
|
from ..egress import Egress, EgressPlan
|
||||||
from ..git_gate import GitGate, GitGatePlan
|
from ..git_gate import GitGate, GitGatePlan
|
||||||
from ..manifest import ManifestBottle
|
from ..manifest import Manifest, ManifestBottle
|
||||||
from ..supervise import Supervise, SupervisePlan
|
from ..supervise import Supervise, SupervisePlan
|
||||||
from . import BottleSpec
|
from . import BottleSpec
|
||||||
|
|
||||||
@@ -66,10 +66,10 @@ def write_launch_metadata(
|
|||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
def prepare_agent_state_dir(slug: str, spec: BottleSpec) -> tuple[Path, Path]:
|
def prepare_agent_state_dir(slug: str, manifest: Manifest) -> tuple[Path, Path]:
|
||||||
"""Create the agent state subdir, write the prompt file.
|
"""Create the agent state subdir, write the prompt file.
|
||||||
Returns (agent_dir, prompt_file)."""
|
Returns (agent_dir, prompt_file)."""
|
||||||
agent = spec.loaded_manifest.agent
|
agent = manifest.agent
|
||||||
agent_dir = agent_state_dir(slug)
|
agent_dir = agent_state_dir(slug)
|
||||||
agent_dir.mkdir(parents=True, exist_ok=True)
|
agent_dir.mkdir(parents=True, exist_ok=True)
|
||||||
prompt_file = agent_dir / "prompt.txt"
|
prompt_file = agent_dir / "prompt.txt"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ from ...egress import EgressPlan
|
|||||||
from ...env import ResolvedEnv
|
from ...env import ResolvedEnv
|
||||||
from ...git_gate import GitGatePlan
|
from ...git_gate import GitGatePlan
|
||||||
from ...supervise import SupervisePlan
|
from ...supervise import SupervisePlan
|
||||||
|
from ...manifest import Manifest
|
||||||
from .. import ActiveAgent, BottleBackend, BottleSpec
|
from .. import ActiveAgent, BottleBackend, BottleSpec
|
||||||
from . import cleanup as _cleanup
|
from . import cleanup as _cleanup
|
||||||
from . import enumerate as _enumerate
|
from . import enumerate as _enumerate
|
||||||
@@ -55,6 +56,7 @@ class SmolmachinesBottleBackend(
|
|||||||
self,
|
self,
|
||||||
spec: BottleSpec,
|
spec: BottleSpec,
|
||||||
*,
|
*,
|
||||||
|
manifest: Manifest,
|
||||||
slug: str,
|
slug: str,
|
||||||
resolved_env: ResolvedEnv,
|
resolved_env: ResolvedEnv,
|
||||||
agent_provision_plan: AgentProvisionPlan,
|
agent_provision_plan: AgentProvisionPlan,
|
||||||
@@ -65,6 +67,7 @@ class SmolmachinesBottleBackend(
|
|||||||
) -> SmolmachinesBottlePlan:
|
) -> SmolmachinesBottlePlan:
|
||||||
return _resolve_plan.resolve_plan(
|
return _resolve_plan.resolve_plan(
|
||||||
spec,
|
spec,
|
||||||
|
manifest=manifest,
|
||||||
slug=slug,
|
slug=slug,
|
||||||
resolved_env=resolved_env,
|
resolved_env=resolved_env,
|
||||||
agent_provision_plan=agent_provision_plan,
|
agent_provision_plan=agent_provision_plan,
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ def _teardown_smolmachines(
|
|||||||
except BaseException as exc: # noqa: W0718 — teardown must not fail
|
except BaseException as exc: # noqa: W0718 — teardown must not fail
|
||||||
teardown_exc = exc
|
teardown_exc = exc
|
||||||
warn(f"smolmachines teardown failed: {exc!r}")
|
warn(f"smolmachines teardown failed: {exc!r}")
|
||||||
bottle = plan.spec.loaded_manifest.bottle
|
bottle = plan.manifest.bottle
|
||||||
revoke_git_gate_provisioned_keys(bottle, git_gate_state_dir(plan.slug))
|
revoke_git_gate_provisioned_keys(bottle, git_gate_state_dir(plan.slug))
|
||||||
if teardown_exc is not None:
|
if teardown_exc is not None:
|
||||||
raise teardown_exc
|
raise teardown_exc
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from __future__ import annotations
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from .. import BottleSpec
|
from .. import BottleSpec
|
||||||
|
from ...manifest import Manifest
|
||||||
from ...env import ResolvedEnv
|
from ...env import ResolvedEnv
|
||||||
from ...agent_provider import AgentProvisionPlan
|
from ...agent_provider import AgentProvisionPlan
|
||||||
from ...egress import EgressPlan
|
from ...egress import EgressPlan
|
||||||
@@ -46,6 +47,7 @@ def build_guest_env(resolved_env: ResolvedEnv) -> dict[str, str]:
|
|||||||
|
|
||||||
def resolve_plan(
|
def resolve_plan(
|
||||||
spec: BottleSpec,
|
spec: BottleSpec,
|
||||||
|
manifest: Manifest,
|
||||||
slug: str,
|
slug: str,
|
||||||
resolved_env: ResolvedEnv,
|
resolved_env: ResolvedEnv,
|
||||||
agent_provision_plan: AgentProvisionPlan,
|
agent_provision_plan: AgentProvisionPlan,
|
||||||
@@ -67,6 +69,7 @@ def resolve_plan(
|
|||||||
|
|
||||||
return SmolmachinesBottlePlan(
|
return SmolmachinesBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=manifest,
|
||||||
stage_dir=stage_dir,
|
stage_dir=stage_dir,
|
||||||
slug=slug,
|
slug=slug,
|
||||||
bundle_subnet=subnet,
|
bundle_subnet=subnet,
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ class ClaudeAgentProvider(AgentProvider):
|
|||||||
when the agent has no skills."""
|
when the agent has no skills."""
|
||||||
from ...backend.util import host_skill_dir
|
from ...backend.util import host_skill_dir
|
||||||
|
|
||||||
agent = plan.spec.loaded_manifest.agent
|
agent = plan.manifest.agent
|
||||||
if not agent.skills:
|
if not agent.skills:
|
||||||
return
|
return
|
||||||
skills_dir = _skills_dir(plan.guest_home)
|
skills_dir = _skills_dir(plan.guest_home)
|
||||||
@@ -240,7 +240,7 @@ class ClaudeAgentProvider(AgentProvider):
|
|||||||
f"chown node:node {prompt_path} && chmod 600 {prompt_path}",
|
f"chown node:node {prompt_path} && chmod 600 {prompt_path}",
|
||||||
user="root",
|
user="root",
|
||||||
)
|
)
|
||||||
agent = plan.spec.loaded_manifest.agent
|
agent = plan.manifest.agent
|
||||||
return prompt_path if plan.agent_provision.has_prompt or agent.prompt else None
|
return prompt_path if plan.agent_provision.has_prompt or agent.prompt else None
|
||||||
|
|
||||||
def provision(self, plan: "BottlePlan", bottle: "Bottle") -> None:
|
def provision(self, plan: "BottlePlan", bottle: "Bottle") -> None:
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ class CodexAgentProvider(AgentProvider):
|
|||||||
skills."""
|
skills."""
|
||||||
from ...backend.util import host_skill_dir
|
from ...backend.util import host_skill_dir
|
||||||
|
|
||||||
agent = plan.spec.loaded_manifest.agent
|
agent = plan.manifest.agent
|
||||||
if not agent.skills:
|
if not agent.skills:
|
||||||
return
|
return
|
||||||
skills_dir = _skills_dir(plan.guest_home)
|
skills_dir = _skills_dir(plan.guest_home)
|
||||||
@@ -206,7 +206,7 @@ class CodexAgentProvider(AgentProvider):
|
|||||||
f"chown node:node {prompt_path} && chmod 600 {prompt_path}",
|
f"chown node:node {prompt_path} && chmod 600 {prompt_path}",
|
||||||
user="root",
|
user="root",
|
||||||
)
|
)
|
||||||
agent = plan.spec.loaded_manifest.agent
|
agent = plan.manifest.agent
|
||||||
return prompt_path if plan.agent_provision.has_prompt or agent.prompt else None
|
return prompt_path if plan.agent_provision.has_prompt or agent.prompt else None
|
||||||
|
|
||||||
def provision(self, plan: "BottlePlan", bottle: "Bottle") -> None:
|
def provision(self, plan: "BottlePlan", bottle: "Bottle") -> None:
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ class PiAgentProvider(AgentProvider):
|
|||||||
def provision_skills(self, plan: "BottlePlan", bottle: "Bottle") -> None:
|
def provision_skills(self, plan: "BottlePlan", bottle: "Bottle") -> None:
|
||||||
from ...backend.util import host_skill_dir
|
from ...backend.util import host_skill_dir
|
||||||
|
|
||||||
agent = plan.spec.loaded_manifest.agent
|
agent = plan.manifest.agent
|
||||||
if not agent.skills:
|
if not agent.skills:
|
||||||
return
|
return
|
||||||
skills_dir = _skills_dir(plan.guest_home)
|
skills_dir = _skills_dir(plan.guest_home)
|
||||||
|
|||||||
@@ -67,16 +67,6 @@ def _manifest(*, supervise: bool, with_git: bool, with_egress: bool) -> Manifest
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def _spec(*, supervise: bool, with_git: bool, with_egress: bool) -> BottleSpec:
|
|
||||||
return BottleSpec(
|
|
||||||
manifest=_manifest(
|
|
||||||
supervise=supervise, with_git=with_git, with_egress=with_egress,
|
|
||||||
),
|
|
||||||
agent_name="demo",
|
|
||||||
copy_cwd=False,
|
|
||||||
user_cwd="/tmp/x",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _git_gate_plan(upstreams: tuple[GitGateUpstream, ...] = ()) -> GitGatePlan:
|
def _git_gate_plan(upstreams: tuple[GitGateUpstream, ...] = ()) -> GitGatePlan:
|
||||||
return GitGatePlan(
|
return GitGatePlan(
|
||||||
@@ -146,9 +136,16 @@ def _plan(
|
|||||||
roles=(),
|
roles=(),
|
||||||
),)
|
),)
|
||||||
|
|
||||||
spec = _spec(supervise=supervise, with_git=with_git, with_egress=with_egress)
|
index = _manifest(supervise=supervise, with_git=with_git, with_egress=with_egress)
|
||||||
|
spec = BottleSpec(
|
||||||
|
manifest=index,
|
||||||
|
agent_name="demo",
|
||||||
|
copy_cwd=False,
|
||||||
|
user_cwd="/tmp/x",
|
||||||
|
)
|
||||||
return DockerBottlePlan(
|
return DockerBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=index.load_for_agent("demo"),
|
||||||
stage_dir=STAGE,
|
stage_dir=STAGE,
|
||||||
slug=SLUG,
|
slug=SLUG,
|
||||||
forwarded_env={"CLAUDE_CODE_OAUTH_TOKEN": "x"},
|
forwarded_env={"CLAUDE_CODE_OAUTH_TOKEN": "x"},
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ def _plan(
|
|||||||
bottle_json: dict = {"agent_provider": {"template": "claude"}} # type: ignore
|
bottle_json: dict = {"agent_provider": {"template": "claude"}} # type: ignore
|
||||||
if supervise:
|
if supervise:
|
||||||
bottle_json["supervise"] = True
|
bottle_json["supervise"] = True
|
||||||
manifest = ManifestIndex.from_json_obj({
|
index = ManifestIndex.from_json_obj({
|
||||||
"bottles": {"dev": bottle_json},
|
"bottles": {"dev": bottle_json},
|
||||||
"agents": {
|
"agents": {
|
||||||
"demo": {
|
"demo": {
|
||||||
@@ -64,9 +64,10 @@ def _plan(
|
|||||||
"bottle": "dev",
|
"bottle": "dev",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).load_for_agent("demo")
|
})
|
||||||
|
manifest = index.load_for_agent("demo")
|
||||||
spec = BottleSpec(
|
spec = BottleSpec(
|
||||||
manifest=manifest, agent_name="demo",
|
manifest=index, agent_name="demo",
|
||||||
copy_cwd=False, user_cwd="/tmp/x",
|
copy_cwd=False, user_cwd="/tmp/x",
|
||||||
)
|
)
|
||||||
supervise_plan = None
|
supervise_plan = None
|
||||||
@@ -78,6 +79,7 @@ def _plan(
|
|||||||
)
|
)
|
||||||
return DockerBottlePlan(
|
return DockerBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=manifest,
|
||||||
stage_dir=Path("/tmp/stage"),
|
stage_dir=Path("/tmp/stage"),
|
||||||
slug="demo-abc12",
|
slug="demo-abc12",
|
||||||
forwarded_env={},
|
forwarded_env={},
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ def _plan(
|
|||||||
bottle_json: dict = {"agent_provider": {"template": "codex"}} # type: ignore
|
bottle_json: dict = {"agent_provider": {"template": "codex"}} # type: ignore
|
||||||
if supervise:
|
if supervise:
|
||||||
bottle_json["supervise"] = True
|
bottle_json["supervise"] = True
|
||||||
manifest = ManifestIndex.from_json_obj({
|
index = ManifestIndex.from_json_obj({
|
||||||
"bottles": {"dev": bottle_json},
|
"bottles": {"dev": bottle_json},
|
||||||
"agents": {
|
"agents": {
|
||||||
"demo": {
|
"demo": {
|
||||||
@@ -64,9 +64,10 @@ def _plan(
|
|||||||
"bottle": "dev",
|
"bottle": "dev",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).load_for_agent("demo")
|
})
|
||||||
|
manifest = index.load_for_agent("demo")
|
||||||
spec = BottleSpec(
|
spec = BottleSpec(
|
||||||
manifest=manifest, agent_name="demo",
|
manifest=index, agent_name="demo",
|
||||||
copy_cwd=False, user_cwd="/tmp/x",
|
copy_cwd=False, user_cwd="/tmp/x",
|
||||||
)
|
)
|
||||||
supervise_plan = None
|
supervise_plan = None
|
||||||
@@ -78,6 +79,7 @@ def _plan(
|
|||||||
)
|
)
|
||||||
return DockerBottlePlan(
|
return DockerBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=manifest,
|
||||||
stage_dir=Path("/tmp/stage"),
|
stage_dir=Path("/tmp/stage"),
|
||||||
slug="demo-abc12",
|
slug="demo-abc12",
|
||||||
forwarded_env={},
|
forwarded_env={},
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ def _plan(
|
|||||||
skills: list[str] | None = None,
|
skills: list[str] | None = None,
|
||||||
agent_provision: AgentProvisionPlan | None = None,
|
agent_provision: AgentProvisionPlan | None = None,
|
||||||
) -> DockerBottlePlan:
|
) -> DockerBottlePlan:
|
||||||
manifest = ManifestIndex.from_json_obj({
|
index = ManifestIndex.from_json_obj({
|
||||||
"bottles": {"dev": {"agent_provider": {"template": "pi"}}},
|
"bottles": {"dev": {"agent_provider": {"template": "pi"}}},
|
||||||
"agents": {
|
"agents": {
|
||||||
"demo": {
|
"demo": {
|
||||||
@@ -52,13 +52,15 @@ def _plan(
|
|||||||
"bottle": "dev",
|
"bottle": "dev",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).load_for_agent("demo")
|
})
|
||||||
|
manifest = index.load_for_agent("demo")
|
||||||
spec = BottleSpec(
|
spec = BottleSpec(
|
||||||
manifest=manifest, agent_name="demo",
|
manifest=index, agent_name="demo",
|
||||||
copy_cwd=False, user_cwd="/tmp/x",
|
copy_cwd=False, user_cwd="/tmp/x",
|
||||||
)
|
)
|
||||||
return DockerBottlePlan(
|
return DockerBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=manifest,
|
||||||
stage_dir=Path("/tmp/stage"),
|
stage_dir=Path("/tmp/stage"),
|
||||||
slug="demo-abc12",
|
slug="demo-abc12",
|
||||||
forwarded_env={},
|
forwarded_env={},
|
||||||
|
|||||||
@@ -23,22 +23,17 @@ from bot_bottle.egress import EgressPlan
|
|||||||
from bot_bottle.git_gate import GitGatePlan
|
from bot_bottle.git_gate import GitGatePlan
|
||||||
from bot_bottle.manifest import ManifestIndex
|
from bot_bottle.manifest import ManifestIndex
|
||||||
|
|
||||||
|
_INDEX = ManifestIndex.from_json_obj({
|
||||||
from bot_bottle.manifest import Manifest, ManifestIndex
|
"bottles": {"dev": {}},
|
||||||
|
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
||||||
|
})
|
||||||
def _manifest() -> Manifest:
|
|
||||||
return ManifestIndex.from_json_obj({
|
|
||||||
"bottles": {"dev": {}},
|
|
||||||
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
|
||||||
}).load_for_agent("demo")
|
|
||||||
|
|
||||||
|
|
||||||
def _plan(tmp: str) -> DockerBottlePlan:
|
def _plan(tmp: str) -> DockerBottlePlan:
|
||||||
stage = Path(tmp)
|
stage = Path(tmp)
|
||||||
manifest = _manifest()
|
manifest = _INDEX.load_for_agent("demo")
|
||||||
spec = BottleSpec(
|
spec = BottleSpec(
|
||||||
manifest=manifest,
|
manifest=_INDEX,
|
||||||
agent_name="demo",
|
agent_name="demo",
|
||||||
copy_cwd=False,
|
copy_cwd=False,
|
||||||
user_cwd=tmp,
|
user_cwd=tmp,
|
||||||
@@ -46,6 +41,7 @@ def _plan(tmp: str) -> DockerBottlePlan:
|
|||||||
)
|
)
|
||||||
return DockerBottlePlan(
|
return DockerBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=manifest,
|
||||||
stage_dir=stage,
|
stage_dir=stage,
|
||||||
git_gate_plan=GitGatePlan(
|
git_gate_plan=GitGatePlan(
|
||||||
slug="test-teardown-00001",
|
slug="test-teardown-00001",
|
||||||
|
|||||||
@@ -51,16 +51,18 @@ def _plan(*, git_user: dict | None = None, # type: ignore
|
|||||||
bottle_json: dict = {} # type: ignore
|
bottle_json: dict = {} # type: ignore
|
||||||
if git_user is not None:
|
if git_user is not None:
|
||||||
bottle_json["git-gate"] = {"user": git_user}
|
bottle_json["git-gate"] = {"user": git_user}
|
||||||
manifest = ManifestIndex.from_json_obj({
|
index = ManifestIndex.from_json_obj({
|
||||||
"bottles": {"dev": bottle_json},
|
"bottles": {"dev": bottle_json},
|
||||||
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
||||||
}).load_for_agent("demo")
|
})
|
||||||
|
manifest = index.load_for_agent("demo")
|
||||||
spec = BottleSpec(
|
spec = BottleSpec(
|
||||||
manifest=manifest, agent_name="demo",
|
manifest=index, agent_name="demo",
|
||||||
copy_cwd=copy_cwd, user_cwd=user_cwd,
|
copy_cwd=copy_cwd, user_cwd=user_cwd,
|
||||||
)
|
)
|
||||||
return DockerBottlePlan(
|
return DockerBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=manifest,
|
||||||
stage_dir=stage_dir or Path("/tmp/stage"),
|
stage_dir=stage_dir or Path("/tmp/stage"),
|
||||||
slug="demo-abc12",
|
slug="demo-abc12",
|
||||||
forwarded_env={},
|
forwarded_env={},
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
from bot_bottle.backend.macos_container import launch
|
from bot_bottle.backend.macos_container import launch
|
||||||
from bot_bottle.backend.macos_container.bottle_plan import MacosContainerBottlePlan
|
from bot_bottle.backend.macos_container.bottle_plan import MacosContainerBottlePlan
|
||||||
|
from bot_bottle.manifest import ManifestIndex
|
||||||
|
|
||||||
|
_MANIFEST = ManifestIndex.from_json_obj({
|
||||||
|
"bottles": {"dev": {}},
|
||||||
|
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
||||||
|
}).load_for_agent("demo")
|
||||||
|
|
||||||
|
|
||||||
def _plan(
|
def _plan(
|
||||||
@@ -67,6 +73,7 @@ def _plan(
|
|||||||
)
|
)
|
||||||
return cast(MacosContainerBottlePlan, SimpleNamespace(
|
return cast(MacosContainerBottlePlan, SimpleNamespace(
|
||||||
spec=SimpleNamespace(),
|
spec=SimpleNamespace(),
|
||||||
|
manifest=_MANIFEST,
|
||||||
stage_dir=stage_dir,
|
stage_dir=stage_dir,
|
||||||
slug="dev-abc",
|
slug="dev-abc",
|
||||||
container_name="bot-bottle-dev-abc",
|
container_name="bot-bottle-dev-abc",
|
||||||
@@ -193,6 +200,7 @@ class TestMacosContainerLaunchArgv(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
plan = MacosContainerBottlePlan(
|
plan = MacosContainerBottlePlan(
|
||||||
spec=base.spec,
|
spec=base.spec,
|
||||||
|
manifest=base.manifest,
|
||||||
stage_dir=base.stage_dir,
|
stage_dir=base.stage_dir,
|
||||||
git_gate_plan=base.git_gate_plan,
|
git_gate_plan=base.git_gate_plan,
|
||||||
egress_plan=base.egress_plan,
|
egress_plan=base.egress_plan,
|
||||||
|
|||||||
@@ -22,16 +22,15 @@ from bot_bottle.git_gate import GitGatePlan, GitGateUpstream
|
|||||||
from bot_bottle.manifest import Manifest, ManifestIndex
|
from bot_bottle.manifest import Manifest, ManifestIndex
|
||||||
|
|
||||||
|
|
||||||
def _manifest() -> Manifest:
|
_INDEX = ManifestIndex.from_json_obj({
|
||||||
return ManifestIndex.from_json_obj({
|
"bottles": {"dev": {}},
|
||||||
"bottles": {"dev": {}},
|
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
||||||
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
})
|
||||||
}).load_for_agent("demo")
|
|
||||||
|
|
||||||
|
|
||||||
def _spec(manifest: Manifest, tmp: str) -> BottleSpec:
|
def _spec(index: ManifestIndex, tmp: str) -> BottleSpec:
|
||||||
return BottleSpec(
|
return BottleSpec(
|
||||||
manifest=manifest,
|
manifest=index,
|
||||||
agent_name="demo",
|
agent_name="demo",
|
||||||
copy_cwd=False,
|
copy_cwd=False,
|
||||||
user_cwd=tmp,
|
user_cwd=tmp,
|
||||||
@@ -92,10 +91,11 @@ def _agent_provision(tmp: str) -> AgentProvisionPlan:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _docker_plan(spec: BottleSpec, tmp: str) -> DockerBottlePlan:
|
def _docker_plan(spec: BottleSpec, manifest: Manifest, tmp: str) -> DockerBottlePlan:
|
||||||
stage = Path(tmp)
|
stage = Path(tmp)
|
||||||
return DockerBottlePlan(
|
return DockerBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=manifest,
|
||||||
stage_dir=stage,
|
stage_dir=stage,
|
||||||
git_gate_plan=_git_gate_plan(tmp),
|
git_gate_plan=_git_gate_plan(tmp),
|
||||||
egress_plan=_egress_plan(tmp),
|
egress_plan=_egress_plan(tmp),
|
||||||
@@ -107,10 +107,11 @@ def _docker_plan(spec: BottleSpec, tmp: str) -> DockerBottlePlan:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _smolmachines_plan(spec: BottleSpec, tmp: str) -> SmolmachinesBottlePlan:
|
def _smolmachines_plan(spec: BottleSpec, manifest: Manifest, tmp: str) -> SmolmachinesBottlePlan:
|
||||||
stage = Path(tmp)
|
stage = Path(tmp)
|
||||||
return SmolmachinesBottlePlan(
|
return SmolmachinesBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=manifest,
|
||||||
stage_dir=stage,
|
stage_dir=stage,
|
||||||
git_gate_plan=_git_gate_plan(tmp),
|
git_gate_plan=_git_gate_plan(tmp),
|
||||||
egress_plan=_egress_plan(tmp),
|
egress_plan=_egress_plan(tmp),
|
||||||
@@ -140,10 +141,10 @@ class TestGitGatePrintParity(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
self._tmp = tempfile.mkdtemp(prefix="plan-print-parity-")
|
self._tmp = tempfile.mkdtemp(prefix="plan-print-parity-")
|
||||||
manifest = _manifest()
|
manifest = _INDEX.load_for_agent("demo")
|
||||||
spec = _spec(manifest, self._tmp)
|
spec = _spec(_INDEX, self._tmp)
|
||||||
self._docker_lines = _capture_print(_docker_plan(spec, self._tmp))
|
self._docker_lines = _capture_print(_docker_plan(spec, manifest, self._tmp))
|
||||||
self._smol_lines = _capture_print(_smolmachines_plan(spec, self._tmp))
|
self._smol_lines = _capture_print(_smolmachines_plan(spec, manifest, self._tmp))
|
||||||
|
|
||||||
def _git_gate_lines(self, lines: list[str]) -> list[str]:
|
def _git_gate_lines(self, lines: list[str]) -> list[str]:
|
||||||
return [ln for ln in lines if "git gate" in ln]
|
return [ln for ln in lines if "git gate" in ln]
|
||||||
@@ -170,10 +171,10 @@ class TestEgressPrintParity(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
self._tmp = tempfile.mkdtemp(prefix="plan-print-parity-")
|
self._tmp = tempfile.mkdtemp(prefix="plan-print-parity-")
|
||||||
manifest = _manifest()
|
manifest = _INDEX.load_for_agent("demo")
|
||||||
spec = _spec(manifest, self._tmp)
|
spec = _spec(_INDEX, self._tmp)
|
||||||
self._docker_lines = _capture_print(_docker_plan(spec, self._tmp))
|
self._docker_lines = _capture_print(_docker_plan(spec, manifest, self._tmp))
|
||||||
self._smol_lines = _capture_print(_smolmachines_plan(spec, self._tmp))
|
self._smol_lines = _capture_print(_smolmachines_plan(spec, manifest, self._tmp))
|
||||||
|
|
||||||
def _egress_section(self, lines: list[str]) -> list[str]:
|
def _egress_section(self, lines: list[str]) -> list[str]:
|
||||||
"""Return lines from the egress label through the last route entry.
|
"""Return lines from the egress label through the last route entry.
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ def _plan(
|
|||||||
bottle_json["git-gate"] = git_gate_json
|
bottle_json["git-gate"] = git_gate_json
|
||||||
if supervise:
|
if supervise:
|
||||||
bottle_json["supervise"] = True
|
bottle_json["supervise"] = True
|
||||||
manifest = ManifestIndex.from_json_obj({
|
index = ManifestIndex.from_json_obj({
|
||||||
"bottles": {"dev": bottle_json},
|
"bottles": {"dev": bottle_json},
|
||||||
"agents": {
|
"agents": {
|
||||||
"demo": {
|
"demo": {
|
||||||
@@ -119,9 +119,10 @@ def _plan(
|
|||||||
"bottle": "dev",
|
"bottle": "dev",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).load_for_agent("demo")
|
})
|
||||||
|
manifest = index.load_for_agent("demo")
|
||||||
spec = BottleSpec(
|
spec = BottleSpec(
|
||||||
manifest=manifest,
|
manifest=index,
|
||||||
agent_name="demo",
|
agent_name="demo",
|
||||||
copy_cwd=copy_cwd,
|
copy_cwd=copy_cwd,
|
||||||
user_cwd=user_cwd,
|
user_cwd=user_cwd,
|
||||||
@@ -135,6 +136,7 @@ def _plan(
|
|||||||
)
|
)
|
||||||
return SmolmachinesBottlePlan(
|
return SmolmachinesBottlePlan(
|
||||||
spec=spec,
|
spec=spec,
|
||||||
|
manifest=manifest,
|
||||||
stage_dir=stage_dir or Path("/tmp/stage"),
|
stage_dir=stage_dir or Path("/tmp/stage"),
|
||||||
slug="demo-abc12",
|
slug="demo-abc12",
|
||||||
bundle_subnet="192.168.50.0/24",
|
bundle_subnet="192.168.50.0/24",
|
||||||
|
|||||||
Reference in New Issue
Block a user