|
9 | 9 |
|
10 | 10 | 1. Shallow-clones the repo at the pinned `ref` into a temp directory, |
11 | 11 | using sparse-checkout so only the configured `path` is fetched. |
12 | | -2. Copies each named skill folder into `skills/<skill>/`. |
| 12 | +2. Copies each named skill folder into `skills/<skill>/`, plus any declared |
| 13 | + companion files (e.g. templates linked from agent markdown but stored |
| 14 | + outside the skill subtree in the upstream repo). |
13 | 15 | 3. Writes `.federated.json` inside each copy with source metadata so we |
14 | 16 | can tell vendored skills apart from skills authored in this repo. |
15 | 17 | 4. Rewrites relative markdown links that point outside the copied skill |
@@ -353,6 +355,45 @@ def copy_skill(src: Path, dest: Path) -> None: |
353 | 355 | shutil.copytree(src, dest) |
354 | 356 |
|
355 | 357 |
|
| 358 | +# Repo-relative paths (inside the upstream clone) that a federated skill links |
| 359 | +# to but that live outside its copied subtree. Fetched with `git show` so the |
| 360 | +# sparse checkout does not need to widen. |
| 361 | +_COMPANION_FILES: dict[tuple[str, str], list[tuple[str, str]]] = { |
| 362 | + ("amd-agi-tracelens", "analysis-orchestrator"): [ |
| 363 | + ( |
| 364 | + "TraceLens/Agent/Analysis/utils/templates/sub_agent_spec.md", |
| 365 | + "utils/templates/sub_agent_spec.md", |
| 366 | + ), |
| 367 | + ], |
| 368 | +} |
| 369 | + |
| 370 | + |
| 371 | +def vendor_companion_files( |
| 372 | + clone_dir: Path, |
| 373 | + commit: str, |
| 374 | + dest_skill: Path, |
| 375 | + source_name: str, |
| 376 | + skill_folder: str, |
| 377 | + log: list[str], |
| 378 | +) -> None: |
| 379 | + """Materialize companion blobs linked from agent markdown but outside the skill folder.""" |
| 380 | + for repo_rel, dest_rel in _COMPANION_FILES.get((source_name, skill_folder), []): |
| 381 | + result = subprocess.run( |
| 382 | + ["git", "show", f"{commit}:{repo_rel}"], |
| 383 | + cwd=clone_dir, |
| 384 | + check=True, |
| 385 | + capture_output=True, |
| 386 | + text=True, |
| 387 | + ) |
| 388 | + out = dest_skill / dest_rel |
| 389 | + out.parent.mkdir(parents=True, exist_ok=True) |
| 390 | + out.write_text(result.stdout, encoding="utf-8") |
| 391 | + log.append( |
| 392 | + f"[{source_name}] vendored companion {repo_rel} -> " |
| 393 | + f"skills/{skill_folder}/{dest_rel}" |
| 394 | + ) |
| 395 | + |
| 396 | + |
356 | 397 | def write_marker( |
357 | 398 | skill_dir: Path, |
358 | 399 | source: Source, |
@@ -502,6 +543,14 @@ def import_source( |
502 | 543 | log.append(f"[{source.name}] {action} {spec.folder} -> skills/{spec.folder}") |
503 | 544 | if not dry_run: |
504 | 545 | copy_skill(src_skill, dest_skill) |
| 546 | + vendor_companion_files( |
| 547 | + tmp_path, |
| 548 | + commit, |
| 549 | + dest_skill, |
| 550 | + source.name, |
| 551 | + spec.folder, |
| 552 | + log, |
| 553 | + ) |
505 | 554 | write_marker(dest_skill, source, commit, relative_path) |
506 | 555 | write_card(dest_skill, source, marketplace_description) |
507 | 556 | rewrite_external_references( |
|
0 commit comments