@jaggerxtrm/pi-extensions 0.8.1 → 0.9.0
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.
|
@@ -3,37 +3,63 @@ import { SubprocessRunner } from "../../src/core";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import * as fs from "node:fs";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
];
|
|
6
|
+
// service-skills v2: the canonical machinery skill is `service-skills`; per-service
|
|
7
|
+
// skills + the registry live under the per-repo umbrella in .xtrm packs.
|
|
8
|
+
const MACHINERY_SKILL = "service-skills";
|
|
10
9
|
|
|
11
10
|
const GLOBAL_SKILL_ROOTS = [
|
|
12
11
|
path.join(process.env.HOME || "", ".agents", "skills"),
|
|
13
12
|
path.join(process.env.HOME || "", ".claude", "skills"),
|
|
14
13
|
];
|
|
15
14
|
|
|
15
|
+
function listPackDirs(cwd: string): string[] {
|
|
16
|
+
const packsRoot = path.join(cwd, ".xtrm", "skills", "user", "packs");
|
|
17
|
+
try {
|
|
18
|
+
return fs
|
|
19
|
+
.readdirSync(packsRoot, { withFileTypes: true })
|
|
20
|
+
.filter((e) => e.isDirectory())
|
|
21
|
+
.map((e) => path.join(packsRoot, e.name))
|
|
22
|
+
.sort();
|
|
23
|
+
} catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
16
28
|
export default function (pi: ExtensionAPI) {
|
|
17
29
|
const getCwd = (ctx: any) => ctx.cwd || process.cwd();
|
|
18
30
|
|
|
31
|
+
// Precedence mirrors bootstrap.get_registry_path: canonical .xtrm umbrella wins,
|
|
32
|
+
// then flat pack-root, then legacy repo-root / .claude (never let stale shadow).
|
|
19
33
|
const resolveRegistryPath = (cwd: string): string | null => {
|
|
20
|
-
|
|
34
|
+
const packDirs = listPackDirs(cwd);
|
|
35
|
+
for (const pack of packDirs) {
|
|
36
|
+
const umbrella = path.join(pack, "service-skills", "service-registry.json");
|
|
37
|
+
if (fs.existsSync(umbrella)) return umbrella;
|
|
38
|
+
}
|
|
39
|
+
for (const pack of packDirs) {
|
|
40
|
+
const flat = path.join(pack, "service-registry.json");
|
|
41
|
+
if (fs.existsSync(flat)) return flat;
|
|
42
|
+
}
|
|
43
|
+
for (const rel of ["service-registry.json", path.join(".claude", "skills", "service-registry.json")]) {
|
|
21
44
|
const candidate = path.join(cwd, rel);
|
|
22
45
|
if (fs.existsSync(candidate)) return candidate;
|
|
23
46
|
}
|
|
24
47
|
return null;
|
|
25
48
|
};
|
|
26
49
|
|
|
27
|
-
const resolveSkillScript = (cwd: string,
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
50
|
+
const resolveSkillScript = (cwd: string, scriptName: string): string | null => {
|
|
51
|
+
const candidates = [
|
|
52
|
+
path.join(cwd, ".claude", "skills", MACHINERY_SKILL, "scripts", scriptName),
|
|
53
|
+
path.join(cwd, ".xtrm", "skills", "default", MACHINERY_SKILL, "scripts", scriptName),
|
|
54
|
+
];
|
|
55
|
+
for (const candidate of candidates) {
|
|
56
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
57
|
+
}
|
|
31
58
|
for (const root of GLOBAL_SKILL_ROOTS) {
|
|
32
59
|
if (!root) continue;
|
|
33
|
-
const candidate = path.join(root,
|
|
60
|
+
const candidate = path.join(root, MACHINERY_SKILL, "scripts", scriptName);
|
|
34
61
|
if (fs.existsSync(candidate)) return candidate;
|
|
35
62
|
}
|
|
36
|
-
|
|
37
63
|
return null;
|
|
38
64
|
};
|
|
39
65
|
|
|
@@ -43,7 +69,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
43
69
|
const registryPath = resolveRegistryPath(cwd);
|
|
44
70
|
if (!registryPath) return undefined;
|
|
45
71
|
|
|
46
|
-
const catalogerPath = resolveSkillScript(cwd, "
|
|
72
|
+
const catalogerPath = resolveSkillScript(cwd, "cataloger.py");
|
|
47
73
|
if (!catalogerPath) return undefined;
|
|
48
74
|
|
|
49
75
|
const result = await SubprocessRunner.run("python3", [catalogerPath], {
|
|
@@ -77,7 +103,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
77
103
|
const registryPath = resolveRegistryPath(cwd);
|
|
78
104
|
if (!registryPath) return undefined;
|
|
79
105
|
|
|
80
|
-
const driftDetectorPath = resolveSkillScript(cwd, "
|
|
106
|
+
const driftDetectorPath = resolveSkillScript(cwd, "drift_detector.py");
|
|
81
107
|
if (!driftDetectorPath) return undefined;
|
|
82
108
|
|
|
83
109
|
const hookInput = JSON.stringify({
|