diff --git a/bot_bottle/cli/start.py b/bot_bottle/cli/start.py index 27bcf3a..b587216 100644 --- a/bot_bottle/cli/start.py +++ b/bot_bottle/cli/start.py @@ -380,7 +380,7 @@ def _peek_agent_bottle(manifest: ManifestIndex, agent_name: str) -> str: return manifest.agents[agent_name].bottle return "" - from ..manifest_loader import scan_agent_names + from ..manifest.loader import scan_agent_names from ..yaml_subset import YamlSubsetError, parse_frontmatter home_agents = scan_agent_names(manifest.home_md / "agents") diff --git a/bot_bottle/deploy_key_provisioner.py b/bot_bottle/deploy_key_provisioner.py index e733bc1..a6d90d5 100644 --- a/bot_bottle/deploy_key_provisioner.py +++ b/bot_bottle/deploy_key_provisioner.py @@ -49,7 +49,7 @@ def get_provisioner( GiteaDeployKeyProvisioner, ) return GiteaDeployKeyProvisioner(token=token, api_url=api_url) - from .manifest_util import ManifestError + from .manifest.util import ManifestError raise ManifestError( f"unknown provisioned_key provider: {provider!r}; " f"available: gitea" diff --git a/bot_bottle/manifest.py b/bot_bottle/manifest/__init__.py similarity index 97% rename from bot_bottle/manifest.py rename to bot_bottle/manifest/__init__.py index f8b6307..8289298 100644 --- a/bot_bottle/manifest.py +++ b/bot_bottle/manifest/__init__.py @@ -63,25 +63,25 @@ from dataclasses import dataclass, field, replace from pathlib import Path from typing import Mapping -from .log import warn -from .manifest_util import ManifestError, as_json_object -from .manifest_agent import ManifestAgent, ManifestAgentProvider -from .manifest_bottle import ManifestBottle -from .manifest_egress import ( +from ..log import warn +from .util import ManifestError, as_json_object +from .agent import ManifestAgent, ManifestAgentProvider +from .bottle import ManifestBottle +from .egress import ( EGRESS_AUTH_SCHEMES, ManifestEgressConfig, ManifestEgressRoute, ) -from .manifest_extends import merge_bottles_runtime, resolve_bottles -from .manifest_git import ManifestGitEntry, ManifestGitUser, ManifestKeyConfig -from .manifest_loader import ( +from .extends import merge_bottles_runtime, resolve_bottles +from .git import ManifestGitEntry, ManifestGitUser, ManifestKeyConfig +from .loader import ( check_stale_json, load_bottle_chain_from_dir, scan_agent_names, scan_bottle_names, ) -from .manifest_schema import validate_agent_frontmatter_keys -from .yaml_subset import YamlSubsetError, parse_frontmatter +from .schema import validate_agent_frontmatter_keys +from ..yaml_subset import YamlSubsetError, parse_frontmatter # Re-export everything that callers currently import from this module. __all__ = [ diff --git a/bot_bottle/manifest_agent.py b/bot_bottle/manifest/agent.py similarity index 98% rename from bot_bottle/manifest_agent.py rename to bot_bottle/manifest/agent.py index c6071ad..f5d76ce 100644 --- a/bot_bottle/manifest_agent.py +++ b/bot_bottle/manifest/agent.py @@ -5,10 +5,10 @@ from __future__ import annotations from dataclasses import dataclass, field from typing import cast -from .agent_provider import PROVIDER_TEMPLATES -from .manifest_util import ManifestError, as_json_object -from .manifest_git import ManifestGitUser -from .manifest_schema import AGENT_MODEL_KEYS, is_valid_entity_name +from ..agent_provider import PROVIDER_TEMPLATES +from .util import ManifestError, as_json_object +from .git import ManifestGitUser +from .schema import AGENT_MODEL_KEYS, is_valid_entity_name @dataclass(frozen=True) diff --git a/bot_bottle/manifest_bottle.py b/bot_bottle/manifest/bottle.py similarity index 87% rename from bot_bottle/manifest_bottle.py rename to bot_bottle/manifest/bottle.py index b4b2015..ae76d7e 100644 --- a/bot_bottle/manifest_bottle.py +++ b/bot_bottle/manifest/bottle.py @@ -1,13 +1,13 @@ """The `ManifestBottle` value type. -Split out of `manifest.py` so the `extends:`/loader resolvers can import it -without a circular dependency: `manifest.py` imports those resolvers, while -they only need this value type. Everything here depends on leaf modules -(`manifest_util`, `manifest_agent`, `manifest_egress`, `manifest_git`, -`manifest_schema`), so this module sits at the bottom of the manifest layer. +Split out of the package facade (`manifest/__init__.py`) so the `extends:`/ +loader resolvers can import it without a circular dependency: the facade +imports those resolvers, while they only need this value type. Everything here +depends on leaf modules (`util`, `agent`, `egress`, `git`, `schema`), so this +module sits at the bottom of the manifest layer. -`manifest.py` re-exports `ManifestBottle`, so existing -`from .manifest import ManifestBottle` callers are unaffected. +The facade re-exports `ManifestBottle`, so existing +`from bot_bottle.manifest import ManifestBottle` callers are unaffected. """ from __future__ import annotations @@ -15,11 +15,11 @@ from __future__ import annotations from dataclasses import dataclass, field from typing import Mapping -from .manifest_util import ManifestError, as_json_object -from .manifest_agent import ManifestAgentProvider -from .manifest_egress import ManifestEgressConfig -from .manifest_git import ManifestGitEntry, ManifestGitUser, parse_git_gate_config -from .manifest_schema import BOTTLE_KEYS +from .util import ManifestError, as_json_object +from .agent import ManifestAgentProvider +from .egress import ManifestEgressConfig +from .git import ManifestGitEntry, ManifestGitUser, parse_git_gate_config +from .schema import BOTTLE_KEYS __all__ = ["ManifestBottle"] diff --git a/bot_bottle/manifest_egress.py b/bot_bottle/manifest/egress.py similarity index 99% rename from bot_bottle/manifest_egress.py rename to bot_bottle/manifest/egress.py index c373f32..a9f22cd 100644 --- a/bot_bottle/manifest_egress.py +++ b/bot_bottle/manifest/egress.py @@ -6,7 +6,7 @@ import re from dataclasses import dataclass from typing import cast -from .manifest_util import ManifestError, as_json_object +from .util import ManifestError, as_json_object EGRESS_AUTH_SCHEMES = ("Bearer", "token") diff --git a/bot_bottle/manifest_extends.py b/bot_bottle/manifest/extends.py similarity index 98% rename from bot_bottle/manifest_extends.py rename to bot_bottle/manifest/extends.py index 698d23f..c96b032 100644 --- a/bot_bottle/manifest_extends.py +++ b/bot_bottle/manifest/extends.py @@ -2,10 +2,10 @@ from __future__ import annotations -from .manifest_bottle import ManifestBottle -from .manifest_egress import ManifestEgressConfig, validate_egress_routes -from .manifest_git import ManifestGitUser, parse_git_gate_config -from .manifest_util import ManifestError, as_json_object +from .bottle import ManifestBottle +from .egress import ManifestEgressConfig, validate_egress_routes +from .git import ManifestGitUser, parse_git_gate_config +from .util import ManifestError, as_json_object def _overlay_declared_bool( diff --git a/bot_bottle/manifest_git.py b/bot_bottle/manifest/git.py similarity index 99% rename from bot_bottle/manifest_git.py rename to bot_bottle/manifest/git.py index f620c15..44c87b6 100644 --- a/bot_bottle/manifest_git.py +++ b/bot_bottle/manifest/git.py @@ -5,7 +5,7 @@ from __future__ import annotations import re from dataclasses import dataclass -from .manifest_util import ManifestError, as_json_object +from .util import ManifestError, as_json_object # Shell-safe characters for git-gate repo names. Names are embedded in # the generated entrypoint shell script (shlex.quote is the primary diff --git a/bot_bottle/manifest_loader.py b/bot_bottle/manifest/loader.py similarity index 93% rename from bot_bottle/manifest_loader.py rename to bot_bottle/manifest/loader.py index c88af32..f19130a 100644 --- a/bot_bottle/manifest_loader.py +++ b/bot_bottle/manifest/loader.py @@ -4,15 +4,15 @@ from __future__ import annotations from pathlib import Path -from .log import warn -from .manifest_bottle import ManifestBottle -from .manifest_extends import resolve_bottles -from .manifest_schema import ( +from ..log import warn +from .bottle import ManifestBottle +from .extends import resolve_bottles +from .schema import ( entity_name_from_path, validate_bottle_frontmatter_keys, ) -from .manifest_util import ManifestError -from .yaml_subset import YamlSubsetError, parse_frontmatter +from .util import ManifestError +from ..yaml_subset import YamlSubsetError, parse_frontmatter def check_stale_json(dir_path: Path, md_dir: Path, label: str) -> None: diff --git a/bot_bottle/manifest_schema.py b/bot_bottle/manifest/schema.py similarity index 98% rename from bot_bottle/manifest_schema.py rename to bot_bottle/manifest/schema.py index 165718a..512231a 100644 --- a/bot_bottle/manifest_schema.py +++ b/bot_bottle/manifest/schema.py @@ -68,7 +68,7 @@ def _validate_frontmatter_keys( keys: object, allowed_keys: frozenset[str], ) -> None: - from .manifest_util import ManifestError + from .util import ManifestError key_set = set(keys) # type: ignore unknown = key_set - allowed_keys # type: ignore diff --git a/bot_bottle/manifest_util.py b/bot_bottle/manifest/util.py similarity index 100% rename from bot_bottle/manifest_util.py rename to bot_bottle/manifest/util.py diff --git a/tests/unit/test_cli_start_selector.py b/tests/unit/test_cli_start_selector.py index 6af13b4..4f41f07 100644 --- a/tests/unit/test_cli_start_selector.py +++ b/tests/unit/test_cli_start_selector.py @@ -336,7 +336,7 @@ class TestManifestToYaml(unittest.TestCase): agent_provider_template: str = "claude", ): from bot_bottle.manifest import Manifest, ManifestBottle - from bot_bottle.manifest_agent import ManifestAgent, ManifestAgentProvider + from bot_bottle.manifest.agent import ManifestAgent, ManifestAgentProvider agent = ManifestAgent(skills=tuple(skills)) bottle = ManifestBottle( diff --git a/tests/unit/test_git_gate_render_provision.py b/tests/unit/test_git_gate_render_provision.py index 481a63c..81263e4 100644 --- a/tests/unit/test_git_gate_render_provision.py +++ b/tests/unit/test_git_gate_render_provision.py @@ -21,7 +21,7 @@ from bot_bottle.git_gate import ( git_gate_render_gitconfig, revoke_git_gate_provisioned_keys, ) -from bot_bottle.manifest_git import ManifestGitEntry, ManifestKeyConfig +from bot_bottle.manifest.git import ManifestGitEntry, ManifestKeyConfig def _entry(**kw: Any) -> ManifestGitEntry: diff --git a/tests/unit/test_manifest_bottle_merge.py b/tests/unit/test_manifest_bottle_merge.py index 03fc7de..256680d 100644 --- a/tests/unit/test_manifest_bottle_merge.py +++ b/tests/unit/test_manifest_bottle_merge.py @@ -14,7 +14,7 @@ import unittest from pathlib import Path from bot_bottle.manifest import ManifestBottle, ManifestError, ManifestIndex -from bot_bottle.manifest_extends import merge_bottles_runtime +from bot_bottle.manifest.extends import merge_bottles_runtime def _index(bottles: dict[str, object], agents: dict[str, object]) -> ManifestIndex: @@ -44,7 +44,7 @@ class TestMergeBottlesRuntime(unittest.TestCase): self.assertEqual("y", result.env["ONLY_OVERRIDE"]) def test_egress_routes_concatenated(self): - from bot_bottle.manifest_egress import ManifestEgressConfig, ManifestEgressRoute + from bot_bottle.manifest.egress import ManifestEgressConfig, ManifestEgressRoute r1 = ManifestEgressRoute(Host="api.a.com") r2 = ManifestEgressRoute(Host="api.b.com") base = ManifestBottle(egress=ManifestEgressConfig(routes=(r1,))) diff --git a/tests/unit/test_manifest_validation.py b/tests/unit/test_manifest_validation.py index 618717d..b762c2a 100644 --- a/tests/unit/test_manifest_validation.py +++ b/tests/unit/test_manifest_validation.py @@ -14,12 +14,12 @@ from unittest.mock import patch from bot_bottle.env import resolve_env from bot_bottle.errors import MissingEnvVarError from bot_bottle.manifest import Manifest, ManifestBottle, ManifestIndex -from bot_bottle.manifest_agent import ( +from bot_bottle.manifest.agent import ( ManifestAgent, ManifestAgentProvider, _parse_provider_settings, ) -from bot_bottle.manifest_util import ManifestError +from bot_bottle.manifest.util import ManifestError def _idx(obj: dict[str, object]) -> ManifestIndex: