diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-09-01 14:48:45 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-09-01 14:48:45 +0300 |
| commit | 8a6d697308162874a236c84aac0b0f8c7ac01f83 (patch) | |
| tree | ed7dc7e8c6f50d66bde721fae78576aede929f66 /scripts/agent_detection_manifest_check.py | |
| parent | b54a78aa510b87d1e3b56c619b72eaeb59e4a2a1 (diff) | |
refactor: separate website presentation from runtime
Diffstat (limited to 'scripts/agent_detection_manifest_check.py')
| -rw-r--r-- | scripts/agent_detection_manifest_check.py | 75 |
1 files changed, 53 insertions, 22 deletions
diff --git a/scripts/agent_detection_manifest_check.py b/scripts/agent_detection_manifest_check.py index f180318b..f0dc0005 100644 --- a/scripts/agent_detection_manifest_check.py +++ b/scripts/agent_detection_manifest_check.py @@ -13,7 +13,7 @@ from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[1] DEFAULT_BUNDLED_DIR = PROJECT_ROOT / "src" / "detect" / "manifests" -DEFAULT_WEBSITE_DIR = PROJECT_ROOT / "website" / "agent-detection" +DEFAULT_PUBLISHED_DIR = PROJECT_ROOT / "distribution" / "agent-detection" ENGINE_SOURCE = PROJECT_ROOT / "src" / "detect" / "manifest_update.rs" MANIFEST_KEYS = {"id", "version", "min_engine_version", "updated_at", "aliases", "rules"} @@ -54,9 +54,9 @@ MAX_TOTAL_MATCHERS = 1024 MAX_MATCHER_CHARS = 512 # Keep engine-2 clients on the OSC-capable manifest until an engine-3 release -# can consume top_non_empty_lines. Remove this entry when the website publishes -# the bundled Grok manifest. -STAGED_WEBSITE_MANIFESTS = { +# can consume top_non_empty_lines. Remove this entry when the distribution +# publishes the bundled Grok manifest. +STAGED_PUBLISHED_MANIFESTS = { "grok": ( "2026.07.16.2", "2026.07.16.1", @@ -64,16 +64,31 @@ STAGED_WEBSITE_MANIFESTS = { ), } +# Muse is bundled on master but has not shipped in a stable binary yet. Stable +# clients cannot identify it, so publish it with the release that first ships +# the corresponding Agent variant and remove this exact-content exception. +UNPUBLISHED_BUNDLED_MANIFESTS = { + "muse": ( + "2026.08.26.1", + "b69c4d87fa9c19e3e6453b706fbe39c98a8b33ffbaa48e8cd5ae6751e9615074", + ), +} + def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--bundled-dir", type=Path, default=DEFAULT_BUNDLED_DIR) - parser.add_argument("--website-dir", type=Path, default=DEFAULT_WEBSITE_DIR) + parser.add_argument("--published-dir", type=Path, default=DEFAULT_PUBLISHED_DIR) parser.add_argument("--engine-version", type=int) parser.add_argument( - "--require-website", + "--require-published", + action="store_true", + help="fail if published agent-detection assets or catalog are missing", + ) + parser.add_argument( + "--require-all-published", action="store_true", - help="fail if website agent-detection assets or catalog are missing", + help="fail if any bundled manifest is intentionally held for a future stable release", ) return parser.parse_args() @@ -286,11 +301,13 @@ def load_manifest_dir(path: Path, engine_version: int) -> dict[str, tuple[Path, def validate_catalog( - website_dir: Path, + published_dir: Path, bundled: dict[str, tuple[Path, dict]], engine_version: int, + *, + allow_unpublished: bool = False, ) -> None: - catalog_path = website_dir / "index.toml" + catalog_path = published_dir / "index.toml" catalog = load_toml(catalog_path) if set(catalog) != {"schema_version", "agents"}: raise CheckError(f"{catalog_path}: expected only schema_version and agents") @@ -314,7 +331,7 @@ def validate_catalog( raise CheckError(f"{catalog_path}: unsafe path for {agent_id}: {rel_path}") if agent_id not in bundled: raise CheckError(f"{catalog_path}: unknown agent {agent_id}; binary cannot identify it") - manifest_path = website_dir / rel_path + manifest_path = published_dir / rel_path manifest = validate_manifest(manifest_path, engine_version) if manifest["id"] != agent_id: raise CheckError(f"{manifest_path}: id {manifest['id']} does not match catalog {agent_id}") @@ -322,17 +339,17 @@ def validate_catalog( bundled_path, bundled_manifest = bundled[agent_id] cmp = compare_versions(manifest["version"], bundled_manifest["version"], manifest_path) - staged_manifest = STAGED_WEBSITE_MANIFESTS.get(agent_id) - website_digest = hashlib.sha256(manifest_path.read_bytes()).hexdigest() + staged_manifest = STAGED_PUBLISHED_MANIFESTS.get(agent_id) + published_digest = hashlib.sha256(manifest_path.read_bytes()).hexdigest() stages_new_engine_manifest = ( staged_manifest - == (bundled_manifest["version"], manifest["version"], website_digest) + == (bundled_manifest["version"], manifest["version"], published_digest) and bundled_manifest["min_engine_version"] == engine_version and manifest["min_engine_version"] < bundled_manifest["min_engine_version"] ) if cmp < 0 and not stages_new_engine_manifest: raise CheckError( - f"{manifest_path}: website version {manifest['version']} is lower than bundled " + f"{manifest_path}: published version {manifest['version']} is lower than bundled " f"{bundled_manifest['version']} in {bundled_path}" ) if cmp == 0 and manifest_path.read_text(encoding="utf-8") != bundled_path.read_text(encoding="utf-8"): @@ -341,13 +358,22 @@ def validate_catalog( ) missing = sorted(set(bundled) - set(seen)) - if missing: - raise CheckError(f"{catalog_path}: missing bundled agent(s): {', '.join(missing)}") + unexpected_missing = [] + for agent_id in missing: + bundled_path, bundled_manifest = bundled[agent_id] + staged = UNPUBLISHED_BUNDLED_MANIFESTS.get(agent_id) if allow_unpublished else None + digest = hashlib.sha256(bundled_path.read_bytes()).hexdigest() + if staged != (bundled_manifest["version"], digest): + unexpected_missing.append(agent_id) + if unexpected_missing: + raise CheckError( + f"{catalog_path}: missing bundled agent(s): {', '.join(unexpected_missing)}" + ) catalog_paths = set(seen.values()) | {"index.toml"} - extra = sorted(path.name for path in website_dir.glob("*.toml") if path.name not in catalog_paths) + extra = sorted(path.name for path in published_dir.glob("*.toml") if path.name not in catalog_paths) if extra: - raise CheckError(f"{website_dir}: TOML file(s) not listed in catalog: {', '.join(extra)}") + raise CheckError(f"{published_dir}: TOML file(s) not listed in catalog: {', '.join(extra)}") def main() -> int: @@ -355,10 +381,15 @@ def main() -> int: try: engine_version = read_engine_version(args.engine_version) bundled = load_manifest_dir(args.bundled_dir, engine_version) - if args.require_website or args.website_dir.exists(): - if not args.website_dir.is_dir(): - raise CheckError(f"{args.website_dir}: website manifest directory is missing") - validate_catalog(args.website_dir, bundled, engine_version) + if args.require_published or args.require_all_published or args.published_dir.exists(): + if not args.published_dir.is_dir(): + raise CheckError(f"{args.published_dir}: published manifest directory is missing") + validate_catalog( + args.published_dir, + bundled, + engine_version, + allow_unpublished=not args.require_all_published, + ) except CheckError as exc: print(f"error: {exc}", file=sys.stderr) return 1 |
