diff --git a/bot_bottle/backend/docker/bottle.py b/bot_bottle/backend/docker/bottle.py index 7c94c40..86d2e3a 100644 --- a/bot_bottle/backend/docker/bottle.py +++ b/bot_bottle/backend/docker/bottle.py @@ -23,7 +23,7 @@ class DockerBottle(Bottle): ): self.name = container self._teardown = teardown - self._prompt_path = prompt_path_in_container + self.prompt_path = prompt_path_in_container self._agent_prompt_mode = agent_prompt_mode self.agent_command = agent_command self.agent_provider_template = ( @@ -36,7 +36,7 @@ class DockerBottle(Bottle): ) -> list[str]: full_argv = list(argv) full_argv.extend( - prompt_args(self._agent_prompt_mode, self._prompt_path, argv=full_argv) + prompt_args(self._agent_prompt_mode, self.prompt_path, argv=full_argv) ) cmd = ["docker", "exec"] if tty: diff --git a/bot_bottle/backend/docker/launch.py b/bot_bottle/backend/docker/launch.py index 6bc92df..f7872a9 100644 --- a/bot_bottle/backend/docker/launch.py +++ b/bot_bottle/backend/docker/launch.py @@ -80,7 +80,7 @@ _REPO_DIR = str(Path(__file__).resolve().parent.parent.parent.parent) def launch( plan: DockerBottlePlan, *, - provision: Callable[[DockerBottlePlan, str], str | None], + provision: Callable[[DockerBottlePlan, "DockerBottle"], str | None], ) -> Generator[DockerBottle, None, None]: """Build, launch, and provision a Docker bottle via compose. Teardown on exit.""" @@ -218,7 +218,7 @@ def launch( agent_command=plan.agent_command, agent_prompt_mode=plan.agent_prompt_mode, ) - bottle._prompt_path = provision(plan, bottle) + bottle.prompt_path = provision(plan, bottle) # Step 9: yield. exec_agent continues to use `docker exec -it` # — the agent runs `sleep infinity` per the renderer's diff --git a/bot_bottle/backend/smolmachines/bottle.py b/bot_bottle/backend/smolmachines/bottle.py index 2553cb2..3f9c22b 100644 --- a/bot_bottle/backend/smolmachines/bottle.py +++ b/bot_bottle/backend/smolmachines/bottle.py @@ -72,7 +72,7 @@ class SmolmachinesBottle(Bottle): # In-VM path to the agent's prompt file. None when the # agent declared no prompt (file still exists; we just # don't pass --append-system-prompt-file). - self._prompt_path = prompt_path + self.prompt_path = prompt_path # Env vars the agent process needs (HTTPS_PROXY, # CLAUDE_CODE_OAUTH_TOKEN, manifest-declared bottle env, …). # Forwarded on every `smolvm machine exec` via `-e K=V` @@ -93,7 +93,7 @@ class SmolmachinesBottle(Bottle): agent_tail = ["env", *_env_assignments_for("node", self._guest_env), self.agent_command] provider_prompt_args = prompt_args( - self._agent_prompt_mode, self._prompt_path, argv=argv, + self._agent_prompt_mode, self.prompt_path, argv=argv, ) if self._agent_prompt_mode == "read_prompt_file": agent_tail += argv diff --git a/bot_bottle/backend/smolmachines/launch.py b/bot_bottle/backend/smolmachines/launch.py index e324d3f..c006dd4 100644 --- a/bot_bottle/backend/smolmachines/launch.py +++ b/bot_bottle/backend/smolmachines/launch.py @@ -89,7 +89,7 @@ _SUPERVISE_PORT = SUPERVISE_PORT def launch( plan: SmolmachinesBottlePlan, *, - provision: Callable[[SmolmachinesBottlePlan, str], str | None], + provision: Callable[[SmolmachinesBottlePlan, "SmolmachinesBottle"], str | None], ) -> Generator[SmolmachinesBottle, None, None]: """Build + run the bottle and yield a handle; tear everything down on exit. Errors during bringup unwind any partial state @@ -120,7 +120,7 @@ def launch( agent_command=plan.agent_command, agent_prompt_mode=plan.agent_prompt_mode, ) - bottle._prompt_path = provision(plan, bottle) + bottle.prompt_path = provision(plan, bottle) yield bottle finally: diff --git a/bot_bottle/backend/smolmachines/local_registry.py b/bot_bottle/backend/smolmachines/local_registry.py index 06d3ba5..21b9b96 100644 --- a/bot_bottle/backend/smolmachines/local_registry.py +++ b/bot_bottle/backend/smolmachines/local_registry.py @@ -42,7 +42,7 @@ import time import uuid from contextlib import contextmanager from dataclasses import dataclass -from typing import Iterator +from typing import Generator, Iterator from ...log import die @@ -98,7 +98,7 @@ class RegistryHandle: @contextmanager -def ephemeral_registry() -> Iterator[RegistryHandle]: +def ephemeral_registry() -> Generator[RegistryHandle, None, None]: """Bring up a per-session docker network + a `registry:2.8.3` container on it (published on a random host port), yield a `RegistryHandle`, force-remove both on exit. diff --git a/bot_bottle/backend/smolmachines/pty_resize.py b/bot_bottle/backend/smolmachines/pty_resize.py index 311836b..2a5ab39 100644 --- a/bot_bottle/backend/smolmachines/pty_resize.py +++ b/bot_bottle/backend/smolmachines/pty_resize.py @@ -123,7 +123,7 @@ def main(argv: list[str]) -> int: machine = argv[0] inner = argv[2:] - def sync(*_args) -> None: + def sync(*_args: int) -> None: size = _read_winsize() if size is None: return diff --git a/bot_bottle/workspace.py b/bot_bottle/workspace.py index a762175..670a6e2 100644 --- a/bot_bottle/workspace.py +++ b/bot_bottle/workspace.py @@ -13,8 +13,15 @@ DEFAULT_WORKSPACE_MODE = "755" class WorkspaceSpec(Protocol): - copy_cwd: bool - user_cwd: str + @property + def copy_cwd(self) -> bool: + """Whether to copy the current working directory.""" + ... + + @property + def user_cwd(self) -> str: + """The user's current working directory.""" + ... @dataclass(frozen=True)