Skip to content

Commit 0ad8f75

Browse files
authored
Merge branch 'main' into iswarya/bringup-localai-skills
2 parents fb1940a + c8d6fe1 commit 0ad8f75

43 files changed

Lines changed: 4088 additions & 96 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude-plugin/marketplace.json

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@
99
"version": "0.1.0"
1010
},
1111
"plugins": [
12-
{
13-
"name": "apu-memory-tuner",
14-
"source": "./skills/apu-memory-tuner",
15-
"description": "Inspect and tune the shared-vs-dedicated memory split (GTT / UMA Frame Buffer) on AMD Ryzen APUs so larger LLMs and image models fit on the iGPU."
16-
},
1712
{
1813
"name": "local-ai-app-integration",
1914
"source": "./skills/local-ai-app-integration",
@@ -25,19 +20,19 @@
2520
"description": "Route image generation, text-to-speech, and speech-to-text through a local AI Server to reduce token/cost usage."
2621
},
2722
{
28-
"name": "magpie",
29-
"source": "./skills/magpie",
23+
"name": "magpie-kernel-evaluator",
24+
"source": "./skills/magpie-kernel-evaluator",
3025
"description": "Performs GPU kernel correctness and performance evaluation and LLM inference benchmarking with Magpie. Analyzes single or multiple kernels (HIP/CUDA/PyTorch), compares kernel implementations, runs vLLM/SGLang benchmarks with profiling and TraceLens, and runs gap analysis on torch traces."
3126
},
32-
{
33-
"name": "rocm-doctor",
34-
"source": "./skills/rocm-doctor",
35-
"description": "Diagnose why ROCm, PyTorch, or llama.cpp isn't working on an AMD GPU. Matches the symptom against a fixed list of twelve known misconfigurations and proposes the next step."
36-
},
3727
{
3828
"name": "serving-llms-on-instinct",
3929
"source": "./skills/serving-llms-on-instinct",
4030
"description": "Serve LLMs on AMD Instinct GPUs (MI300X/MI325X/MI350X/MI355X) with vLLM on ROCm. Handles GPU detection, environment validation, vLLM configuration, launch, and health verification."
31+
},
32+
{
33+
"name": "tracelens-analysis-orchestrator",
34+
"source": "./skills/tracelens-analysis-orchestrator",
35+
"description": "Orchestrates modular PyTorch profiler trace analysis with TraceLens: generates perf reports, prepares category data, runs system-level and compute-kernel subagents in parallel, validates outputs, and writes a prioritized stakeholder report (analysis.md)."
4136
}
4237
]
4338
}

.cursor-plugin/marketplace.json

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@
99
"version": "0.1.0"
1010
},
1111
"plugins": [
12-
{
13-
"name": "apu-memory-tuner",
14-
"source": "./skills/apu-memory-tuner",
15-
"description": "Inspect and tune the shared-vs-dedicated memory split (GTT / UMA Frame Buffer) on AMD Ryzen APUs so larger LLMs and image models fit on the iGPU."
16-
},
1712
{
1813
"name": "local-ai-app-integration",
1914
"source": "./skills/local-ai-app-integration",
@@ -25,19 +20,19 @@
2520
"description": "Route image generation, text-to-speech, and speech-to-text through a local AI Server to reduce token/cost usage."
2621
},
2722
{
28-
"name": "magpie",
29-
"source": "./skills/magpie",
23+
"name": "magpie-kernel-evaluator",
24+
"source": "./skills/magpie-kernel-evaluator",
3025
"description": "Performs GPU kernel correctness and performance evaluation and LLM inference benchmarking with Magpie. Analyzes single or multiple kernels (HIP/CUDA/PyTorch), compares kernel implementations, runs vLLM/SGLang benchmarks with profiling and TraceLens, and runs gap analysis on torch traces."
3126
},
32-
{
33-
"name": "rocm-doctor",
34-
"source": "./skills/rocm-doctor",
35-
"description": "Diagnose why ROCm, PyTorch, or llama.cpp isn't working on an AMD GPU. Matches the symptom against a fixed list of twelve known misconfigurations and proposes the next step."
36-
},
3727
{
3828
"name": "serving-llms-on-instinct",
3929
"source": "./skills/serving-llms-on-instinct",
4030
"description": "Serve LLMs on AMD Instinct GPUs (MI300X/MI325X/MI350X/MI355X) with vLLM on ROCm. Handles GPU detection, environment validation, vLLM configuration, launch, and health verification."
31+
},
32+
{
33+
"name": "tracelens-analysis-orchestrator",
34+
"source": "./skills/tracelens-analysis-orchestrator",
35+
"description": "Orchestrates modular PyTorch profiler trace analysis with TraceLens: generates perf reports, prepares category data, runs system-level and compute-kernel subagents in parallel, validates outputs, and writes a prioritized stakeholder report (analysis.md)."
4136
}
4237
]
4338
}

.github/scripts/import_external_skills.py

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
1. Shallow-clones the repo at the pinned `ref` into a temp directory,
1111
using sparse-checkout so only the configured `path` is fetched.
1212
2. Copies each named skill folder into `skills/<skill>/`.
13+
2b. Optionally vendors the skill under a different local catalog name (the
14+
`as:` field on a skill entry). Federated skills follow a
15+
`<projectrepo>-<skill>` naming convention in this catalog (e.g. the
16+
`analysis-orchestrator` skill from TraceLens is vendored as
17+
`tracelens-analysis-orchestrator`), so the local folder, marketplace
18+
entry, and the SKILL.md `name` frontmatter are all set to the `as:`
19+
value. The upstream folder name is still used to locate the skill in
20+
its source repo.
1321
3. Writes `.federated.json` inside each copy with source metadata so we
1422
can tell vendored skills apart from skills authored in this repo.
1523
4. Rewrites relative markdown links that point outside the copied skill
@@ -30,11 +38,12 @@
3038
Usage:
3139
uv run .github/scripts/import_external_skills.py # write changes
3240
uv run .github/scripts/import_external_skills.py --dry-run # report only
33-
uv run .github/scripts/import_external_skills.py --only magpie # one skill
41+
uv run .github/scripts/import_external_skills.py --only magpie-kernel-evaluator
3442
35-
The `--only` flag (repeatable) restricts the run to the named skill
36-
folder(s): other skills in the catalog are skipped and pruning is limited
37-
to the named skills, so unrelated federated skills are never removed.
43+
The `--only` flag (repeatable) restricts the run to the named *local*
44+
skill folder(s) (the `as:` name when one is set): other skills in the
45+
catalog are skipped and pruning is limited to the named skills, so
46+
unrelated federated skills are never removed.
3847
3948
The companion GitHub Actions workflow `import-external-skills` calls this
4049
script on manual dispatch and opens a pull request with the result.
@@ -68,6 +77,9 @@
6877
r"\A---\s*\n(?P<frontmatter>.*?)\n---\s*\n?(?P<body>.*)\Z",
6978
re.DOTALL,
7079
)
80+
# The `name:` line inside a SKILL.md frontmatter block. Used to rewrite the
81+
# frontmatter `name` when a skill is vendored under a different local name.
82+
NAME_FIELD_RE = re.compile(r"(?m)^(?P<key>name[ \t]*:[ \t]*)(?P<value>.*)$")
7183
# Inline markdown links and images: `[text](target)` / `![alt](target)`,
7284
# with an optional `"title"` after the target. The `target` group captures
7385
# everything up to whitespace or the closing paren.
@@ -85,8 +97,14 @@
8597
@dataclass
8698
class SkillSpec:
8799
folder: str
100+
local_name: str | None = None
88101
marketplace_description_override: str | None = None
89102

103+
@property
104+
def dest_name(self) -> str:
105+
"""Local catalog name: the `as:` override, or the upstream folder."""
106+
return self.local_name or self.folder
107+
90108

91109
@dataclass
92110
class Source:
@@ -145,6 +163,7 @@ def parse_sources(catalog: Path) -> list[Source]:
145163
skills.append(
146164
SkillSpec(
147165
folder=sk["name"],
166+
local_name=sk.get("as"),
148167
marketplace_description_override=sk.get(
149168
"marketplace_description"
150169
),
@@ -399,6 +418,35 @@ def write_card(skill_dir: Path, source: Source, description: str) -> None:
399418
)
400419

401420

421+
def rewrite_skill_name(skill_dir: Path, new_name: str, log: list[str]) -> None:
422+
"""Set the SKILL.md frontmatter `name` to `new_name`.
423+
424+
Upstream ships its own `name` (e.g. `analysis-orchestrator`), but this
425+
repo's validator requires the frontmatter `name` to match the skill's
426+
directory name. When a skill is vendored under a different local name
427+
(the `as:` field), rewrite the frontmatter so the imported copy stays
428+
valid without hand-editing after every refresh.
429+
"""
430+
skill_md = skill_dir / "SKILL.md"
431+
text = skill_md.read_text(encoding="utf-8")
432+
match = FRONTMATTER_RE.match(text)
433+
if not match:
434+
return
435+
fm_start, fm_end = match.span("frontmatter")
436+
frontmatter = match.group("frontmatter")
437+
438+
new_frontmatter, count = NAME_FIELD_RE.subn(
439+
lambda m: f"{m.group('key')}{new_name}", frontmatter, count=1
440+
)
441+
if count == 0:
442+
# No `name:` line to rewrite; prepend one so the copy stays valid.
443+
new_frontmatter = f"name: {new_name}\n{frontmatter}"
444+
if new_frontmatter == frontmatter:
445+
return
446+
skill_md.write_text(text[:fm_start] + new_frontmatter + text[fm_end:], encoding="utf-8")
447+
log.append(f" [SKILL.md] name -> {new_name}")
448+
449+
402450
def update_marketplace(results: Iterable[ImportResult], dry_run: bool) -> bool:
403451
"""Sync `.claude-plugin/marketplace.json` with the imported skills.
404452
@@ -496,14 +544,22 @@ def import_source(
496544
or truncate_description(description)
497545
)
498546

499-
dest_skill = SKILLS_DIR / spec.folder
547+
dest_name = spec.dest_name
548+
dest_skill = SKILLS_DIR / dest_name
549+
# The marker records the skill's *upstream* location, which keeps
550+
# using the source folder name even when we vendor it locally as
551+
# `dest_name`.
500552
relative_path = f"{source.path}/{spec.folder}"
501553
action = "would import" if dry_run else "importing"
502-
log.append(f"[{source.name}] {action} {spec.folder} -> skills/{spec.folder}")
554+
renamed = f" (as {dest_name})" if dest_name != spec.folder else ""
555+
log.append(
556+
f"[{source.name}] {action} {spec.folder} -> skills/{dest_name}{renamed}"
557+
)
503558
if not dry_run:
504559
copy_skill(src_skill, dest_skill)
505560
write_marker(dest_skill, source, commit, relative_path)
506561
write_card(dest_skill, source, marketplace_description)
562+
rewrite_skill_name(dest_skill, dest_name, log)
507563
rewrite_external_references(
508564
dest_skill,
509565
relative_path,
@@ -516,7 +572,7 @@ def import_source(
516572
results.append(
517573
ImportResult(
518574
source=source,
519-
folder=spec.folder,
575+
folder=dest_name,
520576
commit=commit,
521577
skill_description=description.strip(),
522578
marketplace_description=marketplace_description,
@@ -575,15 +631,15 @@ def main(argv: list[str] | None = None) -> int:
575631

576632
only = set(args.only or [])
577633
if only:
578-
known = {spec.folder for source in sources for spec in source.skills}
634+
known = {spec.dest_name for source in sources for spec in source.skills}
579635
unknown = only - known
580636
if unknown:
581637
raise ValueError(
582638
"--only names skill(s) not present in the catalog: "
583639
+ ", ".join(sorted(unknown))
584640
)
585641
for source in sources:
586-
source.skills = [s for s in source.skills if s.folder in only]
642+
source.skills = [s for s in source.skills if s.dest_name in only]
587643
sources = [source for source in sources if source.skills]
588644
log: list[str] = []
589645
declared: set[str] = set()
@@ -594,12 +650,12 @@ def main(argv: list[str] | None = None) -> int:
594650

595651
for source in sources:
596652
for spec in source.skills:
597-
if spec.folder in declared:
653+
if spec.dest_name in declared:
598654
raise ValueError(
599-
f"Skill name collision: {spec.folder!r} is listed by "
655+
f"Skill name collision: {spec.dest_name!r} is listed by "
600656
"more than one source in .github/scripts/sources.yml."
601657
)
602-
declared.add(spec.folder)
658+
declared.add(spec.dest_name)
603659
all_results.extend(import_source(source, args.dry_run, log))
604660

605661
# With --only we deliberately ignore skills the user didn't name, so

.github/scripts/sources.yml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,14 @@
1616
# license: SPDX license identifier (carried into the marker file)
1717
# skills: list of skill folder names to import from `path`
1818
# Either a bare string (folder name) or a mapping:
19-
# { name: <folder>, marketplace_description: <override> }
19+
# { name: <folder>, as: <local-name>,
20+
# marketplace_description: <override> }
21+
# `as` vendors the skill under a different local catalog name
22+
# (folder + marketplace entry + SKILL.md `name`). Federated
23+
# skills use a `<projectrepo>-<skill>` convention, e.g. the
24+
# TraceLens `analysis-orchestrator` skill is imported `as:
25+
# tracelens-analysis-orchestrator`. The upstream `name` is
26+
# still used to locate the folder in the source repo.
2027
#
2128
# To add or remove an imported skill, edit `skills:` here and then run the
2229
# "Import external skills" workflow. The workflow opens a pull request with
@@ -29,4 +36,13 @@ sources:
2936
path: skills
3037
license: MIT
3138
skills:
32-
- magpie
39+
- name: magpie
40+
as: magpie-kernel-evaluator
41+
- name: amd-agi-tracelens
42+
repo: AMD-AGI/TraceLens
43+
ref: feat/gw_rename_directories
44+
path: TraceLens/Agent/Analysis/skills
45+
license: MIT
46+
skills:
47+
- name: analysis-orchestrator
48+
as: tracelens-analysis-orchestrator

0 commit comments

Comments
 (0)