#!/usr/bin/env python3 """Repair installed TransformerLab plugin manifests from the pinned source manifest.""" from __future__ import annotations import argparse import json import sys from pathlib import Path def load_json(path: Path) -> dict: with path.open("r", encoding="utf-8") as handle: return json.load(handle) def write_json(path: Path, payload: dict) -> None: with path.open("w", encoding="utf-8") as handle: json.dump(payload, handle, indent=2, sort_keys=False) handle.write("\n") def candidate_manifest_paths(root: Path, plugin: str) -> list[Path]: candidates = [] patterns = [ f"workspace/plugins/{plugin}/index.json", f"orgs/*/workspace/plugins/{plugin}/index.json", f"orgs/*/plugins/{plugin}/index.json", ] for pattern in patterns: candidates.extend(root.glob(pattern)) unique = [] seen = set() for path in candidates: resolved = path.resolve() if resolved in seen: continue seen.add(resolved) unique.append(path) return unique def repair_manifest(path: Path, required_supports: list[str], source_supports: list[str]) -> bool: payload = load_json(path) existing = payload.get("supports", []) if not isinstance(existing, list): existing = [] desired = [] seen = set() for item in source_supports: if isinstance(item, str) and item not in seen: desired.append(item) seen.add(item) for item in required_supports: if item not in seen: desired.append(item) seen.add(item) if existing == desired: return False payload["supports"] = desired write_json(path, payload) return True def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--transformerlab-dir", required=True) parser.add_argument("--plugin", required=True) parser.add_argument("--required-support", action="append", default=[]) args = parser.parse_args() root = Path(args.transformerlab_dir).expanduser().resolve() source_manifest = root / "src" / "transformerlab" / "plugins" / args.plugin / "index.json" if not source_manifest.exists(): print(f"missing source plugin manifest: {source_manifest}", file=sys.stderr) return 1 source_payload = load_json(source_manifest) source_supports = source_payload.get("supports", []) if not isinstance(source_supports, list): print(f"invalid supports array in {source_manifest}", file=sys.stderr) return 1 missing_required = [item for item in args.required_support if item not in source_supports] if missing_required: print( f"source plugin manifest {source_manifest} is missing required supports: {', '.join(missing_required)}", file=sys.stderr, ) return 1 updated = 0 for manifest in candidate_manifest_paths(root, args.plugin): if repair_manifest(manifest, args.required_support, source_supports): updated += 1 print(f"repaired {manifest}") if updated == 0: print(f"no installed {args.plugin} manifests needed repair") return 0 if __name__ == "__main__": raise SystemExit(main())