agentbundle 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentbundle/__init__.py +14 -0
- agentbundle/__main__.py +5 -0
- agentbundle/_data/adapter.schema.json +270 -0
- agentbundle/_data/adapter.toml +584 -0
- agentbundle/_data/install-marker.py +1099 -0
- agentbundle/_data/pack.schema.json +152 -0
- agentbundle/_data/plugin-manifest.derived.schema.json +33 -0
- agentbundle/_data/plugin-manifest.schema.json +18 -0
- agentbundle/build/__init__.py +206 -0
- agentbundle/build/__main__.py +8 -0
- agentbundle/build/adapter_root_bins.py +336 -0
- agentbundle/build/adapters/__init__.py +46 -0
- agentbundle/build/adapters/claude_code.py +142 -0
- agentbundle/build/adapters/codex.py +227 -0
- agentbundle/build/adapters/copilot.py +149 -0
- agentbundle/build/adapters/kiro.py +608 -0
- agentbundle/build/adapters/kiro_cli.py +53 -0
- agentbundle/build/adapters/kiro_ide.py +275 -0
- agentbundle/build/contract.py +20 -0
- agentbundle/build/lint_packs.py +555 -0
- agentbundle/build/main.py +596 -0
- agentbundle/build/phase_order.py +40 -0
- agentbundle/build/projections/__init__.py +13 -0
- agentbundle/build/projections/codex_agent_toml.py +232 -0
- agentbundle/build/projections/copilot_agent_md.py +206 -0
- agentbundle/build/projections/copilot_hooks_json.py +142 -0
- agentbundle/build/projections/direct_directory.py +41 -0
- agentbundle/build/projections/hook_id.py +27 -0
- agentbundle/build/projections/kiro_ide_hook.py +256 -0
- agentbundle/build/projections/merge_into_agent_json.py +264 -0
- agentbundle/build/projections/merge_json.py +58 -0
- agentbundle/build/projections/user_merge_json.py +324 -0
- agentbundle/build/scope_rails.py +728 -0
- agentbundle/build/self_host.py +1486 -0
- agentbundle/build/shared_libs.py +309 -0
- agentbundle/build/target_resolver.py +85 -0
- agentbundle/build/tests/__init__.py +0 -0
- agentbundle/build/tests/test_adapter_claude_code.py +275 -0
- agentbundle/build/tests/test_adapter_codex.py +699 -0
- agentbundle/build/tests/test_adapter_copilot.py +91 -0
- agentbundle/build/tests/test_adapter_kiro.py +449 -0
- agentbundle/build/tests/test_adapter_kiro_alias.py +105 -0
- agentbundle/build/tests/test_adapter_kiro_cli.py +102 -0
- agentbundle/build/tests/test_adapter_kiro_ide.py +173 -0
- agentbundle/build/tests/test_adapter_root_bins_projection.py +429 -0
- agentbundle/build/tests/test_build_ships_seeds.py +78 -0
- agentbundle/build/tests/test_contract.py +582 -0
- agentbundle/build/tests/test_contract_scope.py +224 -0
- agentbundle/build/tests/test_contract_v07.py +191 -0
- agentbundle/build/tests/test_contract_v08.py +230 -0
- agentbundle/build/tests/test_direct_directory_cleanup.py +65 -0
- agentbundle/build/tests/test_end_to_end_build.py +227 -0
- agentbundle/build/tests/test_lint_agents_md_legacy_block.py +135 -0
- agentbundle/build/tests/test_lint_agents_md_risk_block.py +116 -0
- agentbundle/build/tests/test_lint_packs.py +703 -0
- agentbundle/build/tests/test_load_pack_hook_wiring_safely.py +176 -0
- agentbundle/build/tests/test_pack_schema.py +265 -0
- agentbundle/build/tests/test_pack_schema_allowed_adapters.py +258 -0
- agentbundle/build/tests/test_pack_schema_install.py +305 -0
- agentbundle/build/tests/test_pipeline.py +272 -0
- agentbundle/build/tests/test_plugin_manifest_schema.py +327 -0
- agentbundle/build/tests/test_projections_merge_json.py +148 -0
- agentbundle/build/tests/test_scope_rails.py +398 -0
- agentbundle/build/tests/test_security.py +97 -0
- agentbundle/build/tests/test_self_host_check.py +2100 -0
- agentbundle/build/tests/test_shared_libs_projection.py +415 -0
- agentbundle/build/tests/test_shipped_packs_v07_declarations.py +100 -0
- agentbundle/build/tests/test_shipped_packs_v08_declarations.py +80 -0
- agentbundle/build/tests/test_validate.py +250 -0
- agentbundle/build/validate.py +141 -0
- agentbundle/catalogue.py +164 -0
- agentbundle/cli.py +486 -0
- agentbundle/commands/__init__.py +5 -0
- agentbundle/commands/_common.py +174 -0
- agentbundle/commands/_drop_warning.py +329 -0
- agentbundle/commands/adapt.py +343 -0
- agentbundle/commands/config.py +125 -0
- agentbundle/commands/diff.py +211 -0
- agentbundle/commands/init_state.py +279 -0
- agentbundle/commands/install.py +3026 -0
- agentbundle/commands/list_packs.py +170 -0
- agentbundle/commands/list_targets.py +23 -0
- agentbundle/commands/reconcile.py +161 -0
- agentbundle/commands/render.py +165 -0
- agentbundle/commands/scaffold.py +69 -0
- agentbundle/commands/uninstall.py +294 -0
- agentbundle/commands/upgrade.py +699 -0
- agentbundle/commands/validate.py +688 -0
- agentbundle/config.py +747 -0
- agentbundle/render.py +123 -0
- agentbundle/safety.py +633 -0
- agentbundle/scope.py +319 -0
- agentbundle/user_config.py +284 -0
- agentbundle/version.py +49 -0
- agentbundle-0.2.0.dist-info/METADATA +37 -0
- agentbundle-0.2.0.dist-info/RECORD +99 -0
- agentbundle-0.2.0.dist-info/WHEEL +5 -0
- agentbundle-0.2.0.dist-info/entry_points.txt +2 -0
- agentbundle-0.2.0.dist-info/top_level.txt +1 -0
agentbundle/render.py
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""Thin wrapper around `agentbundle.build` — the library-first render API.
|
|
2
|
+
|
|
3
|
+
The CLI's `render`, `scaffold`, `install`, and `upgrade` subcommands all
|
|
4
|
+
route their projection work through this module so there is exactly one
|
|
5
|
+
implementation of "produce the projected output tree for a pack" in the
|
|
6
|
+
codebase.
|
|
7
|
+
|
|
8
|
+
Two surfaces:
|
|
9
|
+
|
|
10
|
+
- `render_pack_to_dir(pack_path, output_dir, contract=None)` — runs the
|
|
11
|
+
same three RFC-0001 recipes that `make build` runs (per-pack
|
|
12
|
+
claude-plugin, per-pack apm-package, marketplace) and writes them
|
|
13
|
+
into `output_dir`. Byte-identical to `make build`.
|
|
14
|
+
|
|
15
|
+
- `render_pack(pack_path, contract=None)` — same projection, but
|
|
16
|
+
materialised in a tempdir and returned as a `dict[str, bytes]`
|
|
17
|
+
keyed by path-relative-to-the-tempdir. Caller is responsible for
|
|
18
|
+
deciding where (or whether) to write the bytes. Used by `diff`,
|
|
19
|
+
`install`, `upgrade`, and the F-build parity test.
|
|
20
|
+
|
|
21
|
+
Adapter target enumeration lives at `list_adapters()`; it queries the
|
|
22
|
+
runtime registry at `agentbundle.build.adapters` so adding an adapter
|
|
23
|
+
to the registry adds it to `agentbundle list-targets` automatically.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import tempfile
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
from typing import Sequence
|
|
31
|
+
|
|
32
|
+
from agentbundle.build import adapters as _adapters
|
|
33
|
+
import tomllib
|
|
34
|
+
|
|
35
|
+
from agentbundle.build.main import (
|
|
36
|
+
DEFAULT_RECIPES,
|
|
37
|
+
Pack,
|
|
38
|
+
_read_bundled,
|
|
39
|
+
discover_packs,
|
|
40
|
+
load_recipe,
|
|
41
|
+
run_recipe,
|
|
42
|
+
validate_pack_metadata,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def list_adapters() -> Sequence[str]:
|
|
47
|
+
"""Return the adapter names the CLI ships against, in stable sort order."""
|
|
48
|
+
return sorted(_adapters.registry.keys())
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _resolve_contract(contract: dict | None) -> dict:
|
|
52
|
+
return contract if contract is not None else tomllib.loads(_read_bundled("adapter.toml"))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _pack_from_path(pack_path: Path) -> Pack:
|
|
56
|
+
pack_path = pack_path.resolve()
|
|
57
|
+
if not (pack_path / "pack.toml").exists():
|
|
58
|
+
raise FileNotFoundError(f"no pack.toml at {pack_path}")
|
|
59
|
+
validate_pack_metadata(pack_path / "pack.toml")
|
|
60
|
+
return Pack(name=pack_path.name, path=pack_path)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def render_pack_to_dir(
|
|
64
|
+
pack_path: Path,
|
|
65
|
+
output_dir: Path,
|
|
66
|
+
*,
|
|
67
|
+
contract: dict | None = None,
|
|
68
|
+
recipes: Sequence[str] = DEFAULT_RECIPES,
|
|
69
|
+
) -> None:
|
|
70
|
+
"""Render a single pack to `output_dir` using the named recipes.
|
|
71
|
+
|
|
72
|
+
`output_dir` is created if absent. The three default recipes match
|
|
73
|
+
what `make build` runs; the F-build parity test pins this.
|
|
74
|
+
"""
|
|
75
|
+
pack = _pack_from_path(pack_path)
|
|
76
|
+
contract_data = _resolve_contract(contract)
|
|
77
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
78
|
+
for recipe_name in recipes:
|
|
79
|
+
recipe = load_recipe(recipe_name)
|
|
80
|
+
run_recipe(recipe, [pack], output_dir, contract_data)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def render_pack(
|
|
84
|
+
pack_path: Path,
|
|
85
|
+
*,
|
|
86
|
+
contract: dict | None = None,
|
|
87
|
+
recipes: Sequence[str] = DEFAULT_RECIPES,
|
|
88
|
+
) -> dict[str, bytes]:
|
|
89
|
+
"""Render a pack to a tempdir and return its bytes keyed by relpath.
|
|
90
|
+
|
|
91
|
+
Bytes — not str — because hook bodies may be non-UTF-8 binaries in
|
|
92
|
+
principle (and because `bytes` is the right shape for hash + write).
|
|
93
|
+
"""
|
|
94
|
+
with tempfile.TemporaryDirectory() as raw:
|
|
95
|
+
out = Path(raw)
|
|
96
|
+
render_pack_to_dir(pack_path, out, contract=contract, recipes=recipes)
|
|
97
|
+
return _collect_tree(out)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def render_packs_to_dir(
|
|
101
|
+
packs_dir: Path,
|
|
102
|
+
output_dir: Path,
|
|
103
|
+
*,
|
|
104
|
+
contract: dict | None = None,
|
|
105
|
+
recipes: Sequence[str] = DEFAULT_RECIPES,
|
|
106
|
+
) -> None:
|
|
107
|
+
"""Render every pack under `packs_dir` — the full `make build` shape."""
|
|
108
|
+
contract_data = _resolve_contract(contract)
|
|
109
|
+
packs = discover_packs(packs_dir)
|
|
110
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
111
|
+
for recipe_name in recipes:
|
|
112
|
+
recipe = load_recipe(recipe_name)
|
|
113
|
+
run_recipe(recipe, packs, output_dir, contract_data)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _collect_tree(root: Path) -> dict[str, bytes]:
|
|
117
|
+
"""Walk `root` and return every file's bytes keyed by relpath (POSIX-style)."""
|
|
118
|
+
out: dict[str, bytes] = {}
|
|
119
|
+
for path in sorted(root.rglob("*")):
|
|
120
|
+
if path.is_file():
|
|
121
|
+
relpath = path.relative_to(root).as_posix()
|
|
122
|
+
out[relpath] = path.read_bytes()
|
|
123
|
+
return out
|