@dexto/tools-builtins 1.6.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 (77) hide show
  1. package/LICENSE +44 -0
  2. package/dist/builtin-tools-factory.cjs +95 -0
  3. package/dist/builtin-tools-factory.d.cts +19 -0
  4. package/dist/builtin-tools-factory.d.ts +17 -0
  5. package/dist/builtin-tools-factory.d.ts.map +1 -0
  6. package/dist/builtin-tools-factory.js +69 -0
  7. package/dist/builtin-tools-factory.test.cjs +26 -0
  8. package/dist/builtin-tools-factory.test.d.cts +2 -0
  9. package/dist/builtin-tools-factory.test.d.ts +2 -0
  10. package/dist/builtin-tools-factory.test.d.ts.map +1 -0
  11. package/dist/builtin-tools-factory.test.js +25 -0
  12. package/dist/implementations/ask-user-tool.cjs +65 -0
  13. package/dist/implementations/ask-user-tool.d.cts +46 -0
  14. package/dist/implementations/ask-user-tool.d.ts +45 -0
  15. package/dist/implementations/ask-user-tool.d.ts.map +1 -0
  16. package/dist/implementations/ask-user-tool.js +41 -0
  17. package/dist/implementations/delegate-to-url-tool.cjs +183 -0
  18. package/dist/implementations/delegate-to-url-tool.d.cts +27 -0
  19. package/dist/implementations/delegate-to-url-tool.d.ts +26 -0
  20. package/dist/implementations/delegate-to-url-tool.d.ts.map +1 -0
  21. package/dist/implementations/delegate-to-url-tool.js +159 -0
  22. package/dist/implementations/delegate-to-url-tool.test.cjs +75 -0
  23. package/dist/implementations/delegate-to-url-tool.test.d.cts +2 -0
  24. package/dist/implementations/delegate-to-url-tool.test.d.ts +2 -0
  25. package/dist/implementations/delegate-to-url-tool.test.d.ts.map +1 -0
  26. package/dist/implementations/delegate-to-url-tool.test.js +74 -0
  27. package/dist/implementations/exa-code-search-tool.cjs +57 -0
  28. package/dist/implementations/exa-code-search-tool.d.cts +21 -0
  29. package/dist/implementations/exa-code-search-tool.d.ts +20 -0
  30. package/dist/implementations/exa-code-search-tool.d.ts.map +1 -0
  31. package/dist/implementations/exa-code-search-tool.js +33 -0
  32. package/dist/implementations/exa-mcp.cjs +98 -0
  33. package/dist/implementations/exa-mcp.d.cts +24 -0
  34. package/dist/implementations/exa-mcp.d.ts +23 -0
  35. package/dist/implementations/exa-mcp.d.ts.map +1 -0
  36. package/dist/implementations/exa-mcp.js +74 -0
  37. package/dist/implementations/exa-tools.test.cjs +91 -0
  38. package/dist/implementations/exa-tools.test.d.cts +2 -0
  39. package/dist/implementations/exa-tools.test.d.ts +2 -0
  40. package/dist/implementations/exa-tools.test.d.ts.map +1 -0
  41. package/dist/implementations/exa-tools.test.js +90 -0
  42. package/dist/implementations/exa-web-search-tool.cjs +63 -0
  43. package/dist/implementations/exa-web-search-tool.d.cts +30 -0
  44. package/dist/implementations/exa-web-search-tool.d.ts +29 -0
  45. package/dist/implementations/exa-web-search-tool.d.ts.map +1 -0
  46. package/dist/implementations/exa-web-search-tool.js +39 -0
  47. package/dist/implementations/get-resource-tool.cjs +121 -0
  48. package/dist/implementations/get-resource-tool.d.cts +22 -0
  49. package/dist/implementations/get-resource-tool.d.ts +21 -0
  50. package/dist/implementations/get-resource-tool.d.ts.map +1 -0
  51. package/dist/implementations/get-resource-tool.js +97 -0
  52. package/dist/implementations/http-request-tool.cjs +327 -0
  53. package/dist/implementations/http-request-tool.d.cts +31 -0
  54. package/dist/implementations/http-request-tool.d.ts +30 -0
  55. package/dist/implementations/http-request-tool.d.ts.map +1 -0
  56. package/dist/implementations/http-request-tool.js +303 -0
  57. package/dist/implementations/invoke-skill-tool.cjs +134 -0
  58. package/dist/implementations/invoke-skill-tool.d.cts +26 -0
  59. package/dist/implementations/invoke-skill-tool.d.ts +25 -0
  60. package/dist/implementations/invoke-skill-tool.d.ts.map +1 -0
  61. package/dist/implementations/invoke-skill-tool.js +110 -0
  62. package/dist/implementations/list-resources-tool.cjs +99 -0
  63. package/dist/implementations/list-resources-tool.d.cts +26 -0
  64. package/dist/implementations/list-resources-tool.d.ts +25 -0
  65. package/dist/implementations/list-resources-tool.d.ts.map +1 -0
  66. package/dist/implementations/list-resources-tool.js +75 -0
  67. package/dist/implementations/sleep-tool.cjs +45 -0
  68. package/dist/implementations/sleep-tool.d.cts +16 -0
  69. package/dist/implementations/sleep-tool.d.ts +15 -0
  70. package/dist/implementations/sleep-tool.d.ts.map +1 -0
  71. package/dist/implementations/sleep-tool.js +21 -0
  72. package/dist/index.cjs +33 -0
  73. package/dist/index.d.cts +3 -0
  74. package/dist/index.d.ts +17 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +7 -0
  77. package/package.json +38 -0
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var delegate_to_url_tool_exports = {};
20
+ __export(delegate_to_url_tool_exports, {
21
+ createDelegateToUrlTool: () => createDelegateToUrlTool
22
+ });
23
+ module.exports = __toCommonJS(delegate_to_url_tool_exports);
24
+ var import_zod = require("zod");
25
+ var import_core = require("@dexto/core");
26
+ const DelegateToUrlInputSchema = import_zod.z.object({
27
+ url: import_zod.z.string().url().describe(
28
+ 'The A2A-compliant agent URL (e.g., "http://localhost:3001" or "https://agent.example.com"). The tool will automatically append the correct JSON-RPC endpoint.'
29
+ ),
30
+ message: import_zod.z.string().min(1).describe(
31
+ "The message or task to delegate to the agent. This will be sent as natural language input."
32
+ ),
33
+ sessionId: import_zod.z.string().optional().describe(
34
+ "Optional session ID for maintaining conversation state across multiple delegations to the same agent"
35
+ ),
36
+ timeout: import_zod.z.number().optional().default(3e4).describe("Request timeout in milliseconds (default: 30000)")
37
+ }).strict();
38
+ function isPlainObject(value) {
39
+ return typeof value === "object" && value !== null && !Array.isArray(value);
40
+ }
41
+ class SimpleA2AClient {
42
+ url;
43
+ timeout;
44
+ constructor(url, timeout = 3e4) {
45
+ this.url = url.replace(/\/$/, "");
46
+ this.timeout = timeout;
47
+ }
48
+ async sendMessage(message, sessionId) {
49
+ const messageId = this.generateId();
50
+ const taskId = sessionId || this.generateId();
51
+ const a2aMessage = {
52
+ role: "user",
53
+ parts: [
54
+ {
55
+ kind: "text",
56
+ text: message
57
+ }
58
+ ],
59
+ messageId,
60
+ taskId,
61
+ contextId: taskId,
62
+ kind: "message"
63
+ };
64
+ const rpcRequest = {
65
+ jsonrpc: "2.0",
66
+ id: this.generateId(),
67
+ method: "message/send",
68
+ params: {
69
+ message: a2aMessage,
70
+ configuration: {
71
+ blocking: true
72
+ }
73
+ }
74
+ };
75
+ const endpoints = [`${this.url}/v1/jsonrpc`, `${this.url}/jsonrpc`];
76
+ let lastError = null;
77
+ for (const endpoint of endpoints) {
78
+ const controller = new AbortController();
79
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
80
+ try {
81
+ const response = await fetch(endpoint, {
82
+ method: "POST",
83
+ headers: {
84
+ "Content-Type": "application/json",
85
+ "User-Agent": "@dexto/core"
86
+ },
87
+ body: JSON.stringify(rpcRequest),
88
+ signal: controller.signal
89
+ });
90
+ if (!response.ok) {
91
+ lastError = new Error(
92
+ `HTTP ${response.status}: ${response.statusText} (tried ${endpoint})`
93
+ );
94
+ continue;
95
+ }
96
+ const data = await response.json();
97
+ if (isPlainObject(data) && "error" in data && data.error) {
98
+ const errorMessage = isPlainObject(data.error) && typeof data.error.message === "string" ? data.error.message : "Unknown error";
99
+ throw new Error(`Agent returned error: ${errorMessage}`);
100
+ }
101
+ if (isPlainObject(data) && "result" in data) {
102
+ return this.extractTaskResponse(data.result);
103
+ }
104
+ return data;
105
+ } catch (error) {
106
+ if (error instanceof Error && error.name === "AbortError") {
107
+ throw new import_core.DextoRuntimeError(
108
+ "DELEGATION_TIMEOUT",
109
+ import_core.ErrorScope.TOOLS,
110
+ import_core.ErrorType.TIMEOUT,
111
+ `Delegation timeout after ${this.timeout}ms`
112
+ );
113
+ }
114
+ lastError = error instanceof Error ? error : new Error(String(error));
115
+ } finally {
116
+ clearTimeout(timeoutId);
117
+ }
118
+ }
119
+ throw new import_core.DextoRuntimeError(
120
+ "DELEGATION_FAILED",
121
+ import_core.ErrorScope.TOOLS,
122
+ import_core.ErrorType.THIRD_PARTY,
123
+ `Failed to connect to agent at ${this.url}. Tried endpoints: ${endpoints.join(", ")}. Last error: ${lastError?.message || "Unknown error"}`
124
+ );
125
+ }
126
+ extractTaskResponse(task) {
127
+ if (isPlainObject(task) && Array.isArray(task.history)) {
128
+ const agentMessages = task.history.filter(
129
+ (message) => isPlainObject(message) && message.role === "agent"
130
+ );
131
+ if (agentMessages.length > 0) {
132
+ const lastMessage = agentMessages[agentMessages.length - 1];
133
+ if (lastMessage && Array.isArray(lastMessage.parts)) {
134
+ const textParts = lastMessage.parts.filter(
135
+ (part) => isPlainObject(part) && part.kind === "text"
136
+ ).map((part) => part.text).filter((text) => typeof text === "string");
137
+ return textParts.join("\n");
138
+ }
139
+ }
140
+ }
141
+ return JSON.stringify(task, null, 2);
142
+ }
143
+ generateId() {
144
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
145
+ }
146
+ }
147
+ function createDelegateToUrlTool() {
148
+ return (0, import_core.defineTool)({
149
+ id: "delegate_to_url",
150
+ displayName: "Delegate",
151
+ description: 'Delegate a task to another A2A-compliant agent at a specific URL. Supports STATEFUL multi-turn conversations via sessionId parameter. USAGE: (1) First delegation: provide url + message. Tool returns a response AND a sessionId. (2) Follow-up: use the SAME sessionId to continue the conversation with that agent. The agent remembers previous context. EXAMPLE: First call {url: "http://agent:3001", message: "Analyze data X"} returns {sessionId: "xyz", response: "..."}. Second call {url: "http://agent:3001", message: "What was the top insight?", sessionId: "xyz"}. The agent will remember the first analysis and can answer specifically.',
152
+ inputSchema: DelegateToUrlInputSchema,
153
+ async execute(input, _context) {
154
+ const { url, message, sessionId, timeout } = input;
155
+ try {
156
+ const client = new SimpleA2AClient(url, timeout);
157
+ const effectiveSessionId = sessionId || `delegation-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
158
+ const response = await client.sendMessage(message, effectiveSessionId);
159
+ return {
160
+ success: true,
161
+ agentUrl: url,
162
+ sessionId: effectiveSessionId,
163
+ response,
164
+ _hint: sessionId ? "Continued existing conversation" : "Started new conversation - use this sessionId for follow-ups"
165
+ };
166
+ } catch (error) {
167
+ if (error instanceof import_core.DextoRuntimeError) {
168
+ throw error;
169
+ }
170
+ throw new import_core.DextoRuntimeError(
171
+ "DELEGATION_ERROR",
172
+ import_core.ErrorScope.TOOLS,
173
+ import_core.ErrorType.SYSTEM,
174
+ `Delegation failed: ${error instanceof Error ? error.message : String(error)}`
175
+ );
176
+ }
177
+ }
178
+ });
179
+ }
180
+ // Annotate the CommonJS export names for ESM import in node:
181
+ 0 && (module.exports = {
182
+ createDelegateToUrlTool
183
+ });
@@ -0,0 +1,27 @@
1
+ import { z } from 'zod';
2
+ import { Tool } from '@dexto/core';
3
+
4
+ declare const DelegateToUrlInputSchema: z.ZodObject<{
5
+ url: z.ZodString;
6
+ message: z.ZodString;
7
+ sessionId: z.ZodOptional<z.ZodString>;
8
+ timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
9
+ }, "strict", z.ZodTypeAny, {
10
+ timeout: number;
11
+ message: string;
12
+ url: string;
13
+ sessionId?: string | undefined;
14
+ }, {
15
+ message: string;
16
+ url: string;
17
+ timeout?: number | undefined;
18
+ sessionId?: string | undefined;
19
+ }>;
20
+ /**
21
+ * Create the `delegate_to_url` tool.
22
+ *
23
+ * Delegates a message/task to another A2A-compliant agent URL via JSON-RPC and returns its response.
24
+ */
25
+ declare function createDelegateToUrlTool(): Tool<typeof DelegateToUrlInputSchema>;
26
+
27
+ export { createDelegateToUrlTool };
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod';
2
+ import type { Tool } from '@dexto/core';
3
+ declare const DelegateToUrlInputSchema: z.ZodObject<{
4
+ url: z.ZodString;
5
+ message: z.ZodString;
6
+ sessionId: z.ZodOptional<z.ZodString>;
7
+ timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
8
+ }, "strict", z.ZodTypeAny, {
9
+ message: string;
10
+ url: string;
11
+ timeout: number;
12
+ sessionId?: string | undefined;
13
+ }, {
14
+ message: string;
15
+ url: string;
16
+ sessionId?: string | undefined;
17
+ timeout?: number | undefined;
18
+ }>;
19
+ /**
20
+ * Create the `delegate_to_url` tool.
21
+ *
22
+ * Delegates a message/task to another A2A-compliant agent URL via JSON-RPC and returns its response.
23
+ */
24
+ export declare function createDelegateToUrlTool(): Tool<typeof DelegateToUrlInputSchema>;
25
+ export {};
26
+ //# sourceMappingURL=delegate-to-url-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate-to-url-tool.d.ts","sourceRoot":"","sources":["../../src/implementations/delegate-to-url-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,aAAa,CAAC;AAG9D,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;;EA0BjB,CAAC;AAsJd;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAAC,OAAO,wBAAwB,CAAC,CAyC/E"}
@@ -0,0 +1,159 @@
1
+ import { z } from "zod";
2
+ import { DextoRuntimeError, ErrorScope, ErrorType, defineTool } from "@dexto/core";
3
+ const DelegateToUrlInputSchema = z.object({
4
+ url: z.string().url().describe(
5
+ 'The A2A-compliant agent URL (e.g., "http://localhost:3001" or "https://agent.example.com"). The tool will automatically append the correct JSON-RPC endpoint.'
6
+ ),
7
+ message: z.string().min(1).describe(
8
+ "The message or task to delegate to the agent. This will be sent as natural language input."
9
+ ),
10
+ sessionId: z.string().optional().describe(
11
+ "Optional session ID for maintaining conversation state across multiple delegations to the same agent"
12
+ ),
13
+ timeout: z.number().optional().default(3e4).describe("Request timeout in milliseconds (default: 30000)")
14
+ }).strict();
15
+ function isPlainObject(value) {
16
+ return typeof value === "object" && value !== null && !Array.isArray(value);
17
+ }
18
+ class SimpleA2AClient {
19
+ url;
20
+ timeout;
21
+ constructor(url, timeout = 3e4) {
22
+ this.url = url.replace(/\/$/, "");
23
+ this.timeout = timeout;
24
+ }
25
+ async sendMessage(message, sessionId) {
26
+ const messageId = this.generateId();
27
+ const taskId = sessionId || this.generateId();
28
+ const a2aMessage = {
29
+ role: "user",
30
+ parts: [
31
+ {
32
+ kind: "text",
33
+ text: message
34
+ }
35
+ ],
36
+ messageId,
37
+ taskId,
38
+ contextId: taskId,
39
+ kind: "message"
40
+ };
41
+ const rpcRequest = {
42
+ jsonrpc: "2.0",
43
+ id: this.generateId(),
44
+ method: "message/send",
45
+ params: {
46
+ message: a2aMessage,
47
+ configuration: {
48
+ blocking: true
49
+ }
50
+ }
51
+ };
52
+ const endpoints = [`${this.url}/v1/jsonrpc`, `${this.url}/jsonrpc`];
53
+ let lastError = null;
54
+ for (const endpoint of endpoints) {
55
+ const controller = new AbortController();
56
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
57
+ try {
58
+ const response = await fetch(endpoint, {
59
+ method: "POST",
60
+ headers: {
61
+ "Content-Type": "application/json",
62
+ "User-Agent": "@dexto/core"
63
+ },
64
+ body: JSON.stringify(rpcRequest),
65
+ signal: controller.signal
66
+ });
67
+ if (!response.ok) {
68
+ lastError = new Error(
69
+ `HTTP ${response.status}: ${response.statusText} (tried ${endpoint})`
70
+ );
71
+ continue;
72
+ }
73
+ const data = await response.json();
74
+ if (isPlainObject(data) && "error" in data && data.error) {
75
+ const errorMessage = isPlainObject(data.error) && typeof data.error.message === "string" ? data.error.message : "Unknown error";
76
+ throw new Error(`Agent returned error: ${errorMessage}`);
77
+ }
78
+ if (isPlainObject(data) && "result" in data) {
79
+ return this.extractTaskResponse(data.result);
80
+ }
81
+ return data;
82
+ } catch (error) {
83
+ if (error instanceof Error && error.name === "AbortError") {
84
+ throw new DextoRuntimeError(
85
+ "DELEGATION_TIMEOUT",
86
+ ErrorScope.TOOLS,
87
+ ErrorType.TIMEOUT,
88
+ `Delegation timeout after ${this.timeout}ms`
89
+ );
90
+ }
91
+ lastError = error instanceof Error ? error : new Error(String(error));
92
+ } finally {
93
+ clearTimeout(timeoutId);
94
+ }
95
+ }
96
+ throw new DextoRuntimeError(
97
+ "DELEGATION_FAILED",
98
+ ErrorScope.TOOLS,
99
+ ErrorType.THIRD_PARTY,
100
+ `Failed to connect to agent at ${this.url}. Tried endpoints: ${endpoints.join(", ")}. Last error: ${lastError?.message || "Unknown error"}`
101
+ );
102
+ }
103
+ extractTaskResponse(task) {
104
+ if (isPlainObject(task) && Array.isArray(task.history)) {
105
+ const agentMessages = task.history.filter(
106
+ (message) => isPlainObject(message) && message.role === "agent"
107
+ );
108
+ if (agentMessages.length > 0) {
109
+ const lastMessage = agentMessages[agentMessages.length - 1];
110
+ if (lastMessage && Array.isArray(lastMessage.parts)) {
111
+ const textParts = lastMessage.parts.filter(
112
+ (part) => isPlainObject(part) && part.kind === "text"
113
+ ).map((part) => part.text).filter((text) => typeof text === "string");
114
+ return textParts.join("\n");
115
+ }
116
+ }
117
+ }
118
+ return JSON.stringify(task, null, 2);
119
+ }
120
+ generateId() {
121
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
122
+ }
123
+ }
124
+ function createDelegateToUrlTool() {
125
+ return defineTool({
126
+ id: "delegate_to_url",
127
+ displayName: "Delegate",
128
+ description: 'Delegate a task to another A2A-compliant agent at a specific URL. Supports STATEFUL multi-turn conversations via sessionId parameter. USAGE: (1) First delegation: provide url + message. Tool returns a response AND a sessionId. (2) Follow-up: use the SAME sessionId to continue the conversation with that agent. The agent remembers previous context. EXAMPLE: First call {url: "http://agent:3001", message: "Analyze data X"} returns {sessionId: "xyz", response: "..."}. Second call {url: "http://agent:3001", message: "What was the top insight?", sessionId: "xyz"}. The agent will remember the first analysis and can answer specifically.',
129
+ inputSchema: DelegateToUrlInputSchema,
130
+ async execute(input, _context) {
131
+ const { url, message, sessionId, timeout } = input;
132
+ try {
133
+ const client = new SimpleA2AClient(url, timeout);
134
+ const effectiveSessionId = sessionId || `delegation-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
135
+ const response = await client.sendMessage(message, effectiveSessionId);
136
+ return {
137
+ success: true,
138
+ agentUrl: url,
139
+ sessionId: effectiveSessionId,
140
+ response,
141
+ _hint: sessionId ? "Continued existing conversation" : "Started new conversation - use this sessionId for follow-ups"
142
+ };
143
+ } catch (error) {
144
+ if (error instanceof DextoRuntimeError) {
145
+ throw error;
146
+ }
147
+ throw new DextoRuntimeError(
148
+ "DELEGATION_ERROR",
149
+ ErrorScope.TOOLS,
150
+ ErrorType.SYSTEM,
151
+ `Delegation failed: ${error instanceof Error ? error.message : String(error)}`
152
+ );
153
+ }
154
+ }
155
+ });
156
+ }
157
+ export {
158
+ createDelegateToUrlTool
159
+ };
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var import_vitest = require("vitest");
3
+ var import_delegate_to_url_tool = require("./delegate-to-url-tool.js");
4
+ var import_core = require("@dexto/core");
5
+ function createMockLogger() {
6
+ const logger = {
7
+ debug: import_vitest.vi.fn(),
8
+ silly: import_vitest.vi.fn(),
9
+ info: import_vitest.vi.fn(),
10
+ warn: import_vitest.vi.fn(),
11
+ error: import_vitest.vi.fn(),
12
+ trackException: import_vitest.vi.fn(),
13
+ createChild: import_vitest.vi.fn(() => logger),
14
+ setLevel: import_vitest.vi.fn(),
15
+ getLevel: import_vitest.vi.fn(() => "debug"),
16
+ getLogFilePath: import_vitest.vi.fn(() => null),
17
+ destroy: import_vitest.vi.fn(async () => void 0)
18
+ };
19
+ return logger;
20
+ }
21
+ function createToolContext(logger) {
22
+ return { logger };
23
+ }
24
+ (0, import_vitest.describe)("delegate_to_url tool", () => {
25
+ (0, import_vitest.afterEach)(() => {
26
+ import_vitest.vi.unstubAllGlobals();
27
+ });
28
+ (0, import_vitest.it)("throws DELEGATION_FAILED when it cannot reach the remote agent", async () => {
29
+ const logger = createMockLogger();
30
+ const context = createToolContext(logger);
31
+ const fetchMock = import_vitest.vi.fn(async () => {
32
+ throw new Error("boom");
33
+ });
34
+ import_vitest.vi.stubGlobal("fetch", fetchMock);
35
+ const tool = (0, import_delegate_to_url_tool.createDelegateToUrlTool)();
36
+ const input = tool.inputSchema.parse({
37
+ url: "http://example.com",
38
+ message: "hi",
39
+ timeout: 1
40
+ });
41
+ await (0, import_vitest.expect)(tool.execute(input, context)).rejects.toMatchObject({
42
+ name: "DextoRuntimeError",
43
+ code: "DELEGATION_FAILED",
44
+ scope: import_core.ErrorScope.TOOLS,
45
+ type: import_core.ErrorType.THIRD_PARTY
46
+ });
47
+ });
48
+ (0, import_vitest.it)("throws DELEGATION_TIMEOUT when the request times out", async () => {
49
+ const logger = createMockLogger();
50
+ const context = createToolContext(logger);
51
+ const abortError = new Error("aborted");
52
+ abortError.name = "AbortError";
53
+ const fetchMock = import_vitest.vi.fn(async () => {
54
+ throw abortError;
55
+ });
56
+ import_vitest.vi.stubGlobal("fetch", fetchMock);
57
+ const tool = (0, import_delegate_to_url_tool.createDelegateToUrlTool)();
58
+ const input = tool.inputSchema.parse({
59
+ url: "http://example.com",
60
+ message: "hi",
61
+ timeout: 1
62
+ });
63
+ try {
64
+ await tool.execute(input, context);
65
+ import_vitest.expect.fail("Expected tool.execute() to throw");
66
+ } catch (error) {
67
+ (0, import_vitest.expect)(error).toBeInstanceOf(import_core.DextoRuntimeError);
68
+ (0, import_vitest.expect)(error).toMatchObject({
69
+ code: "DELEGATION_TIMEOUT",
70
+ scope: import_core.ErrorScope.TOOLS,
71
+ type: import_core.ErrorType.TIMEOUT
72
+ });
73
+ }
74
+ });
75
+ });
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=delegate-to-url-tool.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate-to-url-tool.test.d.ts","sourceRoot":"","sources":["../../src/implementations/delegate-to-url-tool.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,74 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { createDelegateToUrlTool } from "./delegate-to-url-tool.js";
3
+ import { DextoRuntimeError, ErrorScope, ErrorType } from "@dexto/core";
4
+ function createMockLogger() {
5
+ const logger = {
6
+ debug: vi.fn(),
7
+ silly: vi.fn(),
8
+ info: vi.fn(),
9
+ warn: vi.fn(),
10
+ error: vi.fn(),
11
+ trackException: vi.fn(),
12
+ createChild: vi.fn(() => logger),
13
+ setLevel: vi.fn(),
14
+ getLevel: vi.fn(() => "debug"),
15
+ getLogFilePath: vi.fn(() => null),
16
+ destroy: vi.fn(async () => void 0)
17
+ };
18
+ return logger;
19
+ }
20
+ function createToolContext(logger) {
21
+ return { logger };
22
+ }
23
+ describe("delegate_to_url tool", () => {
24
+ afterEach(() => {
25
+ vi.unstubAllGlobals();
26
+ });
27
+ it("throws DELEGATION_FAILED when it cannot reach the remote agent", async () => {
28
+ const logger = createMockLogger();
29
+ const context = createToolContext(logger);
30
+ const fetchMock = vi.fn(async () => {
31
+ throw new Error("boom");
32
+ });
33
+ vi.stubGlobal("fetch", fetchMock);
34
+ const tool = createDelegateToUrlTool();
35
+ const input = tool.inputSchema.parse({
36
+ url: "http://example.com",
37
+ message: "hi",
38
+ timeout: 1
39
+ });
40
+ await expect(tool.execute(input, context)).rejects.toMatchObject({
41
+ name: "DextoRuntimeError",
42
+ code: "DELEGATION_FAILED",
43
+ scope: ErrorScope.TOOLS,
44
+ type: ErrorType.THIRD_PARTY
45
+ });
46
+ });
47
+ it("throws DELEGATION_TIMEOUT when the request times out", async () => {
48
+ const logger = createMockLogger();
49
+ const context = createToolContext(logger);
50
+ const abortError = new Error("aborted");
51
+ abortError.name = "AbortError";
52
+ const fetchMock = vi.fn(async () => {
53
+ throw abortError;
54
+ });
55
+ vi.stubGlobal("fetch", fetchMock);
56
+ const tool = createDelegateToUrlTool();
57
+ const input = tool.inputSchema.parse({
58
+ url: "http://example.com",
59
+ message: "hi",
60
+ timeout: 1
61
+ });
62
+ try {
63
+ await tool.execute(input, context);
64
+ expect.fail("Expected tool.execute() to throw");
65
+ } catch (error) {
66
+ expect(error).toBeInstanceOf(DextoRuntimeError);
67
+ expect(error).toMatchObject({
68
+ code: "DELEGATION_TIMEOUT",
69
+ scope: ErrorScope.TOOLS,
70
+ type: ErrorType.TIMEOUT
71
+ });
72
+ }
73
+ });
74
+ });
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var exa_code_search_tool_exports = {};
20
+ __export(exa_code_search_tool_exports, {
21
+ createCodeSearchTool: () => createCodeSearchTool
22
+ });
23
+ module.exports = __toCommonJS(exa_code_search_tool_exports);
24
+ var import_zod = require("zod");
25
+ var import_core = require("@dexto/core");
26
+ var import_exa_mcp = require("./exa-mcp.js");
27
+ const CodeSearchInputSchema = import_zod.z.object({
28
+ query: import_zod.z.string().min(1).describe(
29
+ "Search query for code examples and documentation (e.g., 'React useState examples', 'Express middleware', 'Python pandas dataframe filtering')"
30
+ ),
31
+ tokensNum: import_zod.z.number().int().min(1e3).max(5e4).optional().default(5e3).describe("Approximate token budget to return (1000\u201350000, default: 5000)")
32
+ }).strict();
33
+ function createCodeSearchTool() {
34
+ return (0, import_core.defineTool)({
35
+ id: "code_search",
36
+ displayName: "Code Search",
37
+ description: "Search for code examples and documentation across sources like official docs, GitHub, and Stack Overflow. Returns formatted text context.",
38
+ inputSchema: CodeSearchInputSchema,
39
+ async execute(input, context) {
40
+ const { query, tokensNum } = input;
41
+ return await (0, import_exa_mcp.callExaTool)({
42
+ logger: context.logger,
43
+ toolId: "code_search",
44
+ toolName: "get_code_context_exa",
45
+ args: {
46
+ query,
47
+ tokensNum
48
+ },
49
+ timeoutMs: 3e4
50
+ });
51
+ }
52
+ });
53
+ }
54
+ // Annotate the CommonJS export names for ESM import in node:
55
+ 0 && (module.exports = {
56
+ createCodeSearchTool
57
+ });
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ import { Tool } from '@dexto/core';
3
+
4
+ declare const CodeSearchInputSchema: z.ZodObject<{
5
+ query: z.ZodString;
6
+ tokensNum: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
7
+ }, "strict", z.ZodTypeAny, {
8
+ query: string;
9
+ tokensNum: number;
10
+ }, {
11
+ query: string;
12
+ tokensNum?: number | undefined;
13
+ }>;
14
+ /**
15
+ * Create the `code_search` tool.
16
+ *
17
+ * Finds relevant code snippets and documentation by calling Exa's MCP endpoint via the MCP SDK.
18
+ */
19
+ declare function createCodeSearchTool(): Tool<typeof CodeSearchInputSchema>;
20
+
21
+ export { createCodeSearchTool };
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import type { Tool } from '@dexto/core';
3
+ declare const CodeSearchInputSchema: z.ZodObject<{
4
+ query: z.ZodString;
5
+ tokensNum: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
6
+ }, "strict", z.ZodTypeAny, {
7
+ query: string;
8
+ tokensNum: number;
9
+ }, {
10
+ query: string;
11
+ tokensNum?: number | undefined;
12
+ }>;
13
+ /**
14
+ * Create the `code_search` tool.
15
+ *
16
+ * Finds relevant code snippets and documentation by calling Exa's MCP endpoint via the MCP SDK.
17
+ */
18
+ export declare function createCodeSearchTool(): Tool<typeof CodeSearchInputSchema>;
19
+ export {};
20
+ //# sourceMappingURL=exa-code-search-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exa-code-search-tool.d.ts","sourceRoot":"","sources":["../../src/implementations/exa-code-search-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,aAAa,CAAC;AAG9D,QAAA,MAAM,qBAAqB;;;;;;;;;EAiBd,CAAC;AACd;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAAC,OAAO,qBAAqB,CAAC,CAsBzE"}