@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/plan.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { buildInteractiveSpec } from './interactive-spec.js';
|
|
2
|
+
import { resolvePersonaInputs, renderPersonaInputs } from './inputs.js';
|
|
3
|
+
import { materializeSkills } from './skills.js';
|
|
4
|
+
function resolvedInputBindings(inputs, values) {
|
|
5
|
+
if (!inputs)
|
|
6
|
+
return [];
|
|
7
|
+
return Object.entries(inputs)
|
|
8
|
+
.filter(([name]) => values[name] !== undefined)
|
|
9
|
+
.map(([name, spec]) => ({
|
|
10
|
+
name,
|
|
11
|
+
envName: spec.env ?? name,
|
|
12
|
+
value: values[name]
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
function resolveSidecarWrite(selection) {
|
|
16
|
+
const harness = selection.runtime.harness;
|
|
17
|
+
if (harness === 'claude') {
|
|
18
|
+
if (selection.claudeMdContent !== undefined) {
|
|
19
|
+
return [
|
|
20
|
+
{
|
|
21
|
+
filename: 'CLAUDE.md',
|
|
22
|
+
contents: selection.claudeMdContent,
|
|
23
|
+
mode: selection.claudeMdMode ?? 'overwrite'
|
|
24
|
+
}
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
if (selection.claudeMd) {
|
|
28
|
+
return [
|
|
29
|
+
{
|
|
30
|
+
filename: 'CLAUDE.md',
|
|
31
|
+
sourcePath: selection.claudeMd,
|
|
32
|
+
mode: selection.claudeMdMode ?? 'overwrite'
|
|
33
|
+
}
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
if (harness === 'opencode' || harness === 'codex') {
|
|
39
|
+
if (selection.agentsMdContent !== undefined) {
|
|
40
|
+
return [
|
|
41
|
+
{
|
|
42
|
+
filename: 'AGENTS.md',
|
|
43
|
+
contents: selection.agentsMdContent,
|
|
44
|
+
mode: selection.agentsMdMode ?? 'overwrite'
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
if (selection.agentsMd) {
|
|
49
|
+
return [
|
|
50
|
+
{
|
|
51
|
+
filename: 'AGENTS.md',
|
|
52
|
+
sourcePath: selection.agentsMd,
|
|
53
|
+
mode: selection.agentsMdMode ?? 'overwrite'
|
|
54
|
+
}
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
function resolveMountPolicy(mount) {
|
|
62
|
+
if (!mount)
|
|
63
|
+
return undefined;
|
|
64
|
+
const ignored = mount.ignoredPatterns ?? [];
|
|
65
|
+
const readonly = mount.readonlyPatterns ?? [];
|
|
66
|
+
if (ignored.length === 0 && readonly.length === 0)
|
|
67
|
+
return undefined;
|
|
68
|
+
return {
|
|
69
|
+
ignoredPatterns: [...ignored],
|
|
70
|
+
readonlyPatterns: [...readonly]
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Pure plan builder. Composes existing persona-kit helpers
|
|
75
|
+
* ({@link buildInteractiveSpec}, {@link materializeSkills},
|
|
76
|
+
* {@link resolvePersonaInputs}) into a single inspectable
|
|
77
|
+
* {@link PersonaSpawnPlan}. Does **no** filesystem writes and spawns no
|
|
78
|
+
* subprocesses.
|
|
79
|
+
*
|
|
80
|
+
* The returned plan is JSON-serializable: every field is a plain value or
|
|
81
|
+
* primitive array. Callers can stamp it into launch metadata, send it across
|
|
82
|
+
* a wire, or hand it to {@link import('./execute.js').executePersonaSpawnPlan}.
|
|
83
|
+
*/
|
|
84
|
+
export function buildPersonaSpawnPlan(persona, options = {}) {
|
|
85
|
+
const harness = persona.runtime.harness;
|
|
86
|
+
// Input env-var fallbacks read from `processEnv` only when ambient capture
|
|
87
|
+
// is opted into. With ambient capture off, `resolvePersonaInputs` sees an
|
|
88
|
+
// empty env and inputs must resolve from explicit values, persona
|
|
89
|
+
// `inputValues`, or `default` — keeping plans deterministic across hosts.
|
|
90
|
+
const processEnv = options.processEnv ?? (options.includeProcessEnv ? process.env : {});
|
|
91
|
+
const inputResolution = resolvePersonaInputs(persona.inputs ?? persona.inputValues
|
|
92
|
+
? persona.inputs ?? undefined
|
|
93
|
+
: undefined, options.inputValues ?? persona.inputValues, processEnv);
|
|
94
|
+
const renderedSystemPrompt = renderPersonaInputs(persona.runtime.systemPrompt, inputResolution.values);
|
|
95
|
+
const skills = materializeSkills(persona.skills, harness, options.installRoot !== undefined ? { installRoot: options.installRoot } : {});
|
|
96
|
+
const spec = buildInteractiveSpec({
|
|
97
|
+
harness,
|
|
98
|
+
personaId: persona.personaId,
|
|
99
|
+
model: persona.runtime.model,
|
|
100
|
+
systemPrompt: renderedSystemPrompt,
|
|
101
|
+
...(persona.mcpServers ? { mcpServers: persona.mcpServers } : {}),
|
|
102
|
+
...(persona.permissions ? { permissions: persona.permissions } : {}),
|
|
103
|
+
...(persona.runtime.harnessSettings
|
|
104
|
+
? { harnessSettings: persona.runtime.harnessSettings }
|
|
105
|
+
: {}),
|
|
106
|
+
...(skills.sessionInstallRoot
|
|
107
|
+
? { pluginDirs: [skills.sessionInstallRoot] }
|
|
108
|
+
: {})
|
|
109
|
+
});
|
|
110
|
+
const inputBindings = resolvedInputBindings(persona.inputs, inputResolution.values);
|
|
111
|
+
const sidecars = resolveSidecarWrite(persona);
|
|
112
|
+
const mount = resolveMountPolicy(persona.mount);
|
|
113
|
+
// Env precedence (later wins):
|
|
114
|
+
// ambient processEnv (opt-in)
|
|
115
|
+
// → resolved input bindings
|
|
116
|
+
// → caller envOverrides
|
|
117
|
+
// → persona-author env
|
|
118
|
+
//
|
|
119
|
+
// Ambient capture is opt-in to keep secrets out of the JSON-serializable
|
|
120
|
+
// plan by default — callers must pass `includeProcessEnv: true` (or supply
|
|
121
|
+
// a curated `processEnv` snapshot) to forward ambient values.
|
|
122
|
+
const env = {};
|
|
123
|
+
const ambientSource = options.processEnv ?? (options.includeProcessEnv ? process.env : undefined);
|
|
124
|
+
if (ambientSource) {
|
|
125
|
+
for (const [k, v] of Object.entries(ambientSource)) {
|
|
126
|
+
if (typeof v === 'string')
|
|
127
|
+
env[k] = v;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
for (const binding of inputBindings)
|
|
131
|
+
env[binding.envName] = binding.value;
|
|
132
|
+
if (options.envOverrides)
|
|
133
|
+
Object.assign(env, options.envOverrides);
|
|
134
|
+
if (persona.env)
|
|
135
|
+
Object.assign(env, persona.env);
|
|
136
|
+
const plan = {
|
|
137
|
+
persona,
|
|
138
|
+
cli: harness,
|
|
139
|
+
args: [...spec.args],
|
|
140
|
+
configFiles: spec.configFiles.map((f) => ({ path: f.path, contents: f.contents })),
|
|
141
|
+
skills,
|
|
142
|
+
sidecars,
|
|
143
|
+
inputs: inputBindings,
|
|
144
|
+
env,
|
|
145
|
+
...(spec.initialPrompt !== null ? { initialPrompt: spec.initialPrompt } : {}),
|
|
146
|
+
...(mount ? { mount } : {})
|
|
147
|
+
};
|
|
148
|
+
return plan;
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=plan.js.map
|
package/dist/plan.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.test.d.ts","sourceRoot":"","sources":["../src/plan.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { buildPersonaSpawnPlan } from './plan.js';
|
|
4
|
+
function persona(over = {}) {
|
|
5
|
+
return {
|
|
6
|
+
personaId: 'p',
|
|
7
|
+
tier: 'best-value',
|
|
8
|
+
runtime: {
|
|
9
|
+
harness: 'claude',
|
|
10
|
+
model: 'anthropic/claude-3-5-sonnet',
|
|
11
|
+
systemPrompt: 'be helpful',
|
|
12
|
+
harnessSettings: { reasoning: 'medium', timeoutSeconds: 300 }
|
|
13
|
+
},
|
|
14
|
+
skills: [],
|
|
15
|
+
rationale: 'test',
|
|
16
|
+
...over
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const cleanEnv = Object.freeze({});
|
|
20
|
+
test('buildPersonaSpawnPlan returns the persona, cli, and args for claude', () => {
|
|
21
|
+
const plan = buildPersonaSpawnPlan(persona(), { processEnv: cleanEnv });
|
|
22
|
+
assert.equal(plan.cli, 'claude');
|
|
23
|
+
assert.ok(plan.args.length > 0);
|
|
24
|
+
assert.equal(plan.persona.personaId, 'p');
|
|
25
|
+
assert.deepEqual(plan.skills.installs, []);
|
|
26
|
+
assert.deepEqual(plan.sidecars, []);
|
|
27
|
+
assert.equal(plan.mount, undefined);
|
|
28
|
+
assert.deepEqual(plan.inputs, []);
|
|
29
|
+
assert.equal(plan.initialPrompt, undefined);
|
|
30
|
+
});
|
|
31
|
+
test('buildPersonaSpawnPlan emits initialPrompt for codex', () => {
|
|
32
|
+
const plan = buildPersonaSpawnPlan(persona({
|
|
33
|
+
runtime: {
|
|
34
|
+
harness: 'codex',
|
|
35
|
+
model: 'openai/gpt-5',
|
|
36
|
+
systemPrompt: 'codex prompt',
|
|
37
|
+
harnessSettings: { reasoning: 'medium', timeoutSeconds: 300 }
|
|
38
|
+
}
|
|
39
|
+
}), { processEnv: cleanEnv });
|
|
40
|
+
assert.equal(plan.cli, 'codex');
|
|
41
|
+
assert.equal(plan.initialPrompt, 'codex prompt');
|
|
42
|
+
});
|
|
43
|
+
test('buildPersonaSpawnPlan emits configFiles for opencode', () => {
|
|
44
|
+
const plan = buildPersonaSpawnPlan(persona({
|
|
45
|
+
personaId: 'sample',
|
|
46
|
+
runtime: {
|
|
47
|
+
harness: 'opencode',
|
|
48
|
+
model: 'anthropic/claude-3-5-sonnet',
|
|
49
|
+
systemPrompt: 'opencode prompt',
|
|
50
|
+
harnessSettings: { reasoning: 'medium', timeoutSeconds: 300 }
|
|
51
|
+
}
|
|
52
|
+
}), { processEnv: cleanEnv });
|
|
53
|
+
assert.equal(plan.cli, 'opencode');
|
|
54
|
+
assert.ok(plan.configFiles.some((f) => f.path.endsWith('opencode.json')), 'opencode plan must emit an opencode.json');
|
|
55
|
+
});
|
|
56
|
+
test('buildPersonaSpawnPlan resolves sidecars from claudeMdContent / agentsMdContent', () => {
|
|
57
|
+
const claudePlan = buildPersonaSpawnPlan(persona({
|
|
58
|
+
claudeMdContent: '# claude sidecar',
|
|
59
|
+
claudeMdMode: 'overwrite'
|
|
60
|
+
}), { processEnv: cleanEnv });
|
|
61
|
+
assert.equal(claudePlan.sidecars.length, 1);
|
|
62
|
+
assert.equal(claudePlan.sidecars[0].filename, 'CLAUDE.md');
|
|
63
|
+
assert.equal(claudePlan.sidecars[0].contents, '# claude sidecar');
|
|
64
|
+
const opencodePlan = buildPersonaSpawnPlan(persona({
|
|
65
|
+
agentsMdContent: '# agents sidecar',
|
|
66
|
+
agentsMdMode: 'extend',
|
|
67
|
+
runtime: {
|
|
68
|
+
harness: 'opencode',
|
|
69
|
+
model: 'anthropic/claude-3-5-sonnet',
|
|
70
|
+
systemPrompt: 'be helpful',
|
|
71
|
+
harnessSettings: { reasoning: 'medium', timeoutSeconds: 300 }
|
|
72
|
+
}
|
|
73
|
+
}), { processEnv: cleanEnv });
|
|
74
|
+
assert.equal(opencodePlan.sidecars.length, 1);
|
|
75
|
+
assert.equal(opencodePlan.sidecars[0].filename, 'AGENTS.md');
|
|
76
|
+
assert.equal(opencodePlan.sidecars[0].mode, 'extend');
|
|
77
|
+
});
|
|
78
|
+
test('buildPersonaSpawnPlan threads mount policy through when patterns present', () => {
|
|
79
|
+
const plan = buildPersonaSpawnPlan(persona({
|
|
80
|
+
mount: { ignoredPatterns: ['secrets/**'], readonlyPatterns: ['vendor/**'] }
|
|
81
|
+
}), { processEnv: cleanEnv });
|
|
82
|
+
assert.deepEqual(plan.mount?.ignoredPatterns, ['secrets/**']);
|
|
83
|
+
assert.deepEqual(plan.mount?.readonlyPatterns, ['vendor/**']);
|
|
84
|
+
});
|
|
85
|
+
test('buildPersonaSpawnPlan drops empty mount policy', () => {
|
|
86
|
+
const plan = buildPersonaSpawnPlan(persona({ mount: {} }), { processEnv: cleanEnv });
|
|
87
|
+
assert.equal(plan.mount, undefined);
|
|
88
|
+
});
|
|
89
|
+
test('buildPersonaSpawnPlan resolves inputs into env bindings', () => {
|
|
90
|
+
const plan = buildPersonaSpawnPlan(persona({
|
|
91
|
+
inputs: {
|
|
92
|
+
OUTPUT_PATH: { default: '/tmp/out' },
|
|
93
|
+
TARGET: { env: 'TARGET_OVERRIDE' }
|
|
94
|
+
}
|
|
95
|
+
}), { processEnv: { TARGET_OVERRIDE: 'frobnicate' } });
|
|
96
|
+
const byName = Object.fromEntries(plan.inputs.map((b) => [b.name, b]));
|
|
97
|
+
assert.equal(byName.OUTPUT_PATH.envName, 'OUTPUT_PATH');
|
|
98
|
+
assert.equal(byName.OUTPUT_PATH.value, '/tmp/out');
|
|
99
|
+
assert.equal(byName.TARGET.envName, 'TARGET_OVERRIDE');
|
|
100
|
+
assert.equal(byName.TARGET.value, 'frobnicate');
|
|
101
|
+
assert.equal(plan.env.OUTPUT_PATH, '/tmp/out');
|
|
102
|
+
assert.equal(plan.env.TARGET_OVERRIDE, 'frobnicate');
|
|
103
|
+
});
|
|
104
|
+
test('buildPersonaSpawnPlan persona env wins over inputs and overrides', () => {
|
|
105
|
+
const plan = buildPersonaSpawnPlan(persona({
|
|
106
|
+
env: { FOO: 'persona-wins' },
|
|
107
|
+
inputs: { FOO: { default: 'from-input' } }
|
|
108
|
+
}), {
|
|
109
|
+
processEnv: cleanEnv,
|
|
110
|
+
envOverrides: { FOO: 'override-value' }
|
|
111
|
+
});
|
|
112
|
+
assert.equal(plan.env.FOO, 'persona-wins');
|
|
113
|
+
});
|
|
114
|
+
test('buildPersonaSpawnPlan is JSON-serializable', () => {
|
|
115
|
+
const plan = buildPersonaSpawnPlan(persona({
|
|
116
|
+
claudeMdContent: '# sidecar',
|
|
117
|
+
mount: { ignoredPatterns: ['x'] },
|
|
118
|
+
env: { FOO: 'bar' }
|
|
119
|
+
}), { processEnv: cleanEnv });
|
|
120
|
+
const round = JSON.parse(JSON.stringify(plan));
|
|
121
|
+
assert.deepEqual(round.cli, plan.cli);
|
|
122
|
+
assert.deepEqual(round.args, plan.args);
|
|
123
|
+
assert.deepEqual(round.sidecars, plan.sidecars);
|
|
124
|
+
assert.deepEqual(round.mount, plan.mount);
|
|
125
|
+
assert.deepEqual(round.env, plan.env);
|
|
126
|
+
});
|
|
127
|
+
test('buildPersonaSpawnPlan threads installRoot into the skill plan', () => {
|
|
128
|
+
const plan = buildPersonaSpawnPlan(persona({
|
|
129
|
+
skills: [
|
|
130
|
+
{
|
|
131
|
+
id: 'prpm/x',
|
|
132
|
+
source: '@scope/x',
|
|
133
|
+
description: 'd'
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}), { processEnv: cleanEnv, installRoot: '/tmp/session/plugin' });
|
|
137
|
+
assert.equal(plan.skills.sessionInstallRoot, '/tmp/session/plugin');
|
|
138
|
+
// Plugin dirs flow through into the claude argv.
|
|
139
|
+
assert.ok(plan.args.some((arg) => arg === '/tmp/session/plugin'), 'plugin-dir from installRoot should appear in claude argv');
|
|
140
|
+
});
|
|
141
|
+
test('buildPersonaSpawnPlan emits sourcePath when only claudeMd path is set', () => {
|
|
142
|
+
const plan = buildPersonaSpawnPlan(persona({ claudeMd: '/abs/path/to/CLAUDE.md', claudeMdMode: 'extend' }), { processEnv: cleanEnv });
|
|
143
|
+
assert.equal(plan.sidecars.length, 1);
|
|
144
|
+
assert.equal(plan.sidecars[0].filename, 'CLAUDE.md');
|
|
145
|
+
assert.equal(plan.sidecars[0].sourcePath, '/abs/path/to/CLAUDE.md');
|
|
146
|
+
assert.equal(plan.sidecars[0].contents, undefined);
|
|
147
|
+
assert.equal(plan.sidecars[0].mode, 'extend');
|
|
148
|
+
});
|
|
149
|
+
test('buildPersonaSpawnPlan emits sourcePath for opencode/codex agentsMd path', () => {
|
|
150
|
+
const plan = buildPersonaSpawnPlan(persona({
|
|
151
|
+
runtime: {
|
|
152
|
+
harness: 'opencode',
|
|
153
|
+
model: 'm',
|
|
154
|
+
systemPrompt: 's',
|
|
155
|
+
harnessSettings: { reasoning: 'medium', timeoutSeconds: 300 }
|
|
156
|
+
},
|
|
157
|
+
agentsMd: '/abs/path/to/AGENTS.md'
|
|
158
|
+
}), { processEnv: cleanEnv });
|
|
159
|
+
assert.equal(plan.sidecars.length, 1);
|
|
160
|
+
assert.equal(plan.sidecars[0].sourcePath, '/abs/path/to/AGENTS.md');
|
|
161
|
+
});
|
|
162
|
+
test('buildPersonaSpawnPlan does not capture ambient env by default', () => {
|
|
163
|
+
// No processEnv or includeProcessEnv — plan.env should only carry persona/input bindings.
|
|
164
|
+
const plan = buildPersonaSpawnPlan(persona({ env: { ONLY: 'persona' } }));
|
|
165
|
+
assert.deepEqual(plan.env, { ONLY: 'persona' });
|
|
166
|
+
});
|
|
167
|
+
test('buildPersonaSpawnPlan opt-in includeProcessEnv captures process.env', () => {
|
|
168
|
+
const sentinel = `__PK_TEST_${Date.now()}_${Math.random()}__`;
|
|
169
|
+
process.env[sentinel] = 'on';
|
|
170
|
+
try {
|
|
171
|
+
const plan = buildPersonaSpawnPlan(persona(), { includeProcessEnv: true });
|
|
172
|
+
assert.equal(plan.env[sentinel], 'on');
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
delete process.env[sentinel];
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
test('buildPersonaSpawnPlan empty-skills case keeps installs empty', () => {
|
|
179
|
+
for (const harness of ['claude', 'codex', 'opencode']) {
|
|
180
|
+
const plan = buildPersonaSpawnPlan(persona({
|
|
181
|
+
runtime: {
|
|
182
|
+
harness,
|
|
183
|
+
model: 'm',
|
|
184
|
+
systemPrompt: 's',
|
|
185
|
+
harnessSettings: { reasoning: 'medium', timeoutSeconds: 300 }
|
|
186
|
+
}
|
|
187
|
+
}), { processEnv: cleanEnv });
|
|
188
|
+
assert.equal(plan.skills.installs.length, 0, `harness ${harness}`);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
//# sourceMappingURL=plan.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.test.js","sourceRoot":"","sources":["../src/plan.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ResolvedSidecarWrite } from './plan.js';
|
|
2
|
+
export interface PersonaSidecarHandle {
|
|
3
|
+
/** Reverse the write. Idempotent; safe to call twice. */
|
|
4
|
+
dispose(): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Write each sidecar to `<cwd>/<filename>`. In `extend` mode the persona body
|
|
8
|
+
* is appended to the existing on-disk content (joined with `\n\n---\n\n`). In
|
|
9
|
+
* `overwrite` mode the file is replaced. Path-backed sidecars
|
|
10
|
+
* ({@link ResolvedSidecarWrite.sourcePath}) are read at this point, so the
|
|
11
|
+
* plan stays JSON-serializable. The returned handle restores every touched
|
|
12
|
+
* file to its prior state on `dispose()`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function writePersonaSidecars(sidecars: readonly ResolvedSidecarWrite[], options: {
|
|
15
|
+
cwd: string;
|
|
16
|
+
}): Promise<PersonaSidecarHandle>;
|
|
17
|
+
//# sourceMappingURL=sidecars.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidecars.d.ts","sourceRoot":"","sources":["../src/sidecars.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAyDD;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,EACzC,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GACvB,OAAO,CAAC,oBAAoB,CAAC,CA2B/B"}
|
package/dist/sidecars.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { readFile, writeFile, unlink } from 'node:fs/promises';
|
|
2
|
+
import { basename, isAbsolute, join } from 'node:path';
|
|
3
|
+
const SIDECAR_DELIMITER = '\n\n---\n\n';
|
|
4
|
+
/**
|
|
5
|
+
* The plan's filename is typed `'CLAUDE.md' | 'AGENTS.md'` at compile time,
|
|
6
|
+
* but plans can be JSON-deserialized from untrusted sources at runtime.
|
|
7
|
+
* Bound to safe basenames here so a hand-built or tampered plan cannot
|
|
8
|
+
* escape `cwd` via `..` or absolute path segments.
|
|
9
|
+
*/
|
|
10
|
+
function assertSafeSidecarFilename(filename) {
|
|
11
|
+
if (!filename)
|
|
12
|
+
throw new Error('sidecar filename must be non-empty');
|
|
13
|
+
if (isAbsolute(filename)) {
|
|
14
|
+
throw new Error(`sidecar filename must be relative; got ${JSON.stringify(filename)}`);
|
|
15
|
+
}
|
|
16
|
+
if (basename(filename) !== filename) {
|
|
17
|
+
throw new Error(`sidecar filename must be a basename (no directory segments); got ${JSON.stringify(filename)}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function readIfExists(path) {
|
|
21
|
+
try {
|
|
22
|
+
return await readFile(path, 'utf8');
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (err.code === 'ENOENT')
|
|
26
|
+
return null;
|
|
27
|
+
throw err;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function loadSidecarBody(sidecar) {
|
|
31
|
+
if (sidecar.contents !== undefined)
|
|
32
|
+
return sidecar.contents;
|
|
33
|
+
if (sidecar.sourcePath !== undefined) {
|
|
34
|
+
if (!isAbsolute(sidecar.sourcePath)) {
|
|
35
|
+
throw new Error(`ResolvedSidecarWrite.sourcePath must be absolute; got ${JSON.stringify(sidecar.sourcePath)}`);
|
|
36
|
+
}
|
|
37
|
+
return readFile(sidecar.sourcePath, 'utf8');
|
|
38
|
+
}
|
|
39
|
+
// Type system already enforces this; the runtime check keeps the message
|
|
40
|
+
// clear if a hand-built plan slips through.
|
|
41
|
+
const probe = sidecar;
|
|
42
|
+
throw new Error(`ResolvedSidecarWrite for ${probe.filename ?? '<unknown>'} must supply either contents or sourcePath.`);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Write each sidecar to `<cwd>/<filename>`. In `extend` mode the persona body
|
|
46
|
+
* is appended to the existing on-disk content (joined with `\n\n---\n\n`). In
|
|
47
|
+
* `overwrite` mode the file is replaced. Path-backed sidecars
|
|
48
|
+
* ({@link ResolvedSidecarWrite.sourcePath}) are read at this point, so the
|
|
49
|
+
* plan stays JSON-serializable. The returned handle restores every touched
|
|
50
|
+
* file to its prior state on `dispose()`.
|
|
51
|
+
*/
|
|
52
|
+
export async function writePersonaSidecars(sidecars, options) {
|
|
53
|
+
const restored = [];
|
|
54
|
+
let disposed = false;
|
|
55
|
+
try {
|
|
56
|
+
for (const sidecar of sidecars) {
|
|
57
|
+
assertSafeSidecarFilename(sidecar.filename);
|
|
58
|
+
const target = join(options.cwd, sidecar.filename);
|
|
59
|
+
const personaBody = await loadSidecarBody(sidecar);
|
|
60
|
+
const prior = await readIfExists(target);
|
|
61
|
+
restored.push({ path: target, prior });
|
|
62
|
+
const body = sidecar.mode === 'extend' && prior !== null
|
|
63
|
+
? `${prior}${SIDECAR_DELIMITER}${personaBody}`
|
|
64
|
+
: personaBody;
|
|
65
|
+
await writeFile(target, body, 'utf8');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
await disposeRestored(restored);
|
|
70
|
+
throw err;
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
async dispose() {
|
|
74
|
+
if (disposed)
|
|
75
|
+
return;
|
|
76
|
+
disposed = true;
|
|
77
|
+
await disposeRestored(restored);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
async function disposeRestored(restored) {
|
|
82
|
+
for (let i = restored.length - 1; i >= 0; i -= 1) {
|
|
83
|
+
const entry = restored[i];
|
|
84
|
+
try {
|
|
85
|
+
if (entry.prior === null) {
|
|
86
|
+
await unlink(entry.path).catch((err) => {
|
|
87
|
+
if (err.code !== 'ENOENT')
|
|
88
|
+
throw err;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
await writeFile(entry.path, entry.prior, 'utf8');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Best-effort restore — losing a file restore must not stop the
|
|
97
|
+
// remaining entries from being processed.
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=sidecars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidecars.js","sourceRoot":"","sources":["../src/sidecars.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SkillMaterializationPlan } from './types.js';
|
|
2
|
+
export interface PersonaSkillsHandle {
|
|
3
|
+
/**
|
|
4
|
+
* Remove the per-install ephemeral artifact paths declared by the plan
|
|
5
|
+
* (or, in session mode, the whole session install root). Idempotent.
|
|
6
|
+
*/
|
|
7
|
+
dispose(): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface RunSkillInstallsOptions {
|
|
10
|
+
cwd: string;
|
|
11
|
+
/**
|
|
12
|
+
* When true (default) the dispose handle deletes installed skills paths
|
|
13
|
+
* (or, in session mode, the entire session install root). Set false to
|
|
14
|
+
* keep installs around — e.g. for repeat runs that share a stage dir.
|
|
15
|
+
*/
|
|
16
|
+
cleanupOnDispose?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare class SkillInstallError extends Error {
|
|
19
|
+
readonly exitCode: number;
|
|
20
|
+
readonly output: string;
|
|
21
|
+
constructor(exitCode: number, output: string);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Run every install in a {@link SkillMaterializationPlan}. Aborts on the
|
|
25
|
+
* first non-zero exit code with the buffered subprocess output attached to
|
|
26
|
+
* the thrown error. The returned handle removes the installed artifacts on
|
|
27
|
+
* `dispose()` (or the whole session root in session-install-root mode).
|
|
28
|
+
*/
|
|
29
|
+
export declare function runSkillInstalls(plan: SkillMaterializationPlan, options: RunSkillInstallsOptions): Promise<PersonaSkillsHandle>;
|
|
30
|
+
//# sourceMappingURL=skill-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-runner.d.ts","sourceRoot":"","sources":["../src/skill-runner.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAM7C;AAwCD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,wBAAwB,EAC9B,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,mBAAmB,CAAC,CAsC9B"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { rm } from 'node:fs/promises';
|
|
3
|
+
import { constants as osConstants } from 'node:os';
|
|
4
|
+
import { isAbsolute, relative, resolve } from 'node:path';
|
|
5
|
+
import { buildInstallArtifacts } from './skills.js';
|
|
6
|
+
export class SkillInstallError extends Error {
|
|
7
|
+
exitCode;
|
|
8
|
+
output;
|
|
9
|
+
constructor(exitCode, output) {
|
|
10
|
+
super(`Skill install failed (exit ${exitCode})`);
|
|
11
|
+
this.name = 'SkillInstallError';
|
|
12
|
+
this.exitCode = exitCode;
|
|
13
|
+
this.output = output;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function signalExitCode(signal) {
|
|
17
|
+
if (!signal)
|
|
18
|
+
return 0;
|
|
19
|
+
const num = osConstants.signals[signal];
|
|
20
|
+
return 128 + (num ?? 1);
|
|
21
|
+
}
|
|
22
|
+
async function spawnInstall(command, cwd) {
|
|
23
|
+
const [bin, ...args] = command;
|
|
24
|
+
if (!bin)
|
|
25
|
+
return { code: 0, output: '' };
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
const child = spawn(bin, args, {
|
|
28
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
29
|
+
shell: false,
|
|
30
|
+
cwd
|
|
31
|
+
});
|
|
32
|
+
let buffered = '';
|
|
33
|
+
child.stdout?.setEncoding('utf8');
|
|
34
|
+
child.stderr?.setEncoding('utf8');
|
|
35
|
+
child.stdout?.on('data', (chunk) => {
|
|
36
|
+
buffered += chunk;
|
|
37
|
+
});
|
|
38
|
+
child.stderr?.on('data', (chunk) => {
|
|
39
|
+
buffered += chunk;
|
|
40
|
+
});
|
|
41
|
+
child.on('error', (err) => {
|
|
42
|
+
resolve({ code: 1, output: `${buffered}${err.message}\n` });
|
|
43
|
+
});
|
|
44
|
+
child.on('close', (status, signal) => {
|
|
45
|
+
const exit = typeof status === 'number' ? status : signal ? signalExitCode(signal) : 1;
|
|
46
|
+
resolve({ code: exit, output: buffered });
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Run every install in a {@link SkillMaterializationPlan}. Aborts on the
|
|
52
|
+
* first non-zero exit code with the buffered subprocess output attached to
|
|
53
|
+
* the thrown error. The returned handle removes the installed artifacts on
|
|
54
|
+
* `dispose()` (or the whole session root in session-install-root mode).
|
|
55
|
+
*/
|
|
56
|
+
export async function runSkillInstalls(plan, options) {
|
|
57
|
+
const cleanupOnDispose = options.cleanupOnDispose ?? true;
|
|
58
|
+
const artifacts = buildInstallArtifacts(plan);
|
|
59
|
+
if (artifacts.installCommandString !== ':') {
|
|
60
|
+
const { code, output } = await spawnInstall(artifacts.installCommand, options.cwd);
|
|
61
|
+
if (code !== 0) {
|
|
62
|
+
throw new SkillInstallError(code, output);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
let disposed = false;
|
|
66
|
+
return {
|
|
67
|
+
async dispose() {
|
|
68
|
+
if (disposed)
|
|
69
|
+
return;
|
|
70
|
+
disposed = true;
|
|
71
|
+
if (!cleanupOnDispose)
|
|
72
|
+
return;
|
|
73
|
+
if (plan.sessionInstallRoot !== undefined) {
|
|
74
|
+
await rm(plan.sessionInstallRoot, { recursive: true, force: true });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const cwdAbs = resolve(options.cwd);
|
|
78
|
+
for (const install of plan.installs) {
|
|
79
|
+
for (const path of install.cleanupPaths) {
|
|
80
|
+
const abs = isAbsolute(path) ? resolve(path) : resolve(cwdAbs, path);
|
|
81
|
+
const rel = relative(cwdAbs, abs);
|
|
82
|
+
// Refuse to follow a tampered plan into directories outside the
|
|
83
|
+
// workspace — `rm -rf` doesn't get a free pass just because the
|
|
84
|
+
// path was declared in plan data.
|
|
85
|
+
if (rel === '' || rel.startsWith('..') || isAbsolute(rel)) {
|
|
86
|
+
throw new Error(`runSkillInstalls: cleanup path must stay within cwd; got ${JSON.stringify(path)}`);
|
|
87
|
+
}
|
|
88
|
+
await rm(abs, { recursive: true, force: true });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=skill-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-runner.js","sourceRoot":"","sources":["../src/skill-runner.ts"],"names":[],"mappings":"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"}
|