@dexto/agent-management 1.7.2 → 1.8.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/dist/agent-creation.cjs +6 -2
- package/dist/agent-creation.d.ts.map +1 -1
- package/dist/agent-creation.js +6 -2
- package/dist/config/config-enrichment.cjs +1 -16
- package/dist/config/config-enrichment.d.ts.map +1 -1
- package/dist/config/config-enrichment.js +2 -21
- package/dist/index.cjs +4 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/plugins/discover-skills.d.ts +2 -3
- package/dist/plugins/discover-skills.d.ts.map +1 -1
- package/dist/plugins/index.cjs +6 -0
- package/dist/plugins/index.d.ts +4 -0
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +4 -0
- package/dist/plugins/local-skill-source.cjs +104 -0
- package/dist/plugins/local-skill-source.d.ts +20 -0
- package/dist/plugins/local-skill-source.d.ts.map +1 -0
- package/dist/plugins/local-skill-source.js +70 -0
- package/dist/plugins/local-skill-sources.cjs +74 -0
- package/dist/plugins/local-skill-sources.d.ts +7 -0
- package/dist/plugins/local-skill-sources.d.ts.map +1 -0
- package/dist/plugins/local-skill-sources.js +40 -0
- package/dist/plugins/types.d.ts +1 -1
- package/dist/tool-factories/agent-spawner/factory.cjs +2 -4
- package/dist/tool-factories/agent-spawner/factory.d.ts.map +1 -1
- package/dist/tool-factories/agent-spawner/factory.js +2 -4
- package/dist/tool-factories/agent-spawner/runtime.cjs +4 -9
- package/dist/tool-factories/agent-spawner/runtime.d.ts +3 -3
- package/dist/tool-factories/agent-spawner/runtime.d.ts.map +1 -1
- package/dist/tool-factories/agent-spawner/runtime.js +4 -9
- package/dist/tool-factories/creator-tools/factory.cjs +49 -146
- package/dist/tool-factories/creator-tools/factory.d.ts.map +1 -1
- package/dist/tool-factories/creator-tools/factory.js +50 -148
- package/package.json +5 -5
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { discoverClaudeCodePlugins } from "./discover-plugins.js";
|
|
3
|
+
import { discoverStandaloneSkills } from "./discover-skills.js";
|
|
4
|
+
import { loadClaudeCodePlugin } from "./load-plugin.js";
|
|
5
|
+
import { LocalSkillSource } from "./local-skill-source.js";
|
|
6
|
+
function createLocalSkillSources(options = {}) {
|
|
7
|
+
const roots = [];
|
|
8
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9
|
+
const addRoot = (root) => {
|
|
10
|
+
const resolved = path.resolve(root.skillFile);
|
|
11
|
+
if (seen.has(resolved)) return;
|
|
12
|
+
seen.add(resolved);
|
|
13
|
+
roots.push({ ...root, skillFile: resolved });
|
|
14
|
+
};
|
|
15
|
+
for (const skill of discoverStandaloneSkills(options.workspaceRoot)) {
|
|
16
|
+
addRoot({
|
|
17
|
+
id: skill.name,
|
|
18
|
+
skillFile: skill.skillFile
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
for (const plugin of discoverClaudeCodePlugins(
|
|
22
|
+
options.workspaceRoot,
|
|
23
|
+
options.bundledPlugins ?? []
|
|
24
|
+
)) {
|
|
25
|
+
const loaded = loadClaudeCodePlugin(plugin);
|
|
26
|
+
for (const command of loaded.commands) {
|
|
27
|
+
if (!command.isSkill) continue;
|
|
28
|
+
const id = path.basename(path.dirname(command.file));
|
|
29
|
+
addRoot({
|
|
30
|
+
id: `${command.namespace}:${id}`,
|
|
31
|
+
displayName: `${command.namespace}:${id}`,
|
|
32
|
+
skillFile: command.file
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return roots.length > 0 ? [new LocalSkillSource("local", roots)] : [];
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
createLocalSkillSources
|
|
40
|
+
};
|
package/dist/plugins/types.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* ├── .claude-plugin/
|
|
11
11
|
* │ └── plugin.json # {name, description, version, author?}
|
|
12
12
|
* ├── commands/*.md # Commands (→ prompts, user-invocable by default)
|
|
13
|
-
* ├── skills/* /SKILL.md # Skills (
|
|
13
|
+
* ├── skills/* /SKILL.md # Skills (metadata only; not loaded as prompts)
|
|
14
14
|
* ├── hooks/hooks.json # UNSUPPORTED - shell injection
|
|
15
15
|
* ├── .mcp.json # MCP servers to merge into config
|
|
16
16
|
* └── .lsp.json # UNSUPPORTED - language servers
|
|
@@ -49,9 +49,7 @@ const agentSpawnerToolsFactory = {
|
|
|
49
49
|
const { toolServices, taskForker, logger } = options;
|
|
50
50
|
if (toolServices.taskForker !== taskForker) {
|
|
51
51
|
toolServices.taskForker = taskForker;
|
|
52
|
-
logger.debug(
|
|
53
|
-
"AgentSpawnerRuntime attached as taskForker for context:fork skill support"
|
|
54
|
-
);
|
|
52
|
+
logger.debug("AgentSpawnerRuntime attached as taskForker");
|
|
55
53
|
}
|
|
56
54
|
};
|
|
57
55
|
const updateWorkspaceRootHint = (runtime, context) => {
|
|
@@ -147,7 +145,7 @@ const agentSpawnerToolsFactory = {
|
|
|
147
145
|
];
|
|
148
146
|
agent.isSessionBusy(sessionId).then((isBusy) => {
|
|
149
147
|
if (isBusy) {
|
|
150
|
-
agent.
|
|
148
|
+
agent.steer(sessionId, {
|
|
151
149
|
content,
|
|
152
150
|
kind: "background"
|
|
153
151
|
}).catch(() => void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/tool-factories/agent-spawner/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAmBvD,OAAO,EAGH,KAAK,kBAAkB,EAE1B,MAAM,cAAc,CAAC;AAkCtB,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,kBAAkB,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/tool-factories/agent-spawner/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAmBvD,OAAO,EAGH,KAAK,kBAAkB,EAE1B,MAAM,cAAc,CAAC;AAkCtB,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,kBAAkB,CA+XpE,CAAC"}
|
|
@@ -39,9 +39,7 @@ const agentSpawnerToolsFactory = {
|
|
|
39
39
|
const { toolServices, taskForker, logger } = options;
|
|
40
40
|
if (toolServices.taskForker !== taskForker) {
|
|
41
41
|
toolServices.taskForker = taskForker;
|
|
42
|
-
logger.debug(
|
|
43
|
-
"AgentSpawnerRuntime attached as taskForker for context:fork skill support"
|
|
44
|
-
);
|
|
42
|
+
logger.debug("AgentSpawnerRuntime attached as taskForker");
|
|
45
43
|
}
|
|
46
44
|
};
|
|
47
45
|
const updateWorkspaceRootHint = (runtime, context) => {
|
|
@@ -137,7 +135,7 @@ const agentSpawnerToolsFactory = {
|
|
|
137
135
|
];
|
|
138
136
|
agent.isSessionBusy(sessionId).then((isBusy) => {
|
|
139
137
|
if (isBusy) {
|
|
140
|
-
agent.
|
|
138
|
+
agent.steer(sessionId, {
|
|
141
139
|
content,
|
|
142
140
|
kind: "background"
|
|
143
141
|
}).catch(() => void 0);
|
|
@@ -307,7 +307,7 @@ class AgentSpawnerRuntime {
|
|
|
307
307
|
* @param input.task - Short task description (for logging/UI)
|
|
308
308
|
* @param input.instructions - Full prompt sent to sub-agent
|
|
309
309
|
* @param input.agentId - Optional agent ID from registry
|
|
310
|
-
* @param input.autoApprove - Optional override for auto-approve
|
|
310
|
+
* @param input.autoApprove - Optional override for auto-approve
|
|
311
311
|
* @param input.timeout - Optional task timeout in milliseconds
|
|
312
312
|
* @param input.toolCallId - Optional tool call ID for progress events
|
|
313
313
|
* @param input.sessionId - Optional session ID for progress events
|
|
@@ -346,12 +346,12 @@ class AgentSpawnerRuntime {
|
|
|
346
346
|
}
|
|
347
347
|
/**
|
|
348
348
|
* Fork execution to an isolated subagent.
|
|
349
|
-
* Implements TaskForker interface for
|
|
349
|
+
* Implements TaskForker interface for isolated subagent execution.
|
|
350
350
|
*
|
|
351
351
|
* @param options.task - Short description for UI/logs
|
|
352
352
|
* @param options.instructions - Full instructions for the subagent
|
|
353
353
|
* @param options.agentId - Optional agent ID from registry to use for execution
|
|
354
|
-
* @param options.autoApprove - Auto-approve tool calls
|
|
354
|
+
* @param options.autoApprove - Auto-approve tool calls
|
|
355
355
|
* @param options.toolCallId - Optional tool call ID for progress events
|
|
356
356
|
* @param options.sessionId - Optional session ID for progress events
|
|
357
357
|
*/
|
|
@@ -721,13 +721,8 @@ class AgentSpawnerRuntime {
|
|
|
721
721
|
...parentToolPolicies?.alwaysAllow ?? [],
|
|
722
722
|
...subAgentPolicies?.alwaysAllow ?? []
|
|
723
723
|
];
|
|
724
|
-
const alwaysDeny = [
|
|
725
|
-
...parentToolPolicies?.alwaysDeny ?? [],
|
|
726
|
-
...subAgentPolicies?.alwaysDeny ?? []
|
|
727
|
-
];
|
|
728
724
|
return {
|
|
729
|
-
alwaysAllow: Array.from(new Set(alwaysAllow))
|
|
730
|
-
alwaysDeny: Array.from(new Set(alwaysDeny))
|
|
725
|
+
alwaysAllow: Array.from(new Set(alwaysAllow))
|
|
731
726
|
};
|
|
732
727
|
};
|
|
733
728
|
const inheritedLoggerConfig = await (async () => {
|
|
@@ -49,7 +49,7 @@ export declare class AgentSpawnerRuntime implements TaskForker {
|
|
|
49
49
|
* @param input.task - Short task description (for logging/UI)
|
|
50
50
|
* @param input.instructions - Full prompt sent to sub-agent
|
|
51
51
|
* @param input.agentId - Optional agent ID from registry
|
|
52
|
-
* @param input.autoApprove - Optional override for auto-approve
|
|
52
|
+
* @param input.autoApprove - Optional override for auto-approve
|
|
53
53
|
* @param input.timeout - Optional task timeout in milliseconds
|
|
54
54
|
* @param input.toolCallId - Optional tool call ID for progress events
|
|
55
55
|
* @param input.sessionId - Optional session ID for progress events
|
|
@@ -65,12 +65,12 @@ export declare class AgentSpawnerRuntime implements TaskForker {
|
|
|
65
65
|
}): Promise<SpawnAgentOutput>;
|
|
66
66
|
/**
|
|
67
67
|
* Fork execution to an isolated subagent.
|
|
68
|
-
* Implements TaskForker interface for
|
|
68
|
+
* Implements TaskForker interface for isolated subagent execution.
|
|
69
69
|
*
|
|
70
70
|
* @param options.task - Short description for UI/logs
|
|
71
71
|
* @param options.instructions - Full instructions for the subagent
|
|
72
72
|
* @param options.agentId - Optional agent ID from registry to use for execution
|
|
73
|
-
* @param options.autoApprove - Auto-approve tool calls
|
|
73
|
+
* @param options.autoApprove - Auto-approve tool calls
|
|
74
74
|
* @param options.toolCallId - Optional tool call ID for progress events
|
|
75
75
|
* @param options.sessionId - Optional session ID for progress events
|
|
76
76
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/tool-factories/agent-spawner/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAWlE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAiBnD,qBAAa,mBAAoB,YAAW,UAAU;IAClD,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,iBAAiB,CAAqB;IAE9C,OAAO,CAAC,4BAA4B;IAuBpC,OAAO,CAAC,sBAAsB;IA8B9B,OAAO,CAAC,yBAAyB;IAyBjC,OAAO,CAAC,2BAA2B;IAYnC,OAAO,CAAC,wCAAwC;IAUhD,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI;YAKxC,wBAAwB;YAgCxB,iCAAiC;YA8CjC,mCAAmC;gBAyFrC,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM;IAuB/E;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAIhB;;;;;;;;;;;;;;OAcG;IACG,eAAe,CAAC,KAAK,EAAE;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA8C7B;;;;;;;;;;OAUG;IACG,IAAI,CAAC,OAAO,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAIpE;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IA+G7B;;OAEG;YACW,oBAAoB;IA2BlC,OAAO,CAAC,sBAAsB;IAuB9B;;OAEG;IACH,OAAO,CAAC,UAAU;IAsBlB;;OAEG;YACW,oBAAoB;IA4RlC;;;;;;;OAOG;YACW,mBAAmB;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/tool-factories/agent-spawner/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAWlE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAiBnD,qBAAa,mBAAoB,YAAW,UAAU;IAClD,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,iBAAiB,CAAqB;IAE9C,OAAO,CAAC,4BAA4B;IAuBpC,OAAO,CAAC,sBAAsB;IA8B9B,OAAO,CAAC,yBAAyB;IAyBjC,OAAO,CAAC,2BAA2B;IAYnC,OAAO,CAAC,wCAAwC;IAUhD,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI;YAKxC,wBAAwB;YAgCxB,iCAAiC;YA8CjC,mCAAmC;gBAyFrC,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM;IAuB/E;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAIhB;;;;;;;;;;;;;;OAcG;IACG,eAAe,CAAC,KAAK,EAAE;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA8C7B;;;;;;;;;;OAUG;IACG,IAAI,CAAC,OAAO,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAIpE;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IA+G7B;;OAEG;YACW,oBAAoB;IA2BlC,OAAO,CAAC,sBAAsB;IAuB9B;;OAEG;IACH,OAAO,CAAC,UAAU;IAsBlB;;OAEG;YACW,oBAAoB;IA4RlC;;;;;;;OAOG;YACW,mBAAmB;IA4KjC;;;OAGG;IACG,kBAAkB,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAqCzD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAIjC"}
|
|
@@ -279,7 +279,7 @@ class AgentSpawnerRuntime {
|
|
|
279
279
|
* @param input.task - Short task description (for logging/UI)
|
|
280
280
|
* @param input.instructions - Full prompt sent to sub-agent
|
|
281
281
|
* @param input.agentId - Optional agent ID from registry
|
|
282
|
-
* @param input.autoApprove - Optional override for auto-approve
|
|
282
|
+
* @param input.autoApprove - Optional override for auto-approve
|
|
283
283
|
* @param input.timeout - Optional task timeout in milliseconds
|
|
284
284
|
* @param input.toolCallId - Optional tool call ID for progress events
|
|
285
285
|
* @param input.sessionId - Optional session ID for progress events
|
|
@@ -318,12 +318,12 @@ class AgentSpawnerRuntime {
|
|
|
318
318
|
}
|
|
319
319
|
/**
|
|
320
320
|
* Fork execution to an isolated subagent.
|
|
321
|
-
* Implements TaskForker interface for
|
|
321
|
+
* Implements TaskForker interface for isolated subagent execution.
|
|
322
322
|
*
|
|
323
323
|
* @param options.task - Short description for UI/logs
|
|
324
324
|
* @param options.instructions - Full instructions for the subagent
|
|
325
325
|
* @param options.agentId - Optional agent ID from registry to use for execution
|
|
326
|
-
* @param options.autoApprove - Auto-approve tool calls
|
|
326
|
+
* @param options.autoApprove - Auto-approve tool calls
|
|
327
327
|
* @param options.toolCallId - Optional tool call ID for progress events
|
|
328
328
|
* @param options.sessionId - Optional session ID for progress events
|
|
329
329
|
*/
|
|
@@ -693,13 +693,8 @@ class AgentSpawnerRuntime {
|
|
|
693
693
|
...parentToolPolicies?.alwaysAllow ?? [],
|
|
694
694
|
...subAgentPolicies?.alwaysAllow ?? []
|
|
695
695
|
];
|
|
696
|
-
const alwaysDeny = [
|
|
697
|
-
...parentToolPolicies?.alwaysDeny ?? [],
|
|
698
|
-
...subAgentPolicies?.alwaysDeny ?? []
|
|
699
|
-
];
|
|
700
696
|
return {
|
|
701
|
-
alwaysAllow: Array.from(new Set(alwaysAllow))
|
|
702
|
-
alwaysDeny: Array.from(new Set(alwaysDeny))
|
|
697
|
+
alwaysAllow: Array.from(new Set(alwaysAllow))
|
|
703
698
|
};
|
|
704
699
|
};
|
|
705
700
|
const inheritedLoggerConfig = await (async () => {
|
|
@@ -33,7 +33,6 @@ __export(factory_exports, {
|
|
|
33
33
|
module.exports = __toCommonJS(factory_exports);
|
|
34
34
|
var import_node_fs = require("node:fs");
|
|
35
35
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
36
|
-
var import_yaml = require("yaml");
|
|
37
36
|
var import_core = require("@dexto/core");
|
|
38
37
|
var import_discover_skills = require("../../plugins/discover-skills.js");
|
|
39
38
|
var import_schemas = require("./schemas.js");
|
|
@@ -43,8 +42,6 @@ const SkillCreateInputSchema = import_zod.z.object({
|
|
|
43
42
|
id: import_zod.z.string().min(1).describe("Skill id (kebab-case)."),
|
|
44
43
|
description: import_zod.z.string().min(1).describe("Short description of what the skill does."),
|
|
45
44
|
content: import_zod.z.string().min(1).describe("Skill body (markdown) without frontmatter."),
|
|
46
|
-
allowedTools: import_zod.z.array(import_zod.z.string().min(1)).optional().describe("Optional allowed-tools list for the skill frontmatter."),
|
|
47
|
-
toolkits: import_zod.z.array(import_zod.z.string().min(1)).optional().describe("Optional toolkits list for the skill frontmatter."),
|
|
48
45
|
scope: import_zod.z.enum(["global", "workspace"]).optional(),
|
|
49
46
|
overwrite: import_zod.z.boolean().optional()
|
|
50
47
|
}).strict();
|
|
@@ -52,8 +49,6 @@ const SkillUpdateInputSchema = import_zod.z.object({
|
|
|
52
49
|
id: import_zod.z.string().min(1),
|
|
53
50
|
content: import_zod.z.string().min(1).describe("New SKILL.md body (markdown) without frontmatter."),
|
|
54
51
|
description: import_zod.z.string().min(1).optional(),
|
|
55
|
-
allowedTools: import_zod.z.array(import_zod.z.string().min(1)).optional().describe("Optional allowed-tools list for the skill frontmatter."),
|
|
56
|
-
toolkits: import_zod.z.array(import_zod.z.string().min(1)).optional().describe("Optional toolkits list for the skill frontmatter."),
|
|
57
52
|
scope: import_zod.z.enum(["global", "workspace"]).optional()
|
|
58
53
|
}).strict();
|
|
59
54
|
const SkillListInputSchema = import_zod.z.object({
|
|
@@ -85,8 +80,8 @@ function matchesSkillQuery(value, query) {
|
|
|
85
80
|
if (!normalizedQuery) return false;
|
|
86
81
|
return normalizeSkillQuery(value).includes(normalizedQuery);
|
|
87
82
|
}
|
|
88
|
-
function
|
|
89
|
-
return info.displayName || info.
|
|
83
|
+
function resolveSkillName(info) {
|
|
84
|
+
return info.displayName || info.id;
|
|
90
85
|
}
|
|
91
86
|
function resolveWorkspaceBasePath(context) {
|
|
92
87
|
const workspacePath = context.workspace?.path;
|
|
@@ -101,25 +96,6 @@ function resolveWorkspaceSkillDirs(context) {
|
|
|
101
96
|
legacy: import_node_path.default.join(base, ".dexto", "skills")
|
|
102
97
|
};
|
|
103
98
|
}
|
|
104
|
-
function findRegisteredSkillFile(skillId, context) {
|
|
105
|
-
const prompts = context.agent?.getEffectiveConfig().prompts;
|
|
106
|
-
if (!Array.isArray(prompts)) {
|
|
107
|
-
return void 0;
|
|
108
|
-
}
|
|
109
|
-
for (const prompt of prompts) {
|
|
110
|
-
if (!prompt || typeof prompt !== "object" || prompt.type !== "file") {
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
const filePath = typeof prompt.file === "string" ? prompt.file : void 0;
|
|
114
|
-
if (!filePath || import_node_path.default.basename(filePath) !== "SKILL.md") {
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
if (import_node_path.default.basename(import_node_path.default.dirname(filePath)) === skillId) {
|
|
118
|
-
return filePath;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return void 0;
|
|
122
|
-
}
|
|
123
99
|
function resolveSkillBaseDirectory(scope, context) {
|
|
124
100
|
if (scope === "global") {
|
|
125
101
|
return { baseDir: (0, import_path.getDextoGlobalPath)("skills"), scope: "global" };
|
|
@@ -153,20 +129,6 @@ async function resolveSkillUpdateDirectory(input, context) {
|
|
|
153
129
|
return { baseDir: primary, scope: "workspace" };
|
|
154
130
|
}
|
|
155
131
|
async function resolveExistingSkillLocation(input, context) {
|
|
156
|
-
if (input.scope !== "global") {
|
|
157
|
-
const registeredSkillFile = findRegisteredSkillFile(input.id.trim(), context);
|
|
158
|
-
if (registeredSkillFile) {
|
|
159
|
-
const skillDir2 = import_node_path.default.dirname(registeredSkillFile);
|
|
160
|
-
const baseDir2 = import_node_path.default.dirname(skillDir2);
|
|
161
|
-
ensurePathWithinBase(baseDir2, skillDir2, "skill_refresh");
|
|
162
|
-
return {
|
|
163
|
-
baseDir: baseDir2,
|
|
164
|
-
scope: "workspace",
|
|
165
|
-
skillDir: skillDir2,
|
|
166
|
-
skillFile: registeredSkillFile
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
132
|
const { baseDir, scope } = await resolveSkillUpdateDirectory(input, context);
|
|
171
133
|
const skillDir = import_node_path.default.join(baseDir, input.id.trim());
|
|
172
134
|
ensurePathWithinBase(baseDir, skillDir, "skill_refresh");
|
|
@@ -206,10 +168,6 @@ function resolveSkillCreateInput(input) {
|
|
|
206
168
|
content
|
|
207
169
|
};
|
|
208
170
|
}
|
|
209
|
-
function formatFrontmatterList(key, values) {
|
|
210
|
-
const normalized = values.map((value) => JSON.stringify(value.trim()));
|
|
211
|
-
return `${key}: [${normalized.join(", ")}]`;
|
|
212
|
-
}
|
|
213
171
|
function buildSkillMarkdownFromParts(options) {
|
|
214
172
|
const id = options.id.trim();
|
|
215
173
|
const title = titleizeSkillId(id) || id;
|
|
@@ -217,12 +175,6 @@ function buildSkillMarkdownFromParts(options) {
|
|
|
217
175
|
const lines = ["---"];
|
|
218
176
|
lines.push(formatFrontmatterLine("name", id));
|
|
219
177
|
lines.push(formatFrontmatterLine("description", options.description.trim()));
|
|
220
|
-
if (options.toolkits && options.toolkits.length > 0) {
|
|
221
|
-
lines.push(formatFrontmatterList("toolkits", options.toolkits));
|
|
222
|
-
}
|
|
223
|
-
if (options.allowedTools && options.allowedTools.length > 0) {
|
|
224
|
-
lines.push(formatFrontmatterList("allowed-tools", options.allowedTools));
|
|
225
|
-
}
|
|
226
178
|
lines.push("---", "", `# ${title}`);
|
|
227
179
|
if (body.length > 0) {
|
|
228
180
|
lines.push("", body);
|
|
@@ -239,69 +191,36 @@ function buildSkillMarkdown(input) {
|
|
|
239
191
|
return buildSkillMarkdownFromParts({
|
|
240
192
|
id: input.id,
|
|
241
193
|
description: input.description,
|
|
242
|
-
content: input.content
|
|
243
|
-
allowedTools: input.allowedTools,
|
|
244
|
-
toolkits: input.toolkits
|
|
194
|
+
content: input.content
|
|
245
195
|
});
|
|
246
196
|
}
|
|
247
|
-
|
|
197
|
+
function frontmatterDescription(markdown) {
|
|
198
|
+
if (!markdown.startsWith("---\n")) return void 0;
|
|
199
|
+
const end = markdown.indexOf("\n---", 4);
|
|
200
|
+
if (end < 0) return void 0;
|
|
201
|
+
const line = markdown.slice(4, end).split("\n").find((candidate) => candidate.trim().startsWith("description:"));
|
|
202
|
+
return line?.split(":").slice(1).join(":").trim().replace(/^"|"$/g, "") || void 0;
|
|
203
|
+
}
|
|
204
|
+
async function readSkillDescription(skillFile) {
|
|
248
205
|
try {
|
|
249
206
|
const raw = await import_node_fs.promises.readFile(skillFile, "utf-8");
|
|
250
|
-
|
|
251
|
-
if (!match) return {};
|
|
252
|
-
const frontmatter = (0, import_yaml.parse)(match[1] ?? "");
|
|
253
|
-
if (!frontmatter || typeof frontmatter !== "object") return {};
|
|
254
|
-
const name = typeof frontmatter.name === "string" ? frontmatter.name.trim() : void 0;
|
|
255
|
-
const description = typeof frontmatter.description === "string" ? frontmatter.description.trim() : void 0;
|
|
256
|
-
const allowedToolsRaw = frontmatter["allowed-tools"];
|
|
257
|
-
const toolkitsRaw = frontmatter.toolkits;
|
|
258
|
-
const allowedTools = Array.isArray(allowedToolsRaw) ? allowedToolsRaw.filter((item) => typeof item === "string").map((item) => item.trim()).filter((item) => item.length > 0) : void 0;
|
|
259
|
-
const toolkits = Array.isArray(toolkitsRaw) ? toolkitsRaw.filter((item) => typeof item === "string").map((item) => item.trim()).filter((item) => item.length > 0) : void 0;
|
|
260
|
-
const result = {};
|
|
261
|
-
if (name) result.name = name;
|
|
262
|
-
if (description) result.description = description;
|
|
263
|
-
if (allowedTools && allowedTools.length > 0) result.allowedTools = allowedTools;
|
|
264
|
-
if (toolkits && toolkits.length > 0) result.toolkits = toolkits;
|
|
265
|
-
return result;
|
|
207
|
+
return frontmatterDescription(raw);
|
|
266
208
|
} catch {
|
|
267
|
-
return
|
|
209
|
+
return void 0;
|
|
268
210
|
}
|
|
269
211
|
}
|
|
270
|
-
async function
|
|
271
|
-
const
|
|
272
|
-
if (!
|
|
273
|
-
|
|
274
|
-
const existingPrompts = Array.isArray(effective.prompts) ? [...effective.prompts] : [];
|
|
275
|
-
const alreadyPresent = existingPrompts.some((prompt) => {
|
|
276
|
-
if (!prompt || typeof prompt !== "object") return false;
|
|
277
|
-
const record = prompt;
|
|
278
|
-
return record.type === "file" && record.file === skillFile;
|
|
279
|
-
});
|
|
280
|
-
const nextPrompts = alreadyPresent ? existingPrompts : [...existingPrompts, { type: "file", file: skillFile }];
|
|
281
|
-
await agent.refreshPrompts(nextPrompts);
|
|
212
|
+
async function refreshAgentSkills(context) {
|
|
213
|
+
const skillManager = context.services?.skills;
|
|
214
|
+
if (!skillManager) return false;
|
|
215
|
+
await skillManager.refresh();
|
|
282
216
|
return true;
|
|
283
217
|
}
|
|
284
|
-
function
|
|
285
|
-
const notes = [
|
|
286
|
-
"Creating or editing files under mcps/ only defines bundled MCP config. It does not implement or verify the target MCP server.",
|
|
287
|
-
"After editing SKILL.md or bundled MCP files with non-creator tools, run skill_refresh so the current session sees the latest skill content and MCP metadata."
|
|
288
|
-
];
|
|
289
|
-
if (bundledMcpServers.length > 0) {
|
|
290
|
-
notes.push(
|
|
291
|
-
"Bundled MCP config is present. Only describe the skill as shipping a real MCP when the config points at a bundled runnable server or a verified external command/package."
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
return notes;
|
|
295
|
-
}
|
|
296
|
-
function inspectSkillBundle(skillDir, skillId) {
|
|
297
|
-
const bundledMcpResult = (0, import_core.loadBundledMcpConfigFromDirectory)(skillDir, skillId, {
|
|
298
|
-
scanNestedMcps: true
|
|
299
|
-
});
|
|
300
|
-
const bundledMcpServers = Object.keys(bundledMcpResult.mcpServers ?? {});
|
|
218
|
+
function inspectSkillBundle() {
|
|
301
219
|
return {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
220
|
+
notes: [
|
|
221
|
+
"Files under mcps/ are inert bundled files. Configure MCP servers through normal MCP configuration paths.",
|
|
222
|
+
"After editing SKILL.md or bundled files with non-creator tools, run skill_refresh so the current session sees the latest skill content."
|
|
223
|
+
]
|
|
305
224
|
};
|
|
306
225
|
}
|
|
307
226
|
const creatorToolsFactory = {
|
|
@@ -315,7 +234,7 @@ const creatorToolsFactory = {
|
|
|
315
234
|
const enabledTools = config.enabledTools ?? import_schemas.CREATOR_TOOL_NAMES;
|
|
316
235
|
const skillCreateTool = (0, import_core.defineTool)({
|
|
317
236
|
id: "skill_create",
|
|
318
|
-
description: "Create a standalone SKILL.md file, scaffold bundled resource directories, and register it with the running agent.
|
|
237
|
+
description: "Create a standalone SKILL.md file, scaffold bundled resource directories, and register it with the running agent. Files under mcps/ are inert bundled files.",
|
|
319
238
|
inputSchema: SkillCreateInputSchema,
|
|
320
239
|
execute: async (input, context) => {
|
|
321
240
|
const resolvedInput = resolveSkillCreateInput(input);
|
|
@@ -343,9 +262,9 @@ const creatorToolsFactory = {
|
|
|
343
262
|
(directory) => import_node_fs.promises.mkdir(import_node_path.default.join(skillDir, directory), { recursive: true })
|
|
344
263
|
)
|
|
345
264
|
);
|
|
346
|
-
const refreshed = await
|
|
265
|
+
const refreshed = await refreshAgentSkills(context);
|
|
347
266
|
const displayName = titleizeSkillId(skillId) || skillId;
|
|
348
|
-
const bundleDetails = inspectSkillBundle(
|
|
267
|
+
const bundleDetails = inspectSkillBundle();
|
|
349
268
|
return {
|
|
350
269
|
created: true,
|
|
351
270
|
id: skillId,
|
|
@@ -356,7 +275,7 @@ const creatorToolsFactory = {
|
|
|
356
275
|
resourceDirectories: SKILL_RESOURCE_DIRECTORIES.map(
|
|
357
276
|
(directory) => import_node_path.default.join(skillDir, directory)
|
|
358
277
|
),
|
|
359
|
-
|
|
278
|
+
skillsRefreshed: refreshed,
|
|
360
279
|
...bundleDetails
|
|
361
280
|
};
|
|
362
281
|
}
|
|
@@ -371,10 +290,7 @@ const creatorToolsFactory = {
|
|
|
371
290
|
context: "skill_update",
|
|
372
291
|
hint: "Use kebab-case skill ids (e.g., release-notes)"
|
|
373
292
|
});
|
|
374
|
-
const { scope,
|
|
375
|
-
input,
|
|
376
|
-
context
|
|
377
|
-
);
|
|
293
|
+
const { scope, skillFile } = await resolveExistingSkillLocation(input, context);
|
|
378
294
|
const exists = await pathExists(skillFile);
|
|
379
295
|
if (!exists) {
|
|
380
296
|
throw import_core.ToolError.validationFailed(
|
|
@@ -382,40 +298,36 @@ const creatorToolsFactory = {
|
|
|
382
298
|
`Skill not found at ${skillFile}`
|
|
383
299
|
);
|
|
384
300
|
}
|
|
385
|
-
const
|
|
386
|
-
const description = input.description?.trim() ||
|
|
301
|
+
const existingDescription = await readSkillDescription(skillFile);
|
|
302
|
+
const description = input.description?.trim() || existingDescription;
|
|
387
303
|
if (!description) {
|
|
388
304
|
throw import_core.ToolError.validationFailed(
|
|
389
305
|
"skill_update",
|
|
390
306
|
"description is required when the existing skill is missing one"
|
|
391
307
|
);
|
|
392
308
|
}
|
|
393
|
-
const allowedTools = input.allowedTools !== void 0 ? input.allowedTools : existing.allowedTools;
|
|
394
|
-
const toolkits = input.toolkits !== void 0 ? input.toolkits : existing.toolkits;
|
|
395
309
|
const markdown = buildSkillMarkdownFromParts({
|
|
396
310
|
id: skillId,
|
|
397
311
|
description,
|
|
398
|
-
content: input.content.trim()
|
|
399
|
-
allowedTools,
|
|
400
|
-
toolkits
|
|
312
|
+
content: input.content.trim()
|
|
401
313
|
});
|
|
402
314
|
await import_node_fs.promises.writeFile(skillFile, markdown, "utf-8");
|
|
403
|
-
const refreshed = await
|
|
404
|
-
const bundleDetails = inspectSkillBundle(
|
|
315
|
+
const refreshed = await refreshAgentSkills(context);
|
|
316
|
+
const bundleDetails = inspectSkillBundle();
|
|
405
317
|
return {
|
|
406
318
|
updated: true,
|
|
407
319
|
id: skillId,
|
|
408
320
|
description,
|
|
409
321
|
scope,
|
|
410
322
|
path: skillFile,
|
|
411
|
-
|
|
323
|
+
skillsRefreshed: refreshed,
|
|
412
324
|
...bundleDetails
|
|
413
325
|
};
|
|
414
326
|
}
|
|
415
327
|
});
|
|
416
328
|
const skillRefreshTool = (0, import_core.defineTool)({
|
|
417
329
|
id: "skill_refresh",
|
|
418
|
-
description: "Refresh one standalone skill bundle in the current session after editing SKILL.md,
|
|
330
|
+
description: "Refresh one standalone skill bundle in the current session after editing SKILL.md, handlers/, scripts/, mcps/, or references/.",
|
|
419
331
|
inputSchema: SkillRefreshInputSchema,
|
|
420
332
|
execute: async (input, context) => {
|
|
421
333
|
const skillId = input.id.trim();
|
|
@@ -423,15 +335,12 @@ const creatorToolsFactory = {
|
|
|
423
335
|
context: "skill_refresh",
|
|
424
336
|
hint: "Use kebab-case skill ids (e.g., release-notes)"
|
|
425
337
|
});
|
|
426
|
-
if (!context.
|
|
338
|
+
if (!context.services?.skills) {
|
|
427
339
|
throw import_core.ToolError.configInvalid(
|
|
428
|
-
"skill_refresh requires ToolExecutionContext.
|
|
340
|
+
"skill_refresh requires ToolExecutionContext.services.skills"
|
|
429
341
|
);
|
|
430
342
|
}
|
|
431
|
-
const { scope,
|
|
432
|
-
input,
|
|
433
|
-
context
|
|
434
|
-
);
|
|
343
|
+
const { scope, skillFile } = await resolveExistingSkillLocation(input, context);
|
|
435
344
|
const exists = await pathExists(skillFile);
|
|
436
345
|
if (!exists) {
|
|
437
346
|
throw import_core.ToolError.validationFailed(
|
|
@@ -439,14 +348,14 @@ const creatorToolsFactory = {
|
|
|
439
348
|
`Skill not found at ${skillFile}`
|
|
440
349
|
);
|
|
441
350
|
}
|
|
442
|
-
const refreshed = await
|
|
443
|
-
const bundleDetails = inspectSkillBundle(
|
|
351
|
+
const refreshed = await refreshAgentSkills(context);
|
|
352
|
+
const bundleDetails = inspectSkillBundle();
|
|
444
353
|
return {
|
|
445
354
|
refreshed: true,
|
|
446
355
|
id: skillId,
|
|
447
356
|
scope,
|
|
448
357
|
path: skillFile,
|
|
449
|
-
|
|
358
|
+
skillsRefreshed: refreshed,
|
|
450
359
|
...bundleDetails
|
|
451
360
|
};
|
|
452
361
|
}
|
|
@@ -460,28 +369,22 @@ const creatorToolsFactory = {
|
|
|
460
369
|
const normalizedQuery = normalizeSkillQuery(query);
|
|
461
370
|
const hasQuery = normalizedQuery.length > 0;
|
|
462
371
|
const limit = input.limit ?? (hasQuery ? void 0 : 50);
|
|
463
|
-
const
|
|
464
|
-
if (!
|
|
372
|
+
const skillManager = context.services?.skills;
|
|
373
|
+
if (!skillManager) {
|
|
465
374
|
throw import_core.ToolError.configInvalid(
|
|
466
|
-
"skill_search requires ToolExecutionContext.services.
|
|
375
|
+
"skill_search requires ToolExecutionContext.services.skills"
|
|
467
376
|
);
|
|
468
377
|
}
|
|
469
|
-
const loaded = await
|
|
470
|
-
let results =
|
|
471
|
-
id,
|
|
472
|
-
name:
|
|
473
|
-
...info.
|
|
474
|
-
...info.commandName ? { commandName: info.commandName } : {},
|
|
475
|
-
...info.description ? { description: info.description } : {},
|
|
476
|
-
...info.context ? { context: info.context } : {},
|
|
477
|
-
...info.agent ? { agent: info.agent } : {}
|
|
378
|
+
const loaded = await skillManager.list();
|
|
379
|
+
let results = loaded.map((info) => ({
|
|
380
|
+
id: info.id,
|
|
381
|
+
name: resolveSkillName(info),
|
|
382
|
+
...info.description ? { description: info.description } : {}
|
|
478
383
|
}));
|
|
479
384
|
if (hasQuery && normalizedQuery) {
|
|
480
385
|
results = results.filter((entry) => {
|
|
481
386
|
if (matchesSkillQuery(entry.id, normalizedQuery)) return true;
|
|
482
387
|
if (matchesSkillQuery(entry.name, normalizedQuery)) return true;
|
|
483
|
-
if (matchesSkillQuery(entry.displayName, normalizedQuery)) return true;
|
|
484
|
-
if (matchesSkillQuery(entry.commandName, normalizedQuery)) return true;
|
|
485
388
|
if (matchesSkillQuery(entry.description, normalizedQuery)) return true;
|
|
486
389
|
return false;
|
|
487
390
|
});
|
|
@@ -552,7 +455,7 @@ const creatorToolsFactory = {
|
|
|
552
455
|
count: limited.length,
|
|
553
456
|
total: tools.length,
|
|
554
457
|
tools: limited,
|
|
555
|
-
_hint: limited.length > 0 ? "Use tool ids
|
|
458
|
+
_hint: limited.length > 0 ? "Use exact tool ids when configuring agent permissions." : "No tools matched the query."
|
|
556
459
|
};
|
|
557
460
|
}
|
|
558
461
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/tool-factories/creator-tools/factory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/tool-factories/creator-tools/factory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAUvD,OAAO,EAIH,KAAK,kBAAkB,EAC1B,MAAM,cAAc,CAAC;AAqVtB,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,kBAAkB,CAmS/D,CAAC"}
|