@excitedjs/agent-runtime-claude-code 0.6.1-alpha.gffd8b4b7feab → 0.6.1-beta.204
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/dist/skill-adapter.d.ts +15 -4
- package/dist/skill-adapter.d.ts.map +1 -1
- package/dist/skill-adapter.js +46 -35
- package/dist/skill-adapter.js.map +1 -1
- package/dist/skill-materializer.d.ts +9 -8
- package/dist/skill-materializer.d.ts.map +1 -1
- package/dist/skill-materializer.js +43 -15
- package/dist/skill-materializer.js.map +1 -1
- package/package.json +1 -1
package/dist/skill-adapter.d.ts
CHANGED
|
@@ -3,10 +3,13 @@ import type { AgentRuntimeSkillSource } from '@excitedjs/dreamux-types';
|
|
|
3
3
|
* One source root as it exists on disk: the root's own name and absolute path,
|
|
4
4
|
* plus the skill directories under it.
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* The adapter root is keyed by the roots alone, so one set of roots always
|
|
7
|
+
* maps to one directory; the children are recorded in the manifest and
|
|
8
|
+
* compared on every start, because package upgrades happen in place:
|
|
9
|
+
* `npm install --global` can rename the skills under a source root whose own
|
|
10
|
+
* name and path never change, and a view validated by its roots alone would
|
|
11
|
+
* keep serving the previous names forever. A mismatch refreshes the same
|
|
12
|
+
* directory instead of opening a new one.
|
|
10
13
|
*/
|
|
11
14
|
interface SkillAdapterSource {
|
|
12
15
|
name: string;
|
|
@@ -21,6 +24,14 @@ export interface SkillAdapterManifest {
|
|
|
21
24
|
key: string;
|
|
22
25
|
sources: SkillAdapterSource[];
|
|
23
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Whether the directory at `root` is the current view: a plain directory whose
|
|
29
|
+
* manifest is exactly `expected`. Anything else that occupies the path — a
|
|
30
|
+
* view of an earlier inventory, a manifest of the previous format, a
|
|
31
|
+
* half-written tree — is stale and is reported as such so the caller replaces
|
|
32
|
+
* it. Only a path that is not a plain directory at all is refused, because
|
|
33
|
+
* replacing it would delete something this adapter never wrote.
|
|
34
|
+
*/
|
|
24
35
|
export declare function validateSkillAdapter(root: string, expected: SkillAdapterManifest): Promise<boolean>;
|
|
25
36
|
/**
|
|
26
37
|
* Read the adapter's identity from disk — the source roots and the skill
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-adapter.d.ts","sourceRoot":"","sources":["../src/skill-adapter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE
|
|
1
|
+
{"version":3,"file":"skill-adapter.d.ts","sourceRoot":"","sources":["../src/skill-adapter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE;;;;;;;;;;;GAWG;AACH,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,CAAC,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAAC,OAAO,CAAC,CAgClB;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,SAAS,uBAAuB,EAAE,GAC1C,OAAO,CAAC,oBAAoB,CAAC,CAE/B"}
|
package/dist/skill-adapter.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { lstat, readFile, readdir } from 'node:fs/promises';
|
|
3
3
|
import { isAbsolute, join, resolve } from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* Whether the directory at `root` is the current view: a plain directory whose
|
|
6
|
+
* manifest is exactly `expected`. Anything else that occupies the path — a
|
|
7
|
+
* view of an earlier inventory, a manifest of the previous format, a
|
|
8
|
+
* half-written tree — is stale and is reported as such so the caller replaces
|
|
9
|
+
* it. Only a path that is not a plain directory at all is refused, because
|
|
10
|
+
* replacing it would delete something this adapter never wrote.
|
|
11
|
+
*/
|
|
4
12
|
export async function validateSkillAdapter(root, expected) {
|
|
5
13
|
let rootInfo;
|
|
6
14
|
try {
|
|
@@ -14,45 +22,26 @@ export async function validateSkillAdapter(root, expected) {
|
|
|
14
22
|
if (!rootInfo.isDirectory() || rootInfo.isSymbolicLink()) {
|
|
15
23
|
throw new Error(`invalid Claude skill adapter directory at ${root}`);
|
|
16
24
|
}
|
|
17
|
-
const skillsRoot = join(root, '.claude', 'skills');
|
|
18
|
-
const manifest = join(root, '.dreamux-skill-adapter.json');
|
|
19
25
|
let skillsInfo;
|
|
20
26
|
try {
|
|
21
|
-
skillsInfo = await lstat(
|
|
27
|
+
skillsInfo = await lstat(join(root, '.claude', 'skills'));
|
|
22
28
|
}
|
|
23
|
-
catch
|
|
24
|
-
|
|
25
|
-
cause: error,
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
if (!skillsInfo.isDirectory() || skillsInfo.isSymbolicLink()) {
|
|
29
|
-
throw new Error(`invalid Claude skill adapter directory at ${root}`);
|
|
30
|
-
}
|
|
31
|
-
let raw;
|
|
32
|
-
try {
|
|
33
|
-
raw = await readFile(manifest, 'utf8');
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
throw new Error(`invalid Claude skill adapter manifest at ${manifest}`, {
|
|
37
|
-
cause: error,
|
|
38
|
-
});
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
39
31
|
}
|
|
32
|
+
if (!skillsInfo.isDirectory() || skillsInfo.isSymbolicLink())
|
|
33
|
+
return false;
|
|
40
34
|
let value;
|
|
41
35
|
try {
|
|
42
|
-
value = JSON.parse(
|
|
36
|
+
value = JSON.parse(await readFile(join(root, '.dreamux-skill-adapter.json'), 'utf8'));
|
|
43
37
|
}
|
|
44
|
-
catch
|
|
45
|
-
|
|
46
|
-
cause: error,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
if (value === null ||
|
|
50
|
-
typeof value !== 'object' ||
|
|
51
|
-
Array.isArray(value) ||
|
|
52
|
-
JSON.stringify(value) !== JSON.stringify(expected)) {
|
|
53
|
-
throw new Error(`invalid Claude skill adapter manifest at ${manifest}`);
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
54
40
|
}
|
|
55
|
-
return
|
|
41
|
+
return (value !== null &&
|
|
42
|
+
typeof value === 'object' &&
|
|
43
|
+
!Array.isArray(value) &&
|
|
44
|
+
JSON.stringify(value) === JSON.stringify(expected));
|
|
56
45
|
}
|
|
57
46
|
/**
|
|
58
47
|
* Read the adapter's identity from disk — the source roots and the skill
|
|
@@ -65,15 +54,26 @@ export async function readSkillAdapterManifest(sources) {
|
|
|
65
54
|
async function readSkillAdapterInventory(sources) {
|
|
66
55
|
return Promise.all(uniqueSkillSources(sources).map(async (source) => {
|
|
67
56
|
const path = resolve(source.path);
|
|
68
|
-
return {
|
|
57
|
+
return {
|
|
58
|
+
name: source.name,
|
|
59
|
+
path,
|
|
60
|
+
skills: await skillDirsInRoot(source.name, path),
|
|
61
|
+
};
|
|
69
62
|
}));
|
|
70
63
|
}
|
|
71
64
|
function skillAdapterManifest(inventory) {
|
|
72
65
|
return { version: 2, key: skillAdapterKey(inventory), sources: inventory };
|
|
73
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* The key names the directory for one set of roots and nothing else, so the
|
|
69
|
+
* same roots always land in the same place and a refreshed view keeps the path
|
|
70
|
+
* a running child was given. It is the key the version-1 manifests used, so a
|
|
71
|
+
* root left by an earlier release is refreshed in place rather than orphaned.
|
|
72
|
+
*/
|
|
74
73
|
function skillAdapterKey(inventory) {
|
|
74
|
+
const roots = inventory.map(({ name, path }) => ({ name, path }));
|
|
75
75
|
return createHash('sha256')
|
|
76
|
-
.update(JSON.stringify(
|
|
76
|
+
.update(JSON.stringify(roots))
|
|
77
77
|
.digest('hex')
|
|
78
78
|
.slice(0, 24);
|
|
79
79
|
}
|
|
@@ -92,9 +92,20 @@ function uniqueSkillSources(sources) {
|
|
|
92
92
|
/**
|
|
93
93
|
* The child skills of one root in code-point order: the key hashes this list,
|
|
94
94
|
* so the order must not depend on the process locale.
|
|
95
|
+
*
|
|
96
|
+
* The roots are read on every start, so a custom root that was deleted or
|
|
97
|
+
* moved after the Team was created stops the start here; the error names the
|
|
98
|
+
* source so the operator knows which `skill_sources` entry to repair.
|
|
95
99
|
*/
|
|
96
|
-
async function skillDirsInRoot(root) {
|
|
97
|
-
|
|
100
|
+
async function skillDirsInRoot(name, root) {
|
|
101
|
+
let entries;
|
|
102
|
+
try {
|
|
103
|
+
entries = await readdir(root, { withFileTypes: true });
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
throw new Error(`skill source ${JSON.stringify(name)} root ${root} cannot be read: ` +
|
|
107
|
+
(error instanceof Error ? error.message : String(error)), { cause: error });
|
|
108
|
+
}
|
|
98
109
|
return entries
|
|
99
110
|
.filter((entry) => entry.isDirectory())
|
|
100
111
|
.map((entry) => ({ name: entry.name, path: join(root, entry.name) }))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-adapter.js","sourceRoot":"","sources":["../src/skill-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"skill-adapter.js","sourceRoot":"","sources":["../src/skill-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import type { AgentRuntimeSkillSource } from '@excitedjs/dreamux-types';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Materialize the Claude-compatible view of role-gated skills and return the
|
|
4
|
+
* adapter root the child must be given, or null when this runtime has no
|
|
5
|
+
* skill sources.
|
|
6
6
|
*
|
|
7
|
-
* The root is `<cacheDir>/claude-code/skills/<key>`,
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* The root is `<cacheDir>/claude-code/skills/<key>`, one directory per set of
|
|
8
|
+
* source roots. Its manifest records the skill directories under each root as
|
|
9
|
+
* they were when the view was built; a start that reads a different inventory
|
|
10
|
+
* (an in-place package upgrade that renamed skills, a custom root that gained
|
|
11
|
+
* a skill) rebuilds the view beside the root and swaps it into the same path,
|
|
12
|
+
* so the path never changes and no earlier view is left behind.
|
|
12
13
|
*/
|
|
13
14
|
export declare function materializeClaudeSkillAddDir(cacheDir: string, sources: readonly AgentRuntimeSkillSource[], testHooks?: {
|
|
14
15
|
beforePublish?: () => void | Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-materializer.d.ts","sourceRoot":"","sources":["../src/skill-materializer.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"skill-materializer.d.ts","sourceRoot":"","sources":["../src/skill-materializer.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAQxE;;;;;;;;;;;GAWG;AACH,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,SAAS,uBAAuB,EAAE,EAC3C,SAAS,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAAO,GAC7D,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqCxB"}
|
|
@@ -3,15 +3,16 @@ import { mkdir, rename, rm, symlink, writeFile, } from 'node:fs/promises';
|
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
4
|
import { readSkillAdapterManifest, validateSkillAdapter, } from './skill-adapter.js';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Materialize the Claude-compatible view of role-gated skills and return the
|
|
7
|
+
* adapter root the child must be given, or null when this runtime has no
|
|
8
|
+
* skill sources.
|
|
9
9
|
*
|
|
10
|
-
* The root is `<cacheDir>/claude-code/skills/<key>`,
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* The root is `<cacheDir>/claude-code/skills/<key>`, one directory per set of
|
|
11
|
+
* source roots. Its manifest records the skill directories under each root as
|
|
12
|
+
* they were when the view was built; a start that reads a different inventory
|
|
13
|
+
* (an in-place package upgrade that renamed skills, a custom root that gained
|
|
14
|
+
* a skill) rebuilds the view beside the root and swaps it into the same path,
|
|
15
|
+
* so the path never changes and no earlier view is left behind.
|
|
15
16
|
*/
|
|
16
17
|
export async function materializeClaudeSkillAddDir(cacheDir, sources, testHooks = {}) {
|
|
17
18
|
if (sources.length === 0)
|
|
@@ -41,18 +42,45 @@ export async function materializeClaudeSkillAddDir(cacheDir, sources, testHooks
|
|
|
41
42
|
await writeFile(join(tmpRoot, '.dreamux-skill-adapter.json'), `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o600 });
|
|
42
43
|
await mkdir(dirname(root), { recursive: true });
|
|
43
44
|
await testHooks.beforePublish?.();
|
|
44
|
-
await
|
|
45
|
+
await publish(tmpRoot, root, manifest);
|
|
45
46
|
}
|
|
46
47
|
catch (err) {
|
|
47
|
-
const code = err.code;
|
|
48
|
-
if (code === 'EEXIST' || code === 'ENOTEMPTY') {
|
|
49
|
-
await rm(tmpRoot, { recursive: true, force: true }).catch(() => undefined);
|
|
50
|
-
if (await validateSkillAdapter(root, manifest))
|
|
51
|
-
return root;
|
|
52
|
-
}
|
|
53
48
|
await rm(tmpRoot, { recursive: true, force: true }).catch(() => undefined);
|
|
54
49
|
throw err;
|
|
55
50
|
}
|
|
56
51
|
return root;
|
|
57
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Put the fresh view at `root`: whatever occupies the path (a stale view, a
|
|
55
|
+
* manifest of the previous format, a half-written tree) is moved aside first
|
|
56
|
+
* and removed once the swap is done. Two runtimes starting together may both
|
|
57
|
+
* reach here; each swap leaves a complete view at the path, and the one whose
|
|
58
|
+
* final rename finds the path already taken keeps the other's view when it
|
|
59
|
+
* validates.
|
|
60
|
+
*/
|
|
61
|
+
async function publish(tmpRoot, root, manifest) {
|
|
62
|
+
const staleRoot = `${root}.${randomUUID()}.stale`;
|
|
63
|
+
try {
|
|
64
|
+
await rename(root, staleRoot);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
if (err.code !== 'ENOENT')
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
await rename(tmpRoot, root);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
const code = err.code;
|
|
75
|
+
if (code !== 'EEXIST' && code !== 'ENOTEMPTY')
|
|
76
|
+
throw err;
|
|
77
|
+
await rm(tmpRoot, { recursive: true, force: true }).catch(() => undefined);
|
|
78
|
+
if (!(await validateSkillAdapter(root, manifest))) {
|
|
79
|
+
throw new Error(`invalid Claude skill adapter at ${root} after a concurrent publish`, { cause: err });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
await rm(staleRoot, { recursive: true, force: true }).catch(() => undefined);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
58
86
|
//# sourceMappingURL=skill-materializer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-materializer.js","sourceRoot":"","sources":["../src/skill-materializer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,KAAK,EACL,MAAM,EACN,EAAE,EACF,OAAO,EACP,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAI1C,OAAO,EACL,wBAAwB,EACxB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"skill-materializer.js","sourceRoot":"","sources":["../src/skill-materializer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@excitedjs/agent-runtime-claude-code",
|
|
3
|
-
"version": "0.6.1-
|
|
3
|
+
"version": "0.6.1-beta.204",
|
|
4
4
|
"description": "Built-in Claude Code Agent Runtime provider for Dreamux (alias builtin:claude-code). Implements the @excitedjs/dreamux-types AgentRuntimeProvider contract against a resident `claude` stream-json child; depends on @excitedjs/dreamux-types only, never on @excitedjs/dreamux core (issue excitedjs/dreamux#209).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|