@agentworkforce/persona-kit 0.19.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.
- package/README.md +93 -0
- package/dist/config-files.d.ts +21 -0
- package/dist/config-files.d.ts.map +1 -0
- package/dist/config-files.js +81 -0
- package/dist/config-files.js.map +1 -0
- package/dist/constants.d.ts +20 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +78 -0
- package/dist/constants.js.map +1 -0
- package/dist/detect.d.ts +28 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +63 -0
- package/dist/detect.js.map +1 -0
- package/dist/env-refs.d.ts +56 -0
- package/dist/env-refs.d.ts.map +1 -0
- package/dist/env-refs.js +105 -0
- package/dist/env-refs.js.map +1 -0
- package/dist/env-refs.test.d.ts +2 -0
- package/dist/env-refs.test.d.ts.map +1 -0
- package/dist/env-refs.test.js +84 -0
- package/dist/env-refs.test.js.map +1 -0
- package/dist/execute.d.ts +47 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +68 -0
- package/dist/execute.js.map +1 -0
- package/dist/execute.test.d.ts +2 -0
- package/dist/execute.test.d.ts.map +1 -0
- package/dist/execute.test.js +255 -0
- package/dist/execute.test.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +234 -0
- package/dist/index.test.js.map +1 -0
- package/dist/inputs.d.ts +13 -0
- package/dist/inputs.d.ts.map +1 -0
- package/dist/inputs.js +57 -0
- package/dist/inputs.js.map +1 -0
- package/dist/inputs.test.d.ts +2 -0
- package/dist/inputs.test.d.ts.map +1 -0
- package/dist/inputs.test.js +51 -0
- package/dist/inputs.test.js.map +1 -0
- package/dist/interactive-spec.d.ts +117 -0
- package/dist/interactive-spec.d.ts.map +1 -0
- package/dist/interactive-spec.js +260 -0
- package/dist/interactive-spec.js.map +1 -0
- package/dist/interactive-spec.test.d.ts +2 -0
- package/dist/interactive-spec.test.d.ts.map +1 -0
- package/dist/interactive-spec.test.js +308 -0
- package/dist/interactive-spec.test.js.map +1 -0
- package/dist/mcp.d.ts +35 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +86 -0
- package/dist/mcp.js.map +1 -0
- package/dist/mount.d.ts +44 -0
- package/dist/mount.d.ts.map +1 -0
- package/dist/mount.js +51 -0
- package/dist/mount.js.map +1 -0
- package/dist/parse.d.ts +47 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +475 -0
- package/dist/parse.js.map +1 -0
- package/dist/plan.d.ts +118 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +150 -0
- package/dist/plan.js.map +1 -0
- package/dist/plan.test.d.ts +2 -0
- package/dist/plan.test.d.ts.map +1 -0
- package/dist/plan.test.js +191 -0
- package/dist/plan.test.js.map +1 -0
- package/dist/sidecars.d.ts +17 -0
- package/dist/sidecars.d.ts.map +1 -0
- package/dist/sidecars.js +101 -0
- package/dist/sidecars.js.map +1 -0
- package/dist/skill-runner.d.ts +30 -0
- package/dist/skill-runner.d.ts.map +1 -0
- package/dist/skill-runner.js +94 -0
- package/dist/skill-runner.js.map +1 -0
- package/dist/skills.d.ts +41 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +322 -0
- package/dist/skills.js.map +1 -0
- package/dist/types.d.ts +321 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
package/dist/skills.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Harness, PersonaSelection, PersonaSkill, SkillMaterializationOptions, SkillMaterializationPlan, SkillSourceKind } from './types.js';
|
|
2
|
+
interface ResolvedSkillSource {
|
|
3
|
+
kind: SkillSourceKind;
|
|
4
|
+
packageRef: string;
|
|
5
|
+
/** Directory name used for the installed skill (e.g. `npm-trusted-publishing`). */
|
|
6
|
+
installedName: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function resolveSkillSource(source: string): ResolvedSkillSource;
|
|
9
|
+
/**
|
|
10
|
+
* Given a set of persona skills and the harness the persona will run under,
|
|
11
|
+
* produce the concrete install plan: which install invocations to run, where
|
|
12
|
+
* the skill will land on disk, and which artifact paths should be cleaned up
|
|
13
|
+
* after the persona run to keep the workspace tidy.
|
|
14
|
+
*
|
|
15
|
+
* Pure function — does not execute commands or touch the filesystem.
|
|
16
|
+
*/
|
|
17
|
+
export declare function materializeSkills(skills: readonly PersonaSkill[], harness: Harness, options?: SkillMaterializationOptions): SkillMaterializationPlan;
|
|
18
|
+
/**
|
|
19
|
+
* Convenience wrapper: derive the install plan directly from a resolved
|
|
20
|
+
* persona selection, using its tier's harness automatically.
|
|
21
|
+
*/
|
|
22
|
+
export declare function materializeSkillsFor(selection: PersonaSelection, options?: SkillMaterializationOptions): SkillMaterializationPlan;
|
|
23
|
+
export declare function buildInstallArtifacts(plan: SkillMaterializationPlan): {
|
|
24
|
+
installCommand: readonly string[];
|
|
25
|
+
installCommandString: string;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Post-run cleanup: one shell command that removes every ephemeral artifact
|
|
29
|
+
* path declared across all installs in the plan. Runs AFTER the agent step so
|
|
30
|
+
* the agent can still read skill manifests off disk during execution. The
|
|
31
|
+
* provider lockfile is deliberately not in the path set, so repeat runs keep
|
|
32
|
+
* cached resolution.
|
|
33
|
+
*
|
|
34
|
+
* Empty plans return `:` (shell no-op) to keep the post-step shape uniform.
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildCleanupArtifacts(plan: SkillMaterializationPlan): {
|
|
37
|
+
cleanupCommand: readonly string[];
|
|
38
|
+
cleanupCommandString: string;
|
|
39
|
+
};
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=skills.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,gBAAgB,EAChB,YAAY,EAEZ,2BAA2B,EAC3B,wBAAwB,EACxB,eAAe,EAChB,MAAM,YAAY,CAAC;AAmBpB,UAAU,mBAAmB;IAC3B,IAAI,EAAE,eAAe,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,aAAa,EAAE,MAAM,CAAC;CACvB;AA6ID,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CActE;AAUD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,2BAAgC,GACxC,wBAAwB,CAkE1B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,gBAAgB,EAC3B,OAAO,GAAE,2BAAgC,GACxC,wBAAwB,CAE1B;AA0CD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACrE,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CA+CA;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACrE,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAmBA"}
|
package/dist/skills.js
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { HARNESS_SKILL_TARGETS } from './constants.js';
|
|
2
|
+
const PRPM_URL_RE = /^https?:\/\/prpm\.dev\/packages\/([^/\s?#]+)\/([^/\s?#]+)\/?(?:[?#].*)?$/i;
|
|
3
|
+
const PRPM_BARE_REF_RE = /^([^/\s]+)\/([^/\s]+)$/;
|
|
4
|
+
function lastSegment(ref) {
|
|
5
|
+
const slash = ref.lastIndexOf('/');
|
|
6
|
+
return slash >= 0 ? ref.slice(slash + 1) : ref;
|
|
7
|
+
}
|
|
8
|
+
const prpmProvider = {
|
|
9
|
+
kind: 'prpm',
|
|
10
|
+
parse(source) {
|
|
11
|
+
const urlMatch = source.match(PRPM_URL_RE);
|
|
12
|
+
if (urlMatch) {
|
|
13
|
+
const ref = `${urlMatch[1]}/${urlMatch[2]}`;
|
|
14
|
+
return { kind: 'prpm', packageRef: ref, installedName: lastSegment(ref) };
|
|
15
|
+
}
|
|
16
|
+
const bareMatch = source.match(PRPM_BARE_REF_RE);
|
|
17
|
+
if (bareMatch) {
|
|
18
|
+
return { kind: 'prpm', packageRef: source, installedName: lastSegment(source) };
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
},
|
|
22
|
+
buildInstallCommand(ref, harness) {
|
|
23
|
+
const target = HARNESS_SKILL_TARGETS[harness];
|
|
24
|
+
return Object.freeze([
|
|
25
|
+
'npx',
|
|
26
|
+
'-y',
|
|
27
|
+
'prpm',
|
|
28
|
+
'install',
|
|
29
|
+
ref.packageRef,
|
|
30
|
+
'--as',
|
|
31
|
+
target.asFlag
|
|
32
|
+
]);
|
|
33
|
+
},
|
|
34
|
+
cleanupPaths(ref, harness) {
|
|
35
|
+
const target = HARNESS_SKILL_TARGETS[harness];
|
|
36
|
+
return Object.freeze([`${target.dir}/${ref.installedName}`]);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
// skill.sh source forms:
|
|
40
|
+
// - `<github-url>#<skill-name>`
|
|
41
|
+
// - `<github-url>/tree/<ref>/<path-to-skill>`
|
|
42
|
+
// Examples:
|
|
43
|
+
// - `https://github.com/vercel-labs/skills#find-skills`
|
|
44
|
+
// - `https://github.com/wsimmonds/claude-nextjs-skills/tree/main/nextjs-anti-patterns`
|
|
45
|
+
const SKILL_SH_URL_RE = /^(https?:\/\/github\.com\/[^/\s?#]+\/[^/\s?#]+?)(?:\.git)?#([^\s?#]+)$/i;
|
|
46
|
+
const SKILL_SH_TREE_URL_RE = /^(https?:\/\/github\.com\/[^/\s?#]+\/[^/\s?#]+?)(?:\.git)?\/tree\/([^/\s?#]+)\/([^?#]+?)(?:[?#].*)?$/i;
|
|
47
|
+
const SKILL_NAME_RE = /^(?!\.{1,2}$)[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
48
|
+
function toSafeSkillName(raw) {
|
|
49
|
+
const name = raw.trim();
|
|
50
|
+
return SKILL_NAME_RE.test(name) ? name : null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Paths `npx skills add` writes per install. Mirrors the on-disk layout from
|
|
54
|
+
* a live `npx -y skills add ... -y` run (universal dir + harness-side
|
|
55
|
+
* symlinks). `skills-lock.json` is deliberately excluded so repeat runs can
|
|
56
|
+
* re-resolve from the lock instead of refetching sources.
|
|
57
|
+
*/
|
|
58
|
+
function skillShArtifactPaths(installedName) {
|
|
59
|
+
return Object.freeze([
|
|
60
|
+
`.agents/skills/${installedName}`,
|
|
61
|
+
`.claude/skills/${installedName}`,
|
|
62
|
+
`.factory/skills/${installedName}`,
|
|
63
|
+
`.kiro/skills/${installedName}`,
|
|
64
|
+
`skills/${installedName}`
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
const skillShProvider = {
|
|
68
|
+
kind: 'skill.sh',
|
|
69
|
+
parse(source) {
|
|
70
|
+
const match = source.match(SKILL_SH_URL_RE);
|
|
71
|
+
if (match) {
|
|
72
|
+
const [, repoUrl, rawSkillName] = match;
|
|
73
|
+
const skillName = toSafeSkillName(rawSkillName);
|
|
74
|
+
if (!skillName)
|
|
75
|
+
return null;
|
|
76
|
+
return {
|
|
77
|
+
kind: 'skill.sh',
|
|
78
|
+
// packageRef preserves the full `<repo>#<skill>` shape so the command builder
|
|
79
|
+
// can reconstruct both halves without re-parsing the original source.
|
|
80
|
+
packageRef: `${repoUrl}#${skillName}`,
|
|
81
|
+
installedName: skillName
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const treeMatch = source.match(SKILL_SH_TREE_URL_RE);
|
|
85
|
+
if (!treeMatch)
|
|
86
|
+
return null;
|
|
87
|
+
const [, repoUrl, ref, skillPath] = treeMatch;
|
|
88
|
+
const skillName = toSafeSkillName(skillPath.split('/').filter(Boolean).at(-1) ?? '');
|
|
89
|
+
if (!skillName)
|
|
90
|
+
return null;
|
|
91
|
+
return {
|
|
92
|
+
kind: 'skill.sh',
|
|
93
|
+
packageRef: `${repoUrl}/tree/${ref}#${skillName}`,
|
|
94
|
+
installedName: skillName
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
buildInstallCommand(ref) {
|
|
98
|
+
const [repoUrl, skillName] = ref.packageRef.split('#');
|
|
99
|
+
return Object.freeze([
|
|
100
|
+
'npx',
|
|
101
|
+
'-y',
|
|
102
|
+
'skills',
|
|
103
|
+
'add',
|
|
104
|
+
repoUrl,
|
|
105
|
+
'--skill',
|
|
106
|
+
skillName,
|
|
107
|
+
'-y'
|
|
108
|
+
]);
|
|
109
|
+
},
|
|
110
|
+
cleanupPaths(ref) {
|
|
111
|
+
// skill.sh installs the same universal dir + harness symlinks regardless
|
|
112
|
+
// of which agent is the "host" — clean all of them so nothing leaks into
|
|
113
|
+
// `.claude/`, `.agents/`, etc. after the persona run.
|
|
114
|
+
return skillShArtifactPaths(ref.installedName);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const SKILL_PROVIDERS = Object.freeze([prpmProvider, skillShProvider]);
|
|
118
|
+
export function resolveSkillSource(source) {
|
|
119
|
+
for (const provider of SKILL_PROVIDERS) {
|
|
120
|
+
const parsed = provider.parse(source);
|
|
121
|
+
if (parsed) {
|
|
122
|
+
return parsed;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
throw new Error(`Unsupported skill source: ${source}. ` +
|
|
126
|
+
`Supported forms: prpm.dev package URL (https://prpm.dev/packages/<scope>/<name>), ` +
|
|
127
|
+
`bare "<scope>/<name>" prpm reference, ` +
|
|
128
|
+
`skill.sh github URL with skill fragment (https://github.com/<org>/<repo>#<skill>), ` +
|
|
129
|
+
`or GitHub tree URL to a skill directory (https://github.com/<org>/<repo>/tree/<ref>/<skill>).`);
|
|
130
|
+
}
|
|
131
|
+
function providerFor(kind) {
|
|
132
|
+
const provider = SKILL_PROVIDERS.find((p) => p.kind === kind);
|
|
133
|
+
if (!provider) {
|
|
134
|
+
throw new Error(`No skill provider registered for kind: ${kind}`);
|
|
135
|
+
}
|
|
136
|
+
return provider;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Given a set of persona skills and the harness the persona will run under,
|
|
140
|
+
* produce the concrete install plan: which install invocations to run, where
|
|
141
|
+
* the skill will land on disk, and which artifact paths should be cleaned up
|
|
142
|
+
* after the persona run to keep the workspace tidy.
|
|
143
|
+
*
|
|
144
|
+
* Pure function — does not execute commands or touch the filesystem.
|
|
145
|
+
*/
|
|
146
|
+
export function materializeSkills(skills, harness, options = {}) {
|
|
147
|
+
const target = HARNESS_SKILL_TARGETS[harness];
|
|
148
|
+
if (!target) {
|
|
149
|
+
throw new Error(`No skill install target configured for harness: ${harness}`);
|
|
150
|
+
}
|
|
151
|
+
const { installRoot } = options;
|
|
152
|
+
if (installRoot !== undefined && harness !== 'claude') {
|
|
153
|
+
throw new Error(`installRoot is only supported for the claude harness (got: ${harness}). ` +
|
|
154
|
+
`codex and opencode still install into the harness's conventional repo-relative directory.`);
|
|
155
|
+
}
|
|
156
|
+
const installs = skills.map((skill) => {
|
|
157
|
+
const resolved = resolveSkillSource(skill.source);
|
|
158
|
+
const provider = providerFor(resolved.kind);
|
|
159
|
+
const baseCommand = provider.buildInstallCommand(resolved, harness);
|
|
160
|
+
// In session-install-root mode, the install runs `cd <installRoot> && <prpm>`
|
|
161
|
+
// so that prpm's harness-relative dirs (`.claude/skills/<name>`) land
|
|
162
|
+
// inside the stage dir instead of the user's repo. The per-install command
|
|
163
|
+
// stays self-contained so callers who run a single install.installCommand
|
|
164
|
+
// directly still get the correct placement.
|
|
165
|
+
const installCommand = installRoot !== undefined
|
|
166
|
+
? Object.freeze([
|
|
167
|
+
'sh',
|
|
168
|
+
'-c',
|
|
169
|
+
`cd ${shellEscape(installRoot)} && ${commandToShellString(baseCommand)}`
|
|
170
|
+
])
|
|
171
|
+
: baseCommand;
|
|
172
|
+
// For prompt-injection fallback we still want a single canonical manifest
|
|
173
|
+
// path. prpm installs into the harness target dir; skill.sh installs into
|
|
174
|
+
// its universal `.agents/skills` dir regardless of harness, so key off
|
|
175
|
+
// whichever cleanup path ends in the installed name.
|
|
176
|
+
const repoRelativeDir = resolved.kind === 'skill.sh'
|
|
177
|
+
? `.agents/skills/${resolved.installedName}`
|
|
178
|
+
: `${target.dir}/${resolved.installedName}`;
|
|
179
|
+
const installedDir = installRoot !== undefined ? `${installRoot}/${repoRelativeDir}` : repoRelativeDir;
|
|
180
|
+
// When the plan stages into `installRoot`, cleanup targets the whole
|
|
181
|
+
// session dir (handled at plan level in buildCleanupArtifacts). Leave
|
|
182
|
+
// per-skill cleanupPaths empty so callers running individual
|
|
183
|
+
// install.cleanupPaths don't accidentally remove unrelated things.
|
|
184
|
+
const cleanupPaths = installRoot !== undefined
|
|
185
|
+
? Object.freeze([])
|
|
186
|
+
: provider.cleanupPaths(resolved, harness);
|
|
187
|
+
return {
|
|
188
|
+
skillId: skill.id,
|
|
189
|
+
source: skill.source,
|
|
190
|
+
sourceKind: resolved.kind,
|
|
191
|
+
packageRef: resolved.packageRef,
|
|
192
|
+
harness,
|
|
193
|
+
installCommand,
|
|
194
|
+
installedDir,
|
|
195
|
+
installedManifest: `${installedDir}/SKILL.md`,
|
|
196
|
+
cleanupPaths
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
return {
|
|
200
|
+
harness,
|
|
201
|
+
installs,
|
|
202
|
+
...(installRoot !== undefined ? { sessionInstallRoot: installRoot } : {})
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Convenience wrapper: derive the install plan directly from a resolved
|
|
207
|
+
* persona selection, using its tier's harness automatically.
|
|
208
|
+
*/
|
|
209
|
+
export function materializeSkillsFor(selection, options = {}) {
|
|
210
|
+
return materializeSkills(selection.skills, selection.runtime.harness, options);
|
|
211
|
+
}
|
|
212
|
+
function shellEscape(value) {
|
|
213
|
+
if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(value)) {
|
|
214
|
+
return value;
|
|
215
|
+
}
|
|
216
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
217
|
+
}
|
|
218
|
+
function commandToShellString(command) {
|
|
219
|
+
return command.map(shellEscape).join(' ');
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Minimal Claude Code plugin manifest written to `<root>/.claude-plugin/plugin.json`
|
|
223
|
+
* in session-install-root mode. Claude's plugin loader treats any directory
|
|
224
|
+
* that contains this file (alongside a `skills/` tree) as a plugin; we pass
|
|
225
|
+
* the root to `claude --plugin-dir <root>` so the session sees exactly the
|
|
226
|
+
* skills we staged — and nothing the repo happens to carry.
|
|
227
|
+
*/
|
|
228
|
+
const SESSION_PLUGIN_MANIFEST = JSON.stringify({
|
|
229
|
+
name: 'agent-workforce-session',
|
|
230
|
+
version: '0.0.0',
|
|
231
|
+
description: 'Ephemeral skills staged by agent-workforce for this session.'
|
|
232
|
+
});
|
|
233
|
+
function buildSessionScaffoldCommand(root) {
|
|
234
|
+
const q = shellEscape(root);
|
|
235
|
+
// mkdir -p creates both the plugin metadata dir and the prpm target.
|
|
236
|
+
// `ln -sfn .claude/skills skills` makes Claude's expected plugin layout
|
|
237
|
+
// (`<root>/skills/<name>/SKILL.md`) resolve to prpm's actual output
|
|
238
|
+
// (`<root>/.claude/skills/<name>/SKILL.md`) without moving any files.
|
|
239
|
+
// The -n guards against following into an existing `skills/` dir (e.g.
|
|
240
|
+
// when the session dir is reused), and -f replaces a prior symlink so
|
|
241
|
+
// the scaffold is idempotent.
|
|
242
|
+
return [
|
|
243
|
+
`mkdir -p ${q}/.claude-plugin ${q}/.claude/skills`,
|
|
244
|
+
`ln -sfn .claude/skills ${q}/skills`,
|
|
245
|
+
`printf '%s' ${shellEscape(SESSION_PLUGIN_MANIFEST)} > ${q}/.claude-plugin/plugin.json`
|
|
246
|
+
].join(' && ');
|
|
247
|
+
}
|
|
248
|
+
export function buildInstallArtifacts(plan) {
|
|
249
|
+
if (plan.sessionInstallRoot !== undefined) {
|
|
250
|
+
// Session mode always stages a plugin dir so the caller can pass
|
|
251
|
+
// `--plugin-dir <root>` to claude unconditionally. Even for personas
|
|
252
|
+
// with zero skills, we emit the scaffold (mkdir + manifest + symlink)
|
|
253
|
+
// so the `--plugin-dir` target exists.
|
|
254
|
+
const root = plan.sessionInstallRoot;
|
|
255
|
+
const scaffold = buildSessionScaffoldCommand(root);
|
|
256
|
+
if (plan.installs.length === 0) {
|
|
257
|
+
return {
|
|
258
|
+
installCommand: Object.freeze(['sh', '-c', scaffold]),
|
|
259
|
+
installCommandString: scaffold
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
// Chain the raw provider commands after a single `cd <root>` so we emit
|
|
263
|
+
// one shell invocation instead of repeating the cd per skill. Each
|
|
264
|
+
// install.installCommand is already self-contained (`sh -c 'cd <root> &&
|
|
265
|
+
// …'`) for callers who want to run one at a time, but here we flatten
|
|
266
|
+
// to the underlying prpm argv for a cleaner chain.
|
|
267
|
+
const perSkill = plan.installs
|
|
268
|
+
.map((install) => {
|
|
269
|
+
const resolved = resolveSkillSource(install.source);
|
|
270
|
+
const provider = providerFor(resolved.kind);
|
|
271
|
+
return commandToShellString(provider.buildInstallCommand(resolved, plan.harness));
|
|
272
|
+
})
|
|
273
|
+
.join(' && ');
|
|
274
|
+
const installCommandString = `${scaffold} && cd ${shellEscape(root)} && ${perSkill}`;
|
|
275
|
+
return {
|
|
276
|
+
installCommand: Object.freeze(['sh', '-c', installCommandString]),
|
|
277
|
+
installCommandString
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
if (plan.installs.length === 0) {
|
|
281
|
+
return {
|
|
282
|
+
installCommand: Object.freeze(['sh', '-c', ':']),
|
|
283
|
+
installCommandString: ':'
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
const installCommandString = plan.installs
|
|
287
|
+
.map((install) => commandToShellString(install.installCommand))
|
|
288
|
+
.join(' && ');
|
|
289
|
+
return {
|
|
290
|
+
installCommand: Object.freeze(['sh', '-c', installCommandString]),
|
|
291
|
+
installCommandString
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Post-run cleanup: one shell command that removes every ephemeral artifact
|
|
296
|
+
* path declared across all installs in the plan. Runs AFTER the agent step so
|
|
297
|
+
* the agent can still read skill manifests off disk during execution. The
|
|
298
|
+
* provider lockfile is deliberately not in the path set, so repeat runs keep
|
|
299
|
+
* cached resolution.
|
|
300
|
+
*
|
|
301
|
+
* Empty plans return `:` (shell no-op) to keep the post-step shape uniform.
|
|
302
|
+
*/
|
|
303
|
+
export function buildCleanupArtifacts(plan) {
|
|
304
|
+
// Session mode: cleanup is the whole stage dir. The scaffold always runs
|
|
305
|
+
// (even for zero-skill personas), so cleanup unconditionally drops the
|
|
306
|
+
// stage dir. The CLI is responsible for removing the enclosing session
|
|
307
|
+
// root; this command covers the install subtree.
|
|
308
|
+
if (plan.sessionInstallRoot !== undefined) {
|
|
309
|
+
const cleanupCommandString = `rm -rf ${shellEscape(plan.sessionInstallRoot)}`;
|
|
310
|
+
return {
|
|
311
|
+
cleanupCommand: Object.freeze(['sh', '-c', cleanupCommandString]),
|
|
312
|
+
cleanupCommandString
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
const allPaths = plan.installs.flatMap((install) => [...install.cleanupPaths]);
|
|
316
|
+
const cleanupCommandString = allPaths.length === 0 ? ':' : `rm -rf ${allPaths.map(shellEscape).join(' ')}`;
|
|
317
|
+
return {
|
|
318
|
+
cleanupCommand: Object.freeze(['sh', '-c', cleanupCommandString]),
|
|
319
|
+
cleanupCommandString
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"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"}
|