@dexto/tools-builtins 1.7.1 → 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.
Files changed (60) hide show
  1. package/dist/builtin-tools-factory.cjs +4 -0
  2. package/dist/builtin-tools-factory.d.ts +2 -1
  3. package/dist/builtin-tools-factory.d.ts.map +1 -1
  4. package/dist/builtin-tools-factory.js +4 -0
  5. package/dist/builtin-tools-factory.test.cjs +3 -2
  6. package/dist/builtin-tools-factory.test.js +3 -2
  7. package/dist/implementations/ask-user-tool.cjs +5 -5
  8. package/dist/implementations/ask-user-tool.d.ts +1 -1
  9. package/dist/implementations/ask-user-tool.d.ts.map +1 -1
  10. package/dist/implementations/ask-user-tool.js +6 -1
  11. package/dist/implementations/delegate-to-url-tool.cjs +15 -14
  12. package/dist/implementations/delegate-to-url-tool.d.ts +1 -1
  13. package/dist/implementations/delegate-to-url-tool.d.ts.map +1 -1
  14. package/dist/implementations/delegate-to-url-tool.js +2 -8
  15. package/dist/implementations/exa-code-search-tool.cjs +4 -4
  16. package/dist/implementations/exa-code-search-tool.d.ts +1 -1
  17. package/dist/implementations/exa-code-search-tool.d.ts.map +1 -1
  18. package/dist/implementations/exa-code-search-tool.js +1 -1
  19. package/dist/implementations/exa-mcp.cjs +7 -7
  20. package/dist/implementations/exa-mcp.d.ts +1 -1
  21. package/dist/implementations/exa-mcp.d.ts.map +1 -1
  22. package/dist/implementations/exa-mcp.js +2 -2
  23. package/dist/implementations/exa-web-search-tool.cjs +4 -4
  24. package/dist/implementations/exa-web-search-tool.d.ts +1 -1
  25. package/dist/implementations/exa-web-search-tool.d.ts.map +1 -1
  26. package/dist/implementations/exa-web-search-tool.js +1 -1
  27. package/dist/implementations/get-resource-tool.cjs +11 -11
  28. package/dist/implementations/get-resource-tool.d.ts +1 -1
  29. package/dist/implementations/get-resource-tool.d.ts.map +1 -1
  30. package/dist/implementations/get-resource-tool.js +12 -7
  31. package/dist/implementations/http-request-tool.cjs +45 -44
  32. package/dist/implementations/http-request-tool.d.ts +1 -1
  33. package/dist/implementations/http-request-tool.d.ts.map +1 -1
  34. package/dist/implementations/http-request-tool.js +2 -8
  35. package/dist/implementations/invoke-skill-tool.cjs +22 -170
  36. package/dist/implementations/invoke-skill-tool.d.ts +1 -8
  37. package/dist/implementations/invoke-skill-tool.d.ts.map +1 -1
  38. package/dist/implementations/invoke-skill-tool.js +19 -167
  39. package/dist/implementations/invoke-skill-tool.test.cjs +61 -85
  40. package/dist/implementations/invoke-skill-tool.test.js +61 -85
  41. package/dist/implementations/list-resources-tool.cjs +18 -16
  42. package/dist/implementations/list-resources-tool.d.ts +2 -2
  43. package/dist/implementations/list-resources-tool.d.ts.map +1 -1
  44. package/dist/implementations/list-resources-tool.js +15 -13
  45. package/dist/implementations/read-skill-tool.cjs +89 -0
  46. package/dist/implementations/read-skill-tool.d.ts +9 -0
  47. package/dist/implementations/read-skill-tool.d.ts.map +1 -0
  48. package/dist/implementations/read-skill-tool.js +65 -0
  49. package/dist/implementations/read-skill-tool.test.cjs +82 -0
  50. package/dist/implementations/read-skill-tool.test.d.ts +2 -0
  51. package/dist/implementations/read-skill-tool.test.d.ts.map +1 -0
  52. package/dist/implementations/read-skill-tool.test.js +81 -0
  53. package/dist/implementations/sleep-tool.cjs +3 -3
  54. package/dist/implementations/sleep-tool.d.ts +1 -1
  55. package/dist/implementations/sleep-tool.d.ts.map +1 -1
  56. package/dist/implementations/sleep-tool.js +1 -1
  57. package/dist/index.d.cts +2 -1
  58. package/dist/index.d.ts +1 -0
  59. package/dist/index.d.ts.map +1 -1
  60. package/package.json +3 -3
@@ -23,7 +23,8 @@ __export(http_request_tool_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(http_request_tool_exports);
25
25
  var import_zod = require("zod");
26
- var import_core = require("@dexto/core");
26
+ var import_errors = require("@dexto/core/errors");
27
+ var import_tools = require("@dexto/core/tools");
27
28
  var import_node_dns = require("node:dns");
28
29
  var import_node_net = require("node:net");
29
30
  var import_node_util = require("node:util");
@@ -116,10 +117,10 @@ function createSafeLookup(config) {
116
117
  if (BLOCKED_HOSTNAMES.has(hostname) || hostname.endsWith(".localhost")) {
117
118
  emitError(
118
119
  toErrnoException(
119
- new import_core.DextoRuntimeError(
120
+ new import_errors.DextoRuntimeError(
120
121
  "HTTP_REQUEST_UNSAFE_TARGET",
121
- import_core.ErrorScope.TOOLS,
122
- import_core.ErrorType.FORBIDDEN,
122
+ import_errors.ErrorScope.TOOLS,
123
+ import_errors.ErrorType.FORBIDDEN,
123
124
  `Blocked request to local hostname: ${hostname}`
124
125
  )
125
126
  )
@@ -135,10 +136,10 @@ function createSafeLookup(config) {
135
136
  if (!records.length) {
136
137
  emitError(
137
138
  toErrnoException(
138
- new import_core.DextoRuntimeError(
139
+ new import_errors.DextoRuntimeError(
139
140
  "HTTP_REQUEST_DNS_FAILED",
140
- import_core.ErrorScope.TOOLS,
141
- import_core.ErrorType.THIRD_PARTY,
141
+ import_errors.ErrorScope.TOOLS,
142
+ import_errors.ErrorType.THIRD_PARTY,
142
143
  `Failed to resolve hostname: ${hostname}`
143
144
  )
144
145
  )
@@ -149,10 +150,10 @@ function createSafeLookup(config) {
149
150
  if (isPrivateAddress(record.address)) {
150
151
  emitError(
151
152
  toErrnoException(
152
- new import_core.DextoRuntimeError(
153
+ new import_errors.DextoRuntimeError(
153
154
  "HTTP_REQUEST_UNSAFE_TARGET",
154
- import_core.ErrorScope.TOOLS,
155
- import_core.ErrorType.FORBIDDEN,
155
+ import_errors.ErrorScope.TOOLS,
156
+ import_errors.ErrorType.FORBIDDEN,
156
157
  `Blocked request to private address: ${record.address}`
157
158
  )
158
159
  )
@@ -174,10 +175,10 @@ function createSafeLookup(config) {
174
175
  if (!selected) {
175
176
  emitError(
176
177
  toErrnoException(
177
- new import_core.DextoRuntimeError(
178
+ new import_errors.DextoRuntimeError(
178
179
  "HTTP_REQUEST_DNS_FAILED",
179
- import_core.ErrorScope.TOOLS,
180
- import_core.ErrorType.THIRD_PARTY,
180
+ import_errors.ErrorScope.TOOLS,
181
+ import_errors.ErrorType.THIRD_PARTY,
181
182
  `Failed to resolve hostname: ${hostname}`
182
183
  )
183
184
  )
@@ -193,10 +194,10 @@ function createSafeLookup(config) {
193
194
  } catch {
194
195
  }
195
196
  } catch (error) {
196
- const err = error instanceof import_core.DextoRuntimeError ? error : new import_core.DextoRuntimeError(
197
+ const err = error instanceof import_errors.DextoRuntimeError ? error : new import_errors.DextoRuntimeError(
197
198
  "HTTP_REQUEST_DNS_FAILED",
198
- import_core.ErrorScope.TOOLS,
199
- import_core.ErrorType.THIRD_PARTY,
199
+ import_errors.ErrorScope.TOOLS,
200
+ import_errors.ErrorType.THIRD_PARTY,
200
201
  `Failed to resolve hostname: ${hostname}`
201
202
  );
202
203
  emitError(toErrnoException(err));
@@ -210,35 +211,35 @@ function createSafeDispatcher() {
210
211
  }
211
212
  async function assertSafeUrl(requestUrl) {
212
213
  if (!["http:", "https:"].includes(requestUrl.protocol)) {
213
- throw new import_core.DextoRuntimeError(
214
+ throw new import_errors.DextoRuntimeError(
214
215
  "HTTP_REQUEST_UNSUPPORTED_PROTOCOL",
215
- import_core.ErrorScope.TOOLS,
216
- import_core.ErrorType.USER,
216
+ import_errors.ErrorScope.TOOLS,
217
+ import_errors.ErrorType.USER,
217
218
  `Unsupported URL protocol: ${requestUrl.protocol}`
218
219
  );
219
220
  }
220
221
  const hostname = requestUrl.hostname.trim();
221
222
  if (!hostname) {
222
- throw new import_core.DextoRuntimeError(
223
+ throw new import_errors.DextoRuntimeError(
223
224
  "HTTP_REQUEST_INVALID_TARGET",
224
- import_core.ErrorScope.TOOLS,
225
- import_core.ErrorType.USER,
225
+ import_errors.ErrorScope.TOOLS,
226
+ import_errors.ErrorType.USER,
226
227
  "Request URL hostname is required"
227
228
  );
228
229
  }
229
230
  if (BLOCKED_HOSTNAMES.has(hostname) || hostname.endsWith(".localhost")) {
230
- throw new import_core.DextoRuntimeError(
231
+ throw new import_errors.DextoRuntimeError(
231
232
  "HTTP_REQUEST_UNSAFE_TARGET",
232
- import_core.ErrorScope.TOOLS,
233
- import_core.ErrorType.FORBIDDEN,
233
+ import_errors.ErrorScope.TOOLS,
234
+ import_errors.ErrorType.FORBIDDEN,
234
235
  `Blocked request to local hostname: ${hostname}`
235
236
  );
236
237
  }
237
238
  if (isPrivateAddress(hostname)) {
238
- throw new import_core.DextoRuntimeError(
239
+ throw new import_errors.DextoRuntimeError(
239
240
  "HTTP_REQUEST_UNSAFE_TARGET",
240
- import_core.ErrorScope.TOOLS,
241
- import_core.ErrorType.FORBIDDEN,
241
+ import_errors.ErrorScope.TOOLS,
242
+ import_errors.ErrorType.FORBIDDEN,
242
243
  `Blocked request to private address: ${hostname}`
243
244
  );
244
245
  }
@@ -248,10 +249,10 @@ async function readResponseTextWithLimit(response) {
248
249
  if (contentLength) {
249
250
  const parsed = Number.parseInt(contentLength, 10);
250
251
  if (!Number.isNaN(parsed) && parsed > MAX_RESPONSE_BYTES) {
251
- throw new import_core.DextoRuntimeError(
252
+ throw new import_errors.DextoRuntimeError(
252
253
  "HTTP_REQUEST_RESPONSE_TOO_LARGE",
253
- import_core.ErrorScope.TOOLS,
254
- import_core.ErrorType.THIRD_PARTY,
254
+ import_errors.ErrorScope.TOOLS,
255
+ import_errors.ErrorType.THIRD_PARTY,
255
256
  `Response too large: ${parsed} bytes exceeds ${MAX_RESPONSE_BYTES} byte limit`
256
257
  );
257
258
  }
@@ -270,10 +271,10 @@ async function readResponseTextWithLimit(response) {
270
271
  total += value.length;
271
272
  if (total > MAX_RESPONSE_BYTES) {
272
273
  await reader.cancel();
273
- throw new import_core.DextoRuntimeError(
274
+ throw new import_errors.DextoRuntimeError(
274
275
  "HTTP_REQUEST_RESPONSE_TOO_LARGE",
275
- import_core.ErrorScope.TOOLS,
276
- import_core.ErrorType.THIRD_PARTY,
276
+ import_errors.ErrorScope.TOOLS,
277
+ import_errors.ErrorType.THIRD_PARTY,
277
278
  `Response too large: exceeded ${MAX_RESPONSE_BYTES} byte limit`
278
279
  );
279
280
  }
@@ -283,14 +284,14 @@ async function readResponseTextWithLimit(response) {
283
284
  return result;
284
285
  }
285
286
  function createHttpRequestTool() {
286
- return (0, import_core.defineTool)({
287
+ return (0, import_tools.defineTool)({
287
288
  id: "http_request",
288
289
  description: "Make a direct HTTP request using fetch. Supports method, headers, query params, JSON bodies, and timeouts. Returns status, headers, raw body text, and parsed JSON when available.",
289
290
  inputSchema: HttpRequestInputSchema,
290
291
  presentation: {
291
- describeHeader: (input) => (0, import_core.createLocalToolCallHeader)({
292
+ describeHeader: (input) => (0, import_tools.createLocalToolCallHeader)({
292
293
  title: "Fetch",
293
- argsText: (0, import_core.truncateForHeader)(input.url, 140)
294
+ argsText: (0, import_tools.truncateForHeader)(input.url, 140)
294
295
  })
295
296
  },
296
297
  async execute(input, _context) {
@@ -347,21 +348,21 @@ function createHttpRequestTool() {
347
348
  };
348
349
  return payload;
349
350
  } catch (error) {
350
- if (error instanceof import_core.DextoRuntimeError) {
351
+ if (error instanceof import_errors.DextoRuntimeError) {
351
352
  throw error;
352
353
  }
353
354
  if (error instanceof Error && error.name === "AbortError") {
354
- throw new import_core.DextoRuntimeError(
355
+ throw new import_errors.DextoRuntimeError(
355
356
  "HTTP_REQUEST_TIMEOUT",
356
- import_core.ErrorScope.TOOLS,
357
- import_core.ErrorType.TIMEOUT,
357
+ import_errors.ErrorScope.TOOLS,
358
+ import_errors.ErrorType.TIMEOUT,
358
359
  `HTTP request timed out after ${timeoutMs}ms`
359
360
  );
360
361
  }
361
- throw new import_core.DextoRuntimeError(
362
+ throw new import_errors.DextoRuntimeError(
362
363
  "HTTP_REQUEST_FAILED",
363
- import_core.ErrorScope.TOOLS,
364
- import_core.ErrorType.THIRD_PARTY,
364
+ import_errors.ErrorScope.TOOLS,
365
+ import_errors.ErrorType.THIRD_PARTY,
365
366
  `HTTP request failed: ${error instanceof Error ? error.message : String(error)}`
366
367
  );
367
368
  } finally {
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import type { Tool } from '@dexto/core';
2
+ import type { Tool } from '@dexto/core/tools';
3
3
  import { promises as dns, type LookupAddress, type LookupOptions } from 'node:dns';
4
4
  declare const HttpRequestInputSchema: z.ZodObject<{
5
5
  url: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"http-request-tool.d.ts","sourceRoot":"","sources":["../../src/implementations/http-request-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,aAAa,CAAC;AAS9D,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAKnF,QAAA,MAAM,sBAAsB;;;;;;;;;;;;;kBA2Bf,CAAC;AA8Bd,KAAK,cAAc,GACb,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,GAC9E,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,GAAG,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC,CAAC;AAoDhF,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE;IACtC,SAAS,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,CAAC;CACjC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,KAAK,IAAI,CAyI/E;AA2FD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAuG3E"}
1
+ {"version":3,"file":"http-request-tool.d.ts","sourceRoot":"","sources":["../../src/implementations/http-request-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,mBAAmB,CAAC;AAGpE,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAKnF,QAAA,MAAM,sBAAsB;;;;;;;;;;;;;kBA2Bf,CAAC;AA8Bd,KAAK,cAAc,GACb,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,GAC9E,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,GAAG,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC,CAAC;AAoDhF,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE;IACtC,SAAS,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,CAAC;CACjC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,KAAK,IAAI,CAyI/E;AA2FD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAuG3E"}
@@ -1,12 +1,6 @@
1
1
  import { z } from "zod";
2
- import {
3
- DextoRuntimeError,
4
- ErrorScope,
5
- ErrorType,
6
- createLocalToolCallHeader,
7
- defineTool,
8
- truncateForHeader
9
- } from "@dexto/core";
2
+ import { DextoRuntimeError, ErrorScope, ErrorType } from "@dexto/core/errors";
3
+ import { createLocalToolCallHeader, defineTool, truncateForHeader } from "@dexto/core/tools";
10
4
  import { promises as dns } from "node:dns";
11
5
  import { isIP } from "node:net";
12
6
  import { TextDecoder } from "node:util";
@@ -22,140 +22,53 @@ __export(invoke_skill_tool_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(invoke_skill_tool_exports);
24
24
  var import_zod = require("zod");
25
- var import_core = require("@dexto/core");
25
+ var import_tools = require("@dexto/core/tools");
26
26
  const InvokeSkillInputSchema = import_zod.z.object({
27
27
  skill: import_zod.z.string().min(1, "Skill name is required").describe(
28
28
  'The name of the skill to invoke (e.g., "plugin-name:skill-name" or "skill-name")'
29
29
  ),
30
30
  args: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional().describe("Optional arguments to pass to the skill"),
31
- taskContext: import_zod.z.string().optional().describe(
32
- "Context about what task this skill should accomplish. Recommended for forked skills to provide context since they run in isolation without conversation history."
33
- )
31
+ taskContext: import_zod.z.string().optional().describe("Context about what task this skill should accomplish")
34
32
  }).strict();
35
33
  function createInvokeSkillTool() {
36
- return (0, import_core.defineTool)({
34
+ return (0, import_tools.defineTool)({
37
35
  id: "invoke_skill",
38
36
  description: buildToolDescription(),
39
37
  inputSchema: InvokeSkillInputSchema,
40
38
  presentation: {
41
39
  describeHeader: (input) => {
42
- const skillName = input.skill;
43
- const colonIndex = skillName.indexOf(":");
44
- const displaySkillName = colonIndex >= 0 ? skillName.slice(colonIndex + 1) : skillName;
45
- return (0, import_core.createLocalToolCallHeader)({
40
+ const colonIndex = input.skill.indexOf(":");
41
+ const displaySkillName = colonIndex >= 0 ? input.skill.slice(colonIndex + 1) : input.skill;
42
+ return (0, import_tools.createLocalToolCallHeader)({
46
43
  title: "Skill",
47
44
  argsText: `/${displaySkillName}`
48
45
  });
49
46
  }
50
47
  },
51
48
  async execute(input, context) {
52
- const { skill, args, taskContext } = input;
53
- const promptManager = context.services?.prompts;
54
- if (!promptManager) {
55
- throw import_core.ToolError.configInvalid(
56
- "invoke_skill requires ToolExecutionContext.services.prompts"
49
+ const skillManager = context.services?.skills;
50
+ if (!skillManager) {
51
+ throw import_tools.ToolError.configInvalid(
52
+ "invoke_skill requires ToolExecutionContext.services.skills"
57
53
  );
58
54
  }
59
- const autoInvocable = await promptManager.listAutoInvocablePrompts();
60
- let skillKey;
61
- let matchedInfo;
62
- for (const key of Object.keys(autoInvocable)) {
63
- const info = autoInvocable[key];
64
- if (!info) continue;
65
- if (key === skill || info.displayName === skill || info.commandName === skill || info.name === skill) {
66
- skillKey = key;
67
- matchedInfo = info;
68
- break;
69
- }
70
- }
71
- if (!skillKey) {
72
- return {
73
- error: `Skill '${skill}' not found or not available for model invocation. Use a skill from the available list.`,
74
- availableSkills: Object.keys(autoInvocable)
75
- };
76
- }
77
- const toolkits = Array.isArray(matchedInfo?.metadata?.toolkits) ? (matchedInfo?.metadata?.toolkits).filter((toolkit) => typeof toolkit === "string").map((toolkit) => toolkit.trim()).filter((toolkit) => toolkit.length > 0) : [];
78
- if (toolkits.length > 0) {
79
- if (!context.agent?.loadToolkits) {
80
- return {
81
- error: `Skill '${skill}' requires toolkits (${toolkits.join(
82
- ", "
83
- )}), but this agent does not support dynamic tool loading.`,
84
- toolkits
85
- };
86
- }
87
- try {
88
- await context.agent.loadToolkits(toolkits);
89
- } catch (error) {
90
- return {
91
- error: error instanceof Error ? error.message : "Failed to load required toolkits",
92
- toolkits
93
- };
94
- }
95
- }
96
- const promptDef = await promptManager.getPromptDefinition(skillKey);
97
- const taskForker = context.services?.taskForker;
98
- if (promptDef?.context === "fork" && !taskForker) {
55
+ const invoked = await skillManager.invoke(input.skill, input.args);
56
+ if (!invoked) {
57
+ const availableSkills = (await skillManager.list()).map(
58
+ (availableSkill) => availableSkill.displayName
59
+ );
99
60
  return {
100
- error: `Skill '${skill}' requires fork execution (context: fork), but agent spawning is not available.`,
101
- skill: skillKey
61
+ error: `Skill '${input.skill}' not found or not available for model invocation. Use a skill from the available list.`,
62
+ availableSkills
102
63
  };
103
64
  }
104
- const skillMcpError = await ensureSkillMcpServersConnected(skill, matchedInfo, context);
105
- if (skillMcpError) {
106
- return skillMcpError;
107
- }
108
- if (promptDef?.context !== "fork" && promptDef?.allowedTools && promptDef.allowedTools.length > 0 && context.sessionId && context.agent?.toolManager) {
109
- try {
110
- context.agent.toolManager.addSessionAutoApproveTools(
111
- context.sessionId,
112
- promptDef.allowedTools
113
- );
114
- } catch (error) {
115
- context.logger?.warn("Failed to add auto-approve tools for skill", {
116
- tools: promptDef.allowedTools,
117
- error: error instanceof Error ? error.message : String(error)
118
- });
119
- }
120
- }
121
- const promptResult = await promptManager.getPrompt(skillKey, args);
122
- const flattened = (0, import_core.flattenPromptResult)(promptResult);
123
- const content = flattened.text;
124
- if (promptDef?.context === "fork") {
125
- const activeTaskForker = taskForker;
126
- if (!activeTaskForker) {
127
- return {
128
- error: `Skill '${skill}' requires fork execution (context: fork), but agent spawning is not available.`,
129
- skill: skillKey
130
- };
131
- }
132
- const instructions = taskContext ? `## Task Context
133
- ${taskContext}
65
+ const content = input.taskContext ? `## Task Context
66
+ ${input.taskContext}
134
67
 
135
68
  ## Skill Instructions
136
- ${content}` : content;
137
- const forkOptions = {
138
- task: `Skill: ${skill}`,
139
- instructions,
140
- autoApprove: true
141
- };
142
- if (promptDef.agent) {
143
- forkOptions.agentId = promptDef.agent;
144
- }
145
- if (context.toolCallId) {
146
- forkOptions.toolCallId = context.toolCallId;
147
- }
148
- if (context.sessionId) {
149
- forkOptions.sessionId = context.sessionId;
150
- }
151
- const result = await activeTaskForker.fork(forkOptions);
152
- if (result.success) {
153
- return result.response ?? "Task completed successfully.";
154
- }
155
- return `Error: ${result.error ?? "Unknown error during forked execution"}`;
156
- }
69
+ ${invoked.instructions}` : invoked.instructions;
157
70
  return {
158
- skill: skillKey,
71
+ skill: invoked.id,
159
72
  content,
160
73
  instructions: "Follow the instructions in the skill content above to complete the task."
161
74
  };
@@ -163,76 +76,15 @@ ${content}` : content;
163
76
  });
164
77
  }
165
78
  function buildToolDescription() {
166
- return `Invoke a skill to load and execute specialized instructions for a task. Skills are predefined prompts that guide how to handle specific scenarios.
79
+ return `Invoke a skill to load specialized instructions for a task.
167
80
 
168
81
  When to use:
169
82
  - When you recognize a task that matches an available skill
170
83
  - When you need specialized guidance for a complex operation
171
84
  - When the user references a skill by name
172
85
 
173
- Parameters:
174
- - skill: The name of the skill to invoke
175
- - args: Optional arguments to pass to the skill (e.g., for $ARGUMENTS substitution)
176
- - taskContext: Context about what you're trying to accomplish (important for forked skills that run in isolation)
177
-
178
- Execution modes:
179
- - **Inline skills**: Return instructions for you to follow in the current conversation
180
- - **Fork skills**: Automatically execute in an isolated subagent and return the result (no additional tool calls needed)
181
- - **Bundled MCP skills**: Automatically connect any MCP servers carried inside the skill bundle when the skill is invoked
182
-
183
- Fork skills run in complete isolation without access to conversation history. They're useful for tasks that should run independently.
184
-
185
86
  Available skills are listed in your system prompt. Use the skill name exactly as shown.`;
186
87
  }
187
- function getSkillBundledMcpServers(promptInfo) {
188
- const rawServers = promptInfo?.metadata?.mcpServers;
189
- if (!rawServers || typeof rawServers !== "object" || Array.isArray(rawServers)) {
190
- return {};
191
- }
192
- return Object.fromEntries(
193
- Object.entries(rawServers).filter(
194
- ([, config]) => typeof config === "object" && config !== null && !Array.isArray(config)
195
- )
196
- );
197
- }
198
- async function ensureSkillMcpServersConnected(skill, promptInfo, context) {
199
- const mcpServers = getSkillBundledMcpServers(promptInfo);
200
- const serverNames = Object.keys(mcpServers);
201
- if (serverNames.length === 0) {
202
- return void 0;
203
- }
204
- if (!context.agent?.addMcpServer || !context.agent.getMcpServerStatus || !context.agent.enableMcpServer) {
205
- return {
206
- error: `Skill '${skill}' requires bundled MCP servers (${serverNames.join(", ")}), but this agent does not support dynamic MCP loading.`,
207
- mcpServers: serverNames
208
- };
209
- }
210
- try {
211
- for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
212
- let serverStatus = context.agent.getMcpServerStatus(serverName);
213
- if (!serverStatus) {
214
- await context.agent.addMcpServer(serverName, serverConfig);
215
- serverStatus = context.agent.getMcpServerStatus(serverName);
216
- }
217
- if (!serverStatus?.enabled || serverStatus.status !== "connected") {
218
- await context.agent.enableMcpServer(serverName);
219
- serverStatus = context.agent.getMcpServerStatus(serverName);
220
- }
221
- if (!serverStatus || serverStatus.status !== "connected") {
222
- return {
223
- error: `Skill '${skill}' requires MCP server '${serverName}', but it is currently ${serverStatus?.status ?? "unavailable"}${serverStatus?.error ? `: ${serverStatus.error}` : ""}.`,
224
- mcpServers: serverNames
225
- };
226
- }
227
- }
228
- } catch (error) {
229
- return {
230
- error: error instanceof Error ? error.message : "Failed to connect bundled MCP servers for skill",
231
- mcpServers: serverNames
232
- };
233
- }
234
- return void 0;
235
- }
236
88
  // Annotate the CommonJS export names for ESM import in node:
237
89
  0 && (module.exports = {
238
90
  createInvokeSkillTool
@@ -1,17 +1,10 @@
1
1
  import { z } from 'zod';
2
- import type { Tool } from '@dexto/core';
2
+ import type { Tool } from '@dexto/core/tools';
3
3
  declare const InvokeSkillInputSchema: z.ZodObject<{
4
4
  skill: z.ZodString;
5
5
  args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
6
6
  taskContext: z.ZodOptional<z.ZodString>;
7
7
  }, z.core.$strict>;
8
- /**
9
- * Create the `invoke_skill` tool.
10
- *
11
- * Loads an auto-invocable prompt (“skill”) via the PromptManager and returns its content, or
12
- * forks the skill into a sub-agent when the skill is marked as `context: fork`.
13
- * Requires `ToolExecutionContext.services.prompts` and, for forked skills, `services.taskForker`.
14
- */
15
8
  export declare function createInvokeSkillTool(): Tool<typeof InvokeSkillInputSchema>;
16
9
  export {};
17
10
  //# sourceMappingURL=invoke-skill-tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"invoke-skill-tool.d.ts","sourceRoot":"","sources":["../../src/implementations/invoke-skill-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAIR,IAAI,EAEP,MAAM,aAAa,CAAC;AAErB,QAAA,MAAM,sBAAsB;;;;kBAmBf,CAAC;AAEd;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAuK3E"}
1
+ {"version":3,"file":"invoke-skill-tool.d.ts","sourceRoot":"","sources":["../../src/implementations/invoke-skill-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,mBAAmB,CAAC;AAapE,QAAA,MAAM,sBAAsB;;;;kBAiBf,CAAC;AAEd,wBAAgB,qBAAqB,IAAI,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAgD3E"}