@dogpile/sdk 0.2.2 → 0.3.1
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/CHANGELOG.md +15 -0
- package/dist/browser/index.js +1044 -507
- package/dist/browser/index.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime/broadcast.d.ts +1 -0
- package/dist/runtime/broadcast.d.ts.map +1 -1
- package/dist/runtime/broadcast.js +28 -19
- package/dist/runtime/broadcast.js.map +1 -1
- package/dist/runtime/coordinator.d.ts +1 -0
- package/dist/runtime/coordinator.d.ts.map +1 -1
- package/dist/runtime/coordinator.js +46 -21
- package/dist/runtime/coordinator.js.map +1 -1
- package/dist/runtime/engine.d.ts.map +1 -1
- package/dist/runtime/engine.js +5 -0
- package/dist/runtime/engine.js.map +1 -1
- package/dist/runtime/ids.d.ts +19 -0
- package/dist/runtime/ids.d.ts.map +1 -0
- package/dist/runtime/ids.js +36 -0
- package/dist/runtime/ids.js.map +1 -0
- package/dist/runtime/logger.d.ts +61 -0
- package/dist/runtime/logger.d.ts.map +1 -0
- package/dist/runtime/logger.js +114 -0
- package/dist/runtime/logger.js.map +1 -0
- package/dist/runtime/retry.d.ts +99 -0
- package/dist/runtime/retry.d.ts.map +1 -0
- package/dist/runtime/retry.js +181 -0
- package/dist/runtime/retry.js.map +1 -0
- package/dist/runtime/sequential.d.ts +1 -0
- package/dist/runtime/sequential.d.ts.map +1 -1
- package/dist/runtime/sequential.js +25 -16
- package/dist/runtime/sequential.js.map +1 -1
- package/dist/runtime/shared.d.ts +1 -0
- package/dist/runtime/shared.d.ts.map +1 -1
- package/dist/runtime/shared.js +25 -19
- package/dist/runtime/shared.js.map +1 -1
- package/dist/runtime/termination.d.ts +6 -1
- package/dist/runtime/termination.d.ts.map +1 -1
- package/dist/runtime/termination.js +75 -0
- package/dist/runtime/termination.js.map +1 -1
- package/dist/runtime/tools/built-in.d.ts +99 -0
- package/dist/runtime/tools/built-in.d.ts.map +1 -0
- package/dist/runtime/tools/built-in.js +577 -0
- package/dist/runtime/tools/built-in.js.map +1 -0
- package/dist/runtime/tools/vercel-ai.d.ts +67 -0
- package/dist/runtime/tools/vercel-ai.d.ts.map +1 -0
- package/dist/runtime/tools/vercel-ai.js +148 -0
- package/dist/runtime/tools/vercel-ai.js.map +1 -0
- package/dist/runtime/tools.d.ts +5 -268
- package/dist/runtime/tools.d.ts.map +1 -1
- package/dist/runtime/tools.js +7 -770
- package/dist/runtime/tools.js.map +1 -1
- package/dist/runtime/validation.d.ts.map +1 -1
- package/dist/runtime/validation.js +22 -0
- package/dist/runtime/validation.js.map +1 -1
- package/dist/runtime/wrap-up.d.ts +26 -0
- package/dist/runtime/wrap-up.d.ts.map +1 -0
- package/dist/runtime/wrap-up.js +178 -0
- package/dist/runtime/wrap-up.js.map +1 -0
- package/dist/types/benchmark.d.ts +276 -0
- package/dist/types/benchmark.d.ts.map +1 -0
- package/dist/types/benchmark.js +2 -0
- package/dist/types/benchmark.js.map +1 -0
- package/dist/types/events.d.ts +495 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +2 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/replay.d.ts +169 -0
- package/dist/types/replay.d.ts.map +1 -0
- package/dist/types/replay.js +2 -0
- package/dist/types/replay.js.map +1 -0
- package/dist/types.d.ts +74 -935
- package/dist/types.d.ts.map +1 -1
- package/package.json +28 -1
- package/src/index.ts +7 -1
- package/src/runtime/broadcast.ts +50 -35
- package/src/runtime/coordinator.ts +84 -43
- package/src/runtime/engine.ts +6 -0
- package/src/runtime/ids.ts +41 -0
- package/src/runtime/logger.ts +152 -0
- package/src/runtime/retry.ts +270 -0
- package/src/runtime/sequential.ts +46 -31
- package/src/runtime/shared.ts +46 -35
- package/src/runtime/termination.ts +100 -0
- package/src/runtime/tools/built-in.ts +875 -0
- package/src/runtime/tools/vercel-ai.ts +269 -0
- package/src/runtime/tools.ts +60 -1255
- package/src/runtime/validation.ts +25 -0
- package/src/runtime/wrap-up.ts +257 -0
- package/src/types/benchmark.ts +300 -0
- package/src/types/events.ts +544 -0
- package/src/types/replay.ts +201 -0
- package/src/types.ts +174 -994
package/src/runtime/tools.ts
CHANGED
|
@@ -1,284 +1,74 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
JsonObject,
|
|
3
3
|
JsonValue,
|
|
4
|
+
ModelResponse,
|
|
4
5
|
RuntimeTool,
|
|
5
|
-
RuntimeToolAdapterContract,
|
|
6
|
-
RuntimeToolAdapterError,
|
|
7
6
|
RuntimeToolExecutionContext,
|
|
8
7
|
RuntimeToolExecutionRequest,
|
|
9
8
|
RuntimeToolExecutor,
|
|
10
9
|
RuntimeToolIdentity,
|
|
11
|
-
RuntimeToolInputSchema,
|
|
12
10
|
RuntimeToolPermission,
|
|
13
11
|
RuntimeToolResult,
|
|
14
|
-
TranscriptToolCall,
|
|
15
12
|
RuntimeToolTraceContext,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
RunEvent,
|
|
19
|
-
ModelMessage,
|
|
20
|
-
ModelResponse
|
|
13
|
+
TranscriptToolCall,
|
|
14
|
+
RunEvent
|
|
21
15
|
} from "../types.js";
|
|
22
16
|
import { validateRuntimeToolRegistrations } from "./validation.js";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
export
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
readonly init?: RequestInit;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Build a search backend request from normalized web search input.
|
|
83
|
-
*/
|
|
84
|
-
export type WebSearchFetchRequestBuilder = (
|
|
85
|
-
input: Readonly<WebSearchToolInput>,
|
|
86
|
-
context: RuntimeToolExecutionContext
|
|
87
|
-
) => WebSearchFetchRequest;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Parse a search backend response into Dogpile's stable web search output.
|
|
91
|
-
*/
|
|
92
|
-
export type WebSearchFetchResponseParser = (
|
|
93
|
-
response: Response,
|
|
94
|
-
input: Readonly<WebSearchToolInput>,
|
|
95
|
-
context: RuntimeToolExecutionContext
|
|
96
|
-
) => WebSearchToolOutput | Promise<WebSearchToolOutput>;
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Options for the built-in fetch-based web search adapter.
|
|
100
|
-
*/
|
|
101
|
-
export interface WebSearchToolAdapterOptions {
|
|
102
|
-
readonly endpoint: string | URL;
|
|
103
|
-
readonly fetch?: WebSearchFetch;
|
|
104
|
-
readonly headers?: HeadersInit;
|
|
105
|
-
readonly defaultMaxResults?: number;
|
|
106
|
-
readonly identity?: BuiltInDogpileToolIdentityOptions;
|
|
107
|
-
readonly permissions?: readonly RuntimeToolPermission[];
|
|
108
|
-
readonly buildRequest?: WebSearchFetchRequestBuilder;
|
|
109
|
-
readonly parseResponse?: WebSearchFetchResponseParser;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Options for the built-in code execution adapter.
|
|
114
|
-
*/
|
|
115
|
-
export interface CodeExecToolAdapterOptions {
|
|
116
|
-
readonly execute: CodeExecSandboxExecutor;
|
|
117
|
-
readonly defaultTimeoutMs?: number;
|
|
118
|
-
readonly maxTimeoutMs?: number;
|
|
119
|
-
readonly languages?: readonly CodeExecToolLanguage[];
|
|
120
|
-
readonly allowNetwork?: boolean;
|
|
121
|
-
readonly identity?: BuiltInDogpileToolIdentityOptions;
|
|
122
|
-
readonly permissions?: readonly RuntimeToolPermission[];
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Input accepted by the built-in code execution tool contract.
|
|
127
|
-
*
|
|
128
|
-
* @remarks
|
|
129
|
-
* Dogpile core does not provide a sandbox implementation. Callers supply the
|
|
130
|
-
* executor while Dogpile normalizes the public tool identity and schema.
|
|
131
|
-
*/
|
|
132
|
-
export interface CodeExecToolInput extends JsonObject {
|
|
133
|
-
readonly language: "javascript" | "typescript" | "python" | "bash" | "shell";
|
|
134
|
-
readonly code: string;
|
|
135
|
-
readonly timeoutMs?: number;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Output returned by the built-in code execution tool contract.
|
|
140
|
-
*/
|
|
141
|
-
export interface CodeExecToolOutput extends JsonObject {
|
|
142
|
-
readonly stdout: string;
|
|
143
|
-
readonly stderr: string;
|
|
144
|
-
readonly exitCode: number;
|
|
145
|
-
readonly metadata?: JsonObject;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Language identifiers accepted by Dogpile's built-in code execution contract.
|
|
150
|
-
*/
|
|
151
|
-
export type CodeExecToolLanguage = CodeExecToolInput["language"];
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Executor signature for the built-in web search contract.
|
|
155
|
-
*/
|
|
156
|
-
export type WebSearchToolExecutor = (
|
|
157
|
-
input: Readonly<WebSearchToolInput>,
|
|
158
|
-
context: RuntimeToolExecutionContext
|
|
159
|
-
) => RuntimeToolResult<WebSearchToolOutput> | Promise<RuntimeToolResult<WebSearchToolOutput>>;
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Executor signature for the built-in code execution contract.
|
|
163
|
-
*/
|
|
164
|
-
export type CodeExecToolExecutor = (
|
|
165
|
-
input: Readonly<CodeExecToolInput>,
|
|
166
|
-
context: RuntimeToolExecutionContext
|
|
167
|
-
) => RuntimeToolResult<CodeExecToolOutput> | Promise<RuntimeToolResult<CodeExecToolOutput>>;
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Caller-owned sandbox implementation used by Dogpile's built-in code execution adapter.
|
|
171
|
-
*/
|
|
172
|
-
export type CodeExecSandboxExecutor = (
|
|
173
|
-
input: Readonly<CodeExecToolInput>,
|
|
174
|
-
context: RuntimeToolExecutionContext
|
|
175
|
-
) => CodeExecToolOutput | Promise<CodeExecToolOutput>;
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Optional identity fields callers may layer onto built-in Dogpile tools.
|
|
179
|
-
*/
|
|
180
|
-
export interface BuiltInDogpileToolIdentityOptions {
|
|
181
|
-
readonly namespace?: string;
|
|
182
|
-
readonly version?: string;
|
|
183
|
-
readonly description?: string;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Definition used to normalize Dogpile's built-in web search tool.
|
|
188
|
-
*/
|
|
189
|
-
export interface WebSearchDogpileToolDefinition {
|
|
190
|
-
readonly name: "webSearch";
|
|
191
|
-
readonly execute: WebSearchToolExecutor;
|
|
192
|
-
readonly identity?: BuiltInDogpileToolIdentityOptions;
|
|
193
|
-
readonly inputSchema?: RuntimeToolInputSchema;
|
|
194
|
-
readonly permissions?: readonly RuntimeToolPermission[];
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Definition used to normalize Dogpile's built-in code execution tool.
|
|
199
|
-
*/
|
|
200
|
-
export interface CodeExecDogpileToolDefinition {
|
|
201
|
-
readonly name: "codeExec";
|
|
202
|
-
readonly execute: CodeExecToolExecutor;
|
|
203
|
-
readonly identity?: BuiltInDogpileToolIdentityOptions;
|
|
204
|
-
readonly inputSchema?: RuntimeToolInputSchema;
|
|
205
|
-
readonly permissions?: readonly RuntimeToolPermission[];
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Built-in Dogpile tool definitions accepted by the normalization helper.
|
|
210
|
-
*/
|
|
211
|
-
export type BuiltInDogpileToolDefinition = WebSearchDogpileToolDefinition | CodeExecDogpileToolDefinition;
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Caller-supplied built-in tool executors keyed by Dogpile's stable built-in names.
|
|
215
|
-
*/
|
|
216
|
-
export interface BuiltInDogpileToolExecutors {
|
|
217
|
-
readonly webSearch?: WebSearchToolExecutor | WebSearchDogpileToolDefinition;
|
|
218
|
-
readonly codeExec?: CodeExecToolExecutor | CodeExecDogpileToolDefinition;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export type BuiltInDogpileRuntimeTool =
|
|
222
|
-
| RuntimeToolAdapterContract<WebSearchToolInput, WebSearchToolOutput>
|
|
223
|
-
| RuntimeToolAdapterContract<CodeExecToolInput, CodeExecToolOutput>;
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Vercel AI SDK tool shape accepted by Dogpile's normalization adapter.
|
|
227
|
-
*/
|
|
228
|
-
export interface VercelAITool<Input extends JsonObject = JsonObject, Output extends JsonValue = JsonValue> {
|
|
229
|
-
readonly description?: string;
|
|
230
|
-
readonly inputSchema: VercelAICompatibleSchema<Input>;
|
|
231
|
-
readonly execute?: VercelAIToolExecuteFunction<Input, Output>;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Optional identity fields callers may layer onto normalized Vercel AI tools.
|
|
236
|
-
*/
|
|
237
|
-
export interface VercelAIToolIdentityOptions {
|
|
238
|
-
readonly id?: string;
|
|
239
|
-
readonly namespace?: string;
|
|
240
|
-
readonly version?: string;
|
|
241
|
-
readonly description?: string;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Definition used to normalize one Vercel AI SDK tool into Dogpile's runtime tool interface.
|
|
246
|
-
*/
|
|
247
|
-
export interface VercelAIToolDefinition<
|
|
248
|
-
Name extends string = string,
|
|
249
|
-
Input extends JsonObject = JsonObject,
|
|
250
|
-
Output extends JsonValue = JsonValue
|
|
251
|
-
> {
|
|
252
|
-
readonly name: Name;
|
|
253
|
-
readonly tool: VercelAITool<Input, Output>;
|
|
254
|
-
readonly identity?: VercelAIToolIdentityOptions;
|
|
255
|
-
readonly inputSchema?: RuntimeToolInputSchema;
|
|
256
|
-
readonly messages?: readonly ModelMessage[];
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Caller-supplied Vercel AI SDK tool set keyed by model-visible tool name.
|
|
261
|
-
*/
|
|
262
|
-
export interface VercelAIToolSetEntry {
|
|
263
|
-
readonly description?: string;
|
|
264
|
-
readonly inputSchema: VercelAICompatibleSchema<unknown>;
|
|
265
|
-
readonly execute?: VercelAIToolExecuteFunction<never, JsonValue>;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Caller-supplied Vercel AI SDK tool set keyed by model-visible tool name.
|
|
270
|
-
*/
|
|
271
|
-
export type VercelAIToolSet = Readonly<Record<string, VercelAIToolSetEntry>>;
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Options shared while normalizing a Vercel AI SDK tool set.
|
|
275
|
-
*/
|
|
276
|
-
export interface VercelAIToolSetNormalizationOptions {
|
|
277
|
-
readonly namespace?: string;
|
|
278
|
-
readonly version?: string;
|
|
279
|
-
readonly messages?: readonly ModelMessage[];
|
|
280
|
-
readonly identity?: Readonly<Record<string, VercelAIToolIdentityOptions>>;
|
|
281
|
-
}
|
|
17
|
+
import { normalizeRuntimeToolAdapterError } from "./tools/built-in.js";
|
|
18
|
+
|
|
19
|
+
// Re-export the public surface from the split modules so the
|
|
20
|
+
// `@dogpile/sdk/runtime/tools` subpath stays stable.
|
|
21
|
+
export {
|
|
22
|
+
builtInDogpileToolIdentity,
|
|
23
|
+
builtInDogpileToolInputSchema,
|
|
24
|
+
builtInDogpileToolPermissions,
|
|
25
|
+
createCodeExecToolAdapter,
|
|
26
|
+
createWebSearchToolAdapter,
|
|
27
|
+
normalizeBuiltInDogpileTool,
|
|
28
|
+
normalizeBuiltInDogpileTools,
|
|
29
|
+
normalizeRuntimeToolAdapterError,
|
|
30
|
+
validateBuiltInDogpileToolInput
|
|
31
|
+
} from "./tools/built-in.js";
|
|
32
|
+
export type {
|
|
33
|
+
BuiltInDogpileRuntimeTool,
|
|
34
|
+
BuiltInDogpileToolDefinition,
|
|
35
|
+
BuiltInDogpileToolExecutors,
|
|
36
|
+
BuiltInDogpileToolIdentityOptions,
|
|
37
|
+
CodeExecDogpileToolDefinition,
|
|
38
|
+
CodeExecSandboxExecutor,
|
|
39
|
+
CodeExecToolAdapterOptions,
|
|
40
|
+
CodeExecToolExecutor,
|
|
41
|
+
CodeExecToolInput,
|
|
42
|
+
CodeExecToolLanguage,
|
|
43
|
+
CodeExecToolOutput,
|
|
44
|
+
DogpileBuiltInToolName,
|
|
45
|
+
WebSearchDogpileToolDefinition,
|
|
46
|
+
WebSearchFetch,
|
|
47
|
+
WebSearchFetchRequest,
|
|
48
|
+
WebSearchFetchRequestBuilder,
|
|
49
|
+
WebSearchFetchResponseParser,
|
|
50
|
+
WebSearchToolAdapterOptions,
|
|
51
|
+
WebSearchToolExecutor,
|
|
52
|
+
WebSearchToolInput,
|
|
53
|
+
WebSearchToolOutput,
|
|
54
|
+
WebSearchToolResult
|
|
55
|
+
} from "./tools/built-in.js";
|
|
56
|
+
|
|
57
|
+
export { normalizeVercelAITool, normalizeVercelAITools } from "./tools/vercel-ai.js";
|
|
58
|
+
export type {
|
|
59
|
+
VercelAITool,
|
|
60
|
+
VercelAIToolDefinition,
|
|
61
|
+
VercelAIToolIdentityOptions,
|
|
62
|
+
VercelAIToolSet,
|
|
63
|
+
VercelAIToolSetEntry,
|
|
64
|
+
VercelAIToolSetNormalizationOptions
|
|
65
|
+
} from "./tools/vercel-ai.js";
|
|
66
|
+
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// Runtime tool executor — the protocol-agnostic entry point used by every
|
|
69
|
+
// first-party protocol. Stays in tools.ts because it is the central glue
|
|
70
|
+
// between adapters and event emission.
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
282
72
|
|
|
283
73
|
/**
|
|
284
74
|
* Options for the shared protocol-agnostic runtime tool executor.
|
|
@@ -295,124 +85,6 @@ export interface RuntimeToolExecutorOptions {
|
|
|
295
85
|
readonly makeToolCallId?: (tool: RuntimeToolIdentity, callIndex: number) => string;
|
|
296
86
|
}
|
|
297
87
|
|
|
298
|
-
const webSearchIdentity: RuntimeToolIdentity = {
|
|
299
|
-
id: "dogpile.tools.webSearch",
|
|
300
|
-
namespace: "dogpile",
|
|
301
|
-
name: "webSearch",
|
|
302
|
-
version: "1.0.0",
|
|
303
|
-
description: "Search the web through a caller-provided fetch-compatible search adapter."
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const codeExecIdentity: RuntimeToolIdentity = {
|
|
307
|
-
id: "dogpile.tools.codeExec",
|
|
308
|
-
namespace: "dogpile",
|
|
309
|
-
name: "codeExec",
|
|
310
|
-
version: "1.0.0",
|
|
311
|
-
description: "Execute code through a caller-provided sandbox adapter."
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
const webSearchInputSchema: RuntimeToolInputSchema = {
|
|
315
|
-
kind: "json-schema",
|
|
316
|
-
description: "Web search query and optional result cap.",
|
|
317
|
-
schema: {
|
|
318
|
-
type: "object",
|
|
319
|
-
properties: {
|
|
320
|
-
query: { type: "string" },
|
|
321
|
-
maxResults: { type: "number", minimum: 1 }
|
|
322
|
-
},
|
|
323
|
-
required: ["query"],
|
|
324
|
-
additionalProperties: false
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
const codeExecInputSchema: RuntimeToolInputSchema = {
|
|
329
|
-
kind: "json-schema",
|
|
330
|
-
description: "Code snippet plus language and optional timeout.",
|
|
331
|
-
schema: {
|
|
332
|
-
type: "object",
|
|
333
|
-
properties: {
|
|
334
|
-
language: {
|
|
335
|
-
type: "string",
|
|
336
|
-
enum: ["javascript", "typescript", "python", "bash", "shell"]
|
|
337
|
-
},
|
|
338
|
-
code: { type: "string" },
|
|
339
|
-
timeoutMs: { type: "number", minimum: 1 }
|
|
340
|
-
},
|
|
341
|
-
required: ["language", "code"],
|
|
342
|
-
additionalProperties: false
|
|
343
|
-
}
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
const webSearchPermissions: readonly RuntimeToolPermission[] = [
|
|
347
|
-
{
|
|
348
|
-
kind: "network",
|
|
349
|
-
allowPrivateNetwork: false
|
|
350
|
-
}
|
|
351
|
-
];
|
|
352
|
-
|
|
353
|
-
const codeExecPermissions: readonly RuntimeToolPermission[] = [
|
|
354
|
-
{
|
|
355
|
-
kind: "code-execution",
|
|
356
|
-
sandbox: "caller-provided",
|
|
357
|
-
languages: ["javascript", "typescript", "python", "bash", "shell"],
|
|
358
|
-
allowNetwork: false
|
|
359
|
-
}
|
|
360
|
-
];
|
|
361
|
-
|
|
362
|
-
const codeExecLanguages: readonly CodeExecToolLanguage[] = ["javascript", "typescript", "python", "bash", "shell"];
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* Return the default Dogpile identity for one built-in tool name.
|
|
366
|
-
*/
|
|
367
|
-
export function builtInDogpileToolIdentity(name: "webSearch"): RuntimeToolIdentity;
|
|
368
|
-
export function builtInDogpileToolIdentity(name: "codeExec"): RuntimeToolIdentity;
|
|
369
|
-
export function builtInDogpileToolIdentity(name: DogpileBuiltInToolName): RuntimeToolIdentity {
|
|
370
|
-
return name === "webSearch" ? webSearchIdentity : codeExecIdentity;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* Return the default Dogpile input schema for one built-in tool name.
|
|
375
|
-
*/
|
|
376
|
-
export function builtInDogpileToolInputSchema(name: "webSearch"): RuntimeToolInputSchema;
|
|
377
|
-
export function builtInDogpileToolInputSchema(name: "codeExec"): RuntimeToolInputSchema;
|
|
378
|
-
export function builtInDogpileToolInputSchema(name: DogpileBuiltInToolName): RuntimeToolInputSchema {
|
|
379
|
-
return name === "webSearch" ? webSearchInputSchema : codeExecInputSchema;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* Return the default permission declarations for one built-in tool name.
|
|
384
|
-
*/
|
|
385
|
-
export function builtInDogpileToolPermissions(name: DogpileBuiltInToolName): readonly RuntimeToolPermission[] {
|
|
386
|
-
return name === "webSearch" ? webSearchPermissions : codeExecPermissions;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* Validate one built-in Dogpile tool input before adapter execution.
|
|
391
|
-
*/
|
|
392
|
-
export function validateBuiltInDogpileToolInput(
|
|
393
|
-
name: "webSearch",
|
|
394
|
-
input: Readonly<Partial<WebSearchToolInput>>
|
|
395
|
-
): RuntimeToolValidationResult;
|
|
396
|
-
export function validateBuiltInDogpileToolInput(
|
|
397
|
-
name: "codeExec",
|
|
398
|
-
input: Readonly<Partial<CodeExecToolInput>>
|
|
399
|
-
): RuntimeToolValidationResult;
|
|
400
|
-
export function validateBuiltInDogpileToolInput(
|
|
401
|
-
name: DogpileBuiltInToolName,
|
|
402
|
-
input: Readonly<Partial<WebSearchToolInput> | Partial<CodeExecToolInput>>
|
|
403
|
-
): RuntimeToolValidationResult;
|
|
404
|
-
export function validateBuiltInDogpileToolInput(
|
|
405
|
-
name: DogpileBuiltInToolName,
|
|
406
|
-
input: Readonly<Partial<WebSearchToolInput> | Partial<CodeExecToolInput>>
|
|
407
|
-
): RuntimeToolValidationResult {
|
|
408
|
-
const issues =
|
|
409
|
-
name === "webSearch"
|
|
410
|
-
? validateWebSearchInput(input as Readonly<Partial<WebSearchToolInput>>)
|
|
411
|
-
: validateCodeExecInput(input as Readonly<Partial<CodeExecToolInput>>);
|
|
412
|
-
|
|
413
|
-
return issues.length === 0 ? { type: "valid" } : { type: "invalid", issues };
|
|
414
|
-
}
|
|
415
|
-
|
|
416
88
|
/**
|
|
417
89
|
* Create the shared runtime tool executor used by every first-party protocol.
|
|
418
90
|
*
|
|
@@ -567,45 +239,6 @@ function runtimeToolPermissionManifest(permission: RuntimeToolPermission): JsonO
|
|
|
567
239
|
};
|
|
568
240
|
}
|
|
569
241
|
|
|
570
|
-
function validateCodeExecAdapterInput(
|
|
571
|
-
input: Readonly<Partial<CodeExecToolInput>>,
|
|
572
|
-
options: Pick<CodeExecToolAdapterOptions, "languages" | "maxTimeoutMs" | "defaultTimeoutMs">
|
|
573
|
-
): RuntimeToolValidationResult {
|
|
574
|
-
const issues = [...validateCodeExecInput(input)];
|
|
575
|
-
const languages = options.languages ?? codeExecLanguages;
|
|
576
|
-
|
|
577
|
-
if (typeof input.language === "string" && isCodeExecLanguage(input.language) && !languages.includes(input.language)) {
|
|
578
|
-
issues.push({
|
|
579
|
-
code: "invalid-value",
|
|
580
|
-
path: "language",
|
|
581
|
-
message: "codeExec.language is not enabled for this adapter.",
|
|
582
|
-
detail: {
|
|
583
|
-
allowed: Array.from(languages)
|
|
584
|
-
}
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
const effectiveTimeoutMs = input.timeoutMs ?? options.defaultTimeoutMs;
|
|
589
|
-
if (
|
|
590
|
-
effectiveTimeoutMs !== undefined &&
|
|
591
|
-
options.maxTimeoutMs !== undefined &&
|
|
592
|
-
Number.isFinite(effectiveTimeoutMs) &&
|
|
593
|
-
Number.isFinite(options.maxTimeoutMs) &&
|
|
594
|
-
effectiveTimeoutMs > options.maxTimeoutMs
|
|
595
|
-
) {
|
|
596
|
-
issues.push({
|
|
597
|
-
code: "out-of-range",
|
|
598
|
-
path: input.timeoutMs === undefined ? "defaultTimeoutMs" : "timeoutMs",
|
|
599
|
-
message: `codeExec.timeoutMs must be less than or equal to ${options.maxTimeoutMs}.`,
|
|
600
|
-
detail: {
|
|
601
|
-
maximum: options.maxTimeoutMs
|
|
602
|
-
}
|
|
603
|
-
});
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
return issues.length === 0 ? { type: "valid" } : { type: "invalid", issues };
|
|
607
|
-
}
|
|
608
|
-
|
|
609
242
|
function createExecutionContext(
|
|
610
243
|
options: RuntimeToolExecutorOptions,
|
|
611
244
|
request: RuntimeToolExecutionRequest,
|
|
@@ -644,8 +277,8 @@ async function executeRuntimeTool(
|
|
|
644
277
|
};
|
|
645
278
|
}
|
|
646
279
|
|
|
647
|
-
const validation =
|
|
648
|
-
if (validation
|
|
280
|
+
const validation = tool.validateInput?.(input);
|
|
281
|
+
if (validation?.type === "invalid") {
|
|
649
282
|
return {
|
|
650
283
|
type: "error",
|
|
651
284
|
toolCallId: context.toolCallId,
|
|
@@ -678,17 +311,6 @@ async function executeRuntimeTool(
|
|
|
678
311
|
}
|
|
679
312
|
}
|
|
680
313
|
|
|
681
|
-
function validateRuntimeToolInput(
|
|
682
|
-
tool: RuntimeTool<JsonObject, JsonValue>,
|
|
683
|
-
input: JsonObject
|
|
684
|
-
): RuntimeToolValidationResult {
|
|
685
|
-
if (typeof tool.validateInput !== "function") {
|
|
686
|
-
return { type: "valid" };
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
return tool.validateInput(input);
|
|
690
|
-
}
|
|
691
|
-
|
|
692
314
|
function mergeToolMetadata(base: JsonObject | undefined, request: JsonObject | undefined): JsonObject {
|
|
693
315
|
return {
|
|
694
316
|
...(base ?? {}),
|
|
@@ -699,820 +321,3 @@ function mergeToolMetadata(base: JsonObject | undefined, request: JsonObject | u
|
|
|
699
321
|
function defaultToolCallId(runId: string, callIndex: number): string {
|
|
700
322
|
return `${runId}:tool-${callIndex + 1}`;
|
|
701
323
|
}
|
|
702
|
-
|
|
703
|
-
/**
|
|
704
|
-
* Convert an unknown adapter failure into Dogpile's serializable error data.
|
|
705
|
-
*/
|
|
706
|
-
export function normalizeRuntimeToolAdapterError(error: unknown): RuntimeToolAdapterError {
|
|
707
|
-
if (isRuntimeToolAdapterError(error)) {
|
|
708
|
-
return error;
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
if (error instanceof DOMException && error.name === "AbortError") {
|
|
712
|
-
return {
|
|
713
|
-
code: "aborted",
|
|
714
|
-
message: error.message || "Tool execution was aborted.",
|
|
715
|
-
retryable: true,
|
|
716
|
-
detail: {
|
|
717
|
-
name: error.name
|
|
718
|
-
}
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
if (error instanceof Error) {
|
|
723
|
-
return {
|
|
724
|
-
code: "backend-error",
|
|
725
|
-
message: error.message,
|
|
726
|
-
retryable: false,
|
|
727
|
-
detail: {
|
|
728
|
-
name: error.name
|
|
729
|
-
}
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
return {
|
|
734
|
-
code: "unknown",
|
|
735
|
-
message: "Tool execution failed with a non-Error value.",
|
|
736
|
-
retryable: false,
|
|
737
|
-
detail: {
|
|
738
|
-
valueType: typeof error
|
|
739
|
-
}
|
|
740
|
-
};
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
/**
|
|
744
|
-
* Create Dogpile's built-in fetch-based web search adapter.
|
|
745
|
-
*
|
|
746
|
-
* @remarks
|
|
747
|
-
* The adapter is backend-neutral: by default it sends a GET request with
|
|
748
|
-
* `q` and `limit` query parameters, then accepts either `{ results: [...] }`
|
|
749
|
-
* or a bare array of result objects from the response JSON. Callers can replace
|
|
750
|
-
* request construction or response parsing for a specific search API while
|
|
751
|
-
* keeping Dogpile's shared runtime tool contract, identity, permissions, input
|
|
752
|
-
* validation, and serializable errors.
|
|
753
|
-
*/
|
|
754
|
-
export function createWebSearchToolAdapter(
|
|
755
|
-
options: WebSearchToolAdapterOptions
|
|
756
|
-
): RuntimeToolAdapterContract<WebSearchToolInput, WebSearchToolOutput> {
|
|
757
|
-
const identity = mergeIdentity(webSearchIdentity, options.identity);
|
|
758
|
-
|
|
759
|
-
return normalizeBuiltInDogpileTool({
|
|
760
|
-
name: "webSearch",
|
|
761
|
-
...(options.identity ? { identity: options.identity } : {}),
|
|
762
|
-
...(options.permissions ? { permissions: options.permissions } : {}),
|
|
763
|
-
async execute(input, context): Promise<RuntimeToolResult<WebSearchToolOutput>> {
|
|
764
|
-
const fetchImplementation = options.fetch ?? globalThis.fetch;
|
|
765
|
-
|
|
766
|
-
if (!fetchImplementation) {
|
|
767
|
-
return {
|
|
768
|
-
type: "error",
|
|
769
|
-
toolCallId: context.toolCallId,
|
|
770
|
-
tool: identity,
|
|
771
|
-
error: {
|
|
772
|
-
code: "unavailable",
|
|
773
|
-
message: "No fetch implementation is available for webSearch.",
|
|
774
|
-
retryable: false
|
|
775
|
-
}
|
|
776
|
-
};
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
const request = options.buildRequest
|
|
780
|
-
? options.buildRequest(input, context)
|
|
781
|
-
: defaultWebSearchRequest(options, input, context);
|
|
782
|
-
const response = await fetchImplementation(request.url, {
|
|
783
|
-
...request.init,
|
|
784
|
-
...(context.abortSignal ? { signal: context.abortSignal } : {})
|
|
785
|
-
});
|
|
786
|
-
|
|
787
|
-
if (!response.ok) {
|
|
788
|
-
throw {
|
|
789
|
-
code: response.status >= 500 ? "unavailable" : "backend-error",
|
|
790
|
-
message: `Web search backend returned HTTP ${response.status}.`,
|
|
791
|
-
retryable: response.status === 408 || response.status === 429 || response.status >= 500,
|
|
792
|
-
detail: {
|
|
793
|
-
status: response.status,
|
|
794
|
-
statusText: response.statusText
|
|
795
|
-
}
|
|
796
|
-
} satisfies RuntimeToolAdapterError;
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
const output = options.parseResponse
|
|
800
|
-
? await options.parseResponse(response, input, context)
|
|
801
|
-
: await defaultWebSearchResponseParser(response);
|
|
802
|
-
|
|
803
|
-
return {
|
|
804
|
-
type: "success",
|
|
805
|
-
toolCallId: context.toolCallId,
|
|
806
|
-
tool: identity,
|
|
807
|
-
output
|
|
808
|
-
};
|
|
809
|
-
}
|
|
810
|
-
});
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
/**
|
|
814
|
-
* Create Dogpile's built-in code execution adapter around a caller-owned sandbox.
|
|
815
|
-
*
|
|
816
|
-
* @remarks
|
|
817
|
-
* Dogpile core stays runtime-portable and never evaluates code itself. This
|
|
818
|
-
* adapter supplies the stable `codeExec` identity, schema, permissions,
|
|
819
|
-
* validation, timeout defaults, abort handling, and serializable errors while
|
|
820
|
-
* the host application owns the sandbox boundary.
|
|
821
|
-
*/
|
|
822
|
-
export function createCodeExecToolAdapter(
|
|
823
|
-
options: CodeExecToolAdapterOptions
|
|
824
|
-
): RuntimeToolAdapterContract<CodeExecToolInput, CodeExecToolOutput> {
|
|
825
|
-
const identity = mergeIdentity(codeExecIdentity, options.identity);
|
|
826
|
-
const permissions =
|
|
827
|
-
options.permissions ??
|
|
828
|
-
codeExecPermissionsFor(options.languages ?? codeExecLanguages, options.allowNetwork ?? false);
|
|
829
|
-
const inputSchema = codeExecInputSchemaFor(options.languages ?? codeExecLanguages);
|
|
830
|
-
|
|
831
|
-
return {
|
|
832
|
-
identity,
|
|
833
|
-
inputSchema,
|
|
834
|
-
permissions,
|
|
835
|
-
validateInput: (input: Readonly<CodeExecToolInput>) => validateCodeExecAdapterInput(input, options),
|
|
836
|
-
async execute(input, context): Promise<RuntimeToolResult<CodeExecToolOutput>> {
|
|
837
|
-
const validation = validateCodeExecAdapterInput(input, options);
|
|
838
|
-
|
|
839
|
-
if (validation.type === "invalid") {
|
|
840
|
-
return {
|
|
841
|
-
type: "error",
|
|
842
|
-
toolCallId: context.toolCallId,
|
|
843
|
-
tool: identity,
|
|
844
|
-
error: {
|
|
845
|
-
code: "invalid-input",
|
|
846
|
-
message: "Invalid codeExec tool input.",
|
|
847
|
-
retryable: false,
|
|
848
|
-
detail: {
|
|
849
|
-
issues: validation.issues as unknown as JsonValue
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
};
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
const timeoutMs = input.timeoutMs ?? options.defaultTimeoutMs;
|
|
856
|
-
const executionInput: CodeExecToolInput =
|
|
857
|
-
timeoutMs === undefined
|
|
858
|
-
? input
|
|
859
|
-
: {
|
|
860
|
-
...input,
|
|
861
|
-
timeoutMs
|
|
862
|
-
};
|
|
863
|
-
|
|
864
|
-
try {
|
|
865
|
-
const output = await executeSandboxWithPolicy(options.execute, executionInput, context, timeoutMs);
|
|
866
|
-
|
|
867
|
-
return {
|
|
868
|
-
type: "success",
|
|
869
|
-
toolCallId: context.toolCallId,
|
|
870
|
-
tool: identity,
|
|
871
|
-
output
|
|
872
|
-
};
|
|
873
|
-
} catch (error) {
|
|
874
|
-
return {
|
|
875
|
-
type: "error",
|
|
876
|
-
toolCallId: context.toolCallId,
|
|
877
|
-
tool: identity,
|
|
878
|
-
error: normalizeRuntimeToolAdapterError(error)
|
|
879
|
-
};
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
};
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
/**
|
|
886
|
-
* Normalize one built-in Dogpile tool definition into the shared runtime tool interface.
|
|
887
|
-
*/
|
|
888
|
-
export function normalizeBuiltInDogpileTool(
|
|
889
|
-
definition: WebSearchDogpileToolDefinition
|
|
890
|
-
): RuntimeToolAdapterContract<WebSearchToolInput, WebSearchToolOutput>;
|
|
891
|
-
export function normalizeBuiltInDogpileTool(
|
|
892
|
-
definition: CodeExecDogpileToolDefinition
|
|
893
|
-
): RuntimeToolAdapterContract<CodeExecToolInput, CodeExecToolOutput>;
|
|
894
|
-
export function normalizeBuiltInDogpileTool(definition: BuiltInDogpileToolDefinition): BuiltInDogpileRuntimeTool {
|
|
895
|
-
switch (definition.name) {
|
|
896
|
-
case "webSearch": {
|
|
897
|
-
const identity = mergeIdentity(webSearchIdentity, definition.identity);
|
|
898
|
-
const permissions = definition.permissions ?? webSearchPermissions;
|
|
899
|
-
const tool: RuntimeToolAdapterContract<WebSearchToolInput, WebSearchToolOutput> = {
|
|
900
|
-
identity,
|
|
901
|
-
inputSchema: definition.inputSchema ?? webSearchInputSchema,
|
|
902
|
-
permissions,
|
|
903
|
-
validateInput: (input: Readonly<WebSearchToolInput>) => validateBuiltInDogpileToolInput("webSearch", input),
|
|
904
|
-
execute: (input: Readonly<WebSearchToolInput>, context: RuntimeToolExecutionContext) =>
|
|
905
|
-
executeBuiltInTool(identity, definition.execute, input, context, "webSearch")
|
|
906
|
-
};
|
|
907
|
-
return tool;
|
|
908
|
-
}
|
|
909
|
-
case "codeExec": {
|
|
910
|
-
const identity = mergeIdentity(codeExecIdentity, definition.identity);
|
|
911
|
-
const permissions = definition.permissions ?? codeExecPermissions;
|
|
912
|
-
const tool: RuntimeToolAdapterContract<CodeExecToolInput, CodeExecToolOutput> = {
|
|
913
|
-
identity,
|
|
914
|
-
inputSchema: definition.inputSchema ?? codeExecInputSchema,
|
|
915
|
-
permissions,
|
|
916
|
-
validateInput: (input: Readonly<CodeExecToolInput>) => validateBuiltInDogpileToolInput("codeExec", input),
|
|
917
|
-
execute: (input: Readonly<CodeExecToolInput>, context: RuntimeToolExecutionContext) =>
|
|
918
|
-
executeBuiltInTool(identity, definition.execute, input, context, "codeExec")
|
|
919
|
-
};
|
|
920
|
-
return tool;
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
/**
|
|
926
|
-
* Normalize configured built-in Dogpile tool executors into runtime tools.
|
|
927
|
-
*/
|
|
928
|
-
export function normalizeBuiltInDogpileTools(tools: BuiltInDogpileToolExecutors): readonly BuiltInDogpileRuntimeTool[] {
|
|
929
|
-
const normalized: BuiltInDogpileRuntimeTool[] = [];
|
|
930
|
-
|
|
931
|
-
if (tools.webSearch) {
|
|
932
|
-
normalized.push(normalizeBuiltInDogpileTool(asWebSearchDefinition(tools.webSearch)));
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
if (tools.codeExec) {
|
|
936
|
-
normalized.push(normalizeBuiltInDogpileTool(asCodeExecDefinition(tools.codeExec)));
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
return normalized;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
/**
|
|
943
|
-
* Normalize one Vercel AI SDK tool into Dogpile's shared runtime tool interface.
|
|
944
|
-
*/
|
|
945
|
-
export async function normalizeVercelAITool<
|
|
946
|
-
Name extends string,
|
|
947
|
-
Input extends JsonObject,
|
|
948
|
-
Output extends JsonValue
|
|
949
|
-
>(definition: VercelAIToolDefinition<Name, Input, Output>): Promise<RuntimeTool<Input, Output>> {
|
|
950
|
-
if (!definition.tool.execute) {
|
|
951
|
-
throw new Error(`Vercel AI tool "${definition.name}" must define execute() to run inside Dogpile.`);
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
const identity = vercelAIToolIdentity(definition);
|
|
955
|
-
const inputSchema = definition.inputSchema ?? (await vercelAIInputSchema(definition.tool, definition.name));
|
|
956
|
-
const execute = definition.tool.execute;
|
|
957
|
-
|
|
958
|
-
return {
|
|
959
|
-
identity,
|
|
960
|
-
inputSchema,
|
|
961
|
-
async execute(input, context): Promise<RuntimeToolResult<Output>> {
|
|
962
|
-
try {
|
|
963
|
-
const output = await resolveVercelAIToolOutput(
|
|
964
|
-
execute(input, {
|
|
965
|
-
toolCallId: context.toolCallId,
|
|
966
|
-
messages: Array.from(definition.messages ?? []),
|
|
967
|
-
...(context.abortSignal ? { abortSignal: context.abortSignal } : {}),
|
|
968
|
-
experimental_context: context
|
|
969
|
-
})
|
|
970
|
-
);
|
|
971
|
-
|
|
972
|
-
return {
|
|
973
|
-
type: "success",
|
|
974
|
-
toolCallId: context.toolCallId,
|
|
975
|
-
tool: identity,
|
|
976
|
-
output
|
|
977
|
-
};
|
|
978
|
-
} catch (error) {
|
|
979
|
-
return {
|
|
980
|
-
type: "error",
|
|
981
|
-
toolCallId: context.toolCallId,
|
|
982
|
-
tool: identity,
|
|
983
|
-
error: {
|
|
984
|
-
code: "vercel-ai-tool-error",
|
|
985
|
-
message: error instanceof Error ? error.message : "Vercel AI tool execution failed.",
|
|
986
|
-
retryable: false,
|
|
987
|
-
detail: errorDetail(error)
|
|
988
|
-
}
|
|
989
|
-
};
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
};
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
/**
|
|
996
|
-
* Normalize a Vercel AI SDK tool set into runtime tools in caller-defined key order.
|
|
997
|
-
*/
|
|
998
|
-
export async function normalizeVercelAITools(
|
|
999
|
-
tools: VercelAIToolSet,
|
|
1000
|
-
options: VercelAIToolSetNormalizationOptions = {}
|
|
1001
|
-
): Promise<readonly RuntimeTool<JsonObject, JsonValue>[]> {
|
|
1002
|
-
return Promise.all(
|
|
1003
|
-
Object.entries(tools).map(([name, tool]) => {
|
|
1004
|
-
const identity = removeUndefinedIdentityFields({
|
|
1005
|
-
...(options.namespace !== undefined ? { namespace: options.namespace } : {}),
|
|
1006
|
-
...(options.version !== undefined ? { version: options.version } : {}),
|
|
1007
|
-
...options.identity?.[name]
|
|
1008
|
-
});
|
|
1009
|
-
return normalizeVercelAITool({
|
|
1010
|
-
name,
|
|
1011
|
-
tool: asJsonRuntimeVercelAITool(tool),
|
|
1012
|
-
...(options.messages ? { messages: options.messages } : {}),
|
|
1013
|
-
...(identity ? { identity } : {})
|
|
1014
|
-
});
|
|
1015
|
-
})
|
|
1016
|
-
);
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
async function executeBuiltInTool<Input extends object, Output>(
|
|
1020
|
-
identity: RuntimeToolIdentity,
|
|
1021
|
-
execute: (
|
|
1022
|
-
input: Readonly<Input>,
|
|
1023
|
-
context: RuntimeToolExecutionContext
|
|
1024
|
-
) => RuntimeToolResult<Output> | Promise<RuntimeToolResult<Output>>,
|
|
1025
|
-
input: Readonly<Input>,
|
|
1026
|
-
context: RuntimeToolExecutionContext,
|
|
1027
|
-
name: DogpileBuiltInToolName
|
|
1028
|
-
): Promise<RuntimeToolResult<Output>> {
|
|
1029
|
-
const validation = validateBuiltInDogpileToolInput(
|
|
1030
|
-
name,
|
|
1031
|
-
input as Readonly<Partial<WebSearchToolInput> | Partial<CodeExecToolInput>>
|
|
1032
|
-
);
|
|
1033
|
-
|
|
1034
|
-
if (validation.type === "invalid") {
|
|
1035
|
-
return {
|
|
1036
|
-
type: "error",
|
|
1037
|
-
toolCallId: context.toolCallId,
|
|
1038
|
-
tool: identity,
|
|
1039
|
-
error: {
|
|
1040
|
-
code: "invalid-input",
|
|
1041
|
-
message: `Invalid ${name} tool input.`,
|
|
1042
|
-
retryable: false,
|
|
1043
|
-
detail: {
|
|
1044
|
-
issues: validation.issues as unknown as JsonValue
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
};
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
try {
|
|
1051
|
-
return await execute(input, context);
|
|
1052
|
-
} catch (error) {
|
|
1053
|
-
return {
|
|
1054
|
-
type: "error",
|
|
1055
|
-
toolCallId: context.toolCallId,
|
|
1056
|
-
tool: identity,
|
|
1057
|
-
error: normalizeRuntimeToolAdapterError(error)
|
|
1058
|
-
};
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
function asWebSearchDefinition(
|
|
1063
|
-
tool: WebSearchToolExecutor | WebSearchDogpileToolDefinition
|
|
1064
|
-
): WebSearchDogpileToolDefinition {
|
|
1065
|
-
return typeof tool === "function" ? { name: "webSearch", execute: tool } : tool;
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
function asCodeExecDefinition(tool: CodeExecToolExecutor | CodeExecDogpileToolDefinition): CodeExecDogpileToolDefinition {
|
|
1069
|
-
return typeof tool === "function" ? { name: "codeExec", execute: tool } : tool;
|
|
1070
|
-
}
|
|
1071
|
-
|
|
1072
|
-
function mergeIdentity(
|
|
1073
|
-
defaultIdentity: RuntimeToolIdentity,
|
|
1074
|
-
options: BuiltInDogpileToolIdentityOptions | undefined
|
|
1075
|
-
): RuntimeToolIdentity {
|
|
1076
|
-
if (!options) {
|
|
1077
|
-
return defaultIdentity;
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
return {
|
|
1081
|
-
...defaultIdentity,
|
|
1082
|
-
...(options.namespace !== undefined ? { namespace: options.namespace } : {}),
|
|
1083
|
-
...(options.version !== undefined ? { version: options.version } : {}),
|
|
1084
|
-
...(options.description !== undefined ? { description: options.description } : {})
|
|
1085
|
-
};
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
async function vercelAIInputSchema<Input extends JsonObject, Output extends JsonValue>(
|
|
1089
|
-
tool: VercelAITool<Input, Output>,
|
|
1090
|
-
name: string
|
|
1091
|
-
): Promise<RuntimeToolInputSchema> {
|
|
1092
|
-
const schema = await resolveCompatibleSchema(tool.inputSchema);
|
|
1093
|
-
const jsonSchema = asJsonObject(schema, `Vercel AI tool "${name}" input schema`);
|
|
1094
|
-
|
|
1095
|
-
return {
|
|
1096
|
-
kind: "json-schema",
|
|
1097
|
-
schema: jsonSchema,
|
|
1098
|
-
...(tool.description ? { description: tool.description } : {})
|
|
1099
|
-
};
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
async function resolveCompatibleSchema<Input>(schema: VercelAICompatibleSchema<Input>): Promise<unknown> {
|
|
1103
|
-
if (isJsonSchemaWrapper(schema)) {
|
|
1104
|
-
return await schema.jsonSchema;
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
return schema;
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
function isJsonSchemaWrapper<Input>(
|
|
1111
|
-
schema: VercelAICompatibleSchema<Input>
|
|
1112
|
-
): schema is { readonly jsonSchema: unknown | PromiseLike<unknown> } {
|
|
1113
|
-
return typeof schema === "object" && schema !== null && "jsonSchema" in schema;
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1116
|
-
function vercelAIToolIdentity<Name extends string, Input extends JsonObject, Output extends JsonValue>(
|
|
1117
|
-
definition: VercelAIToolDefinition<Name, Input, Output>
|
|
1118
|
-
): RuntimeToolIdentity {
|
|
1119
|
-
return {
|
|
1120
|
-
id: definition.identity?.id ?? `vercel-ai.tools.${definition.name}`,
|
|
1121
|
-
name: definition.name,
|
|
1122
|
-
namespace: definition.identity?.namespace ?? "vercel-ai",
|
|
1123
|
-
...(definition.identity?.version ? { version: definition.identity.version } : {}),
|
|
1124
|
-
...(definition.identity?.description ?? definition.tool.description
|
|
1125
|
-
? { description: definition.identity?.description ?? definition.tool.description }
|
|
1126
|
-
: {})
|
|
1127
|
-
};
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
async function resolveVercelAIToolOutput<Output extends JsonValue>(
|
|
1131
|
-
output: AsyncIterable<Output> | PromiseLike<Output> | Output
|
|
1132
|
-
): Promise<Output> {
|
|
1133
|
-
if (isAsyncIterable(output)) {
|
|
1134
|
-
let lastOutput: Output | undefined;
|
|
1135
|
-
|
|
1136
|
-
for await (const chunk of output) {
|
|
1137
|
-
lastOutput = chunk;
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
if (lastOutput === undefined) {
|
|
1141
|
-
throw new Error("Vercel AI tool async iterable completed without an output.");
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
return lastOutput;
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
return await output;
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
|
-
function isAsyncIterable<Output extends JsonValue>(
|
|
1151
|
-
value: AsyncIterable<Output> | PromiseLike<Output> | Output
|
|
1152
|
-
): value is AsyncIterable<Output> {
|
|
1153
|
-
return typeof value === "object" && value !== null && Symbol.asyncIterator in value;
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
function asJsonObject(value: unknown, label: string): JsonObject {
|
|
1157
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1158
|
-
throw new Error(`${label} must resolve to a JSON object.`);
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
return value as JsonObject;
|
|
1162
|
-
}
|
|
1163
|
-
|
|
1164
|
-
function errorDetail(error: unknown): JsonObject {
|
|
1165
|
-
if (error instanceof Error) {
|
|
1166
|
-
return {
|
|
1167
|
-
name: error.name
|
|
1168
|
-
};
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
return {
|
|
1172
|
-
valueType: typeof error
|
|
1173
|
-
};
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
function defaultWebSearchRequest(
|
|
1177
|
-
options: WebSearchToolAdapterOptions,
|
|
1178
|
-
input: Readonly<WebSearchToolInput>,
|
|
1179
|
-
_context: RuntimeToolExecutionContext
|
|
1180
|
-
): WebSearchFetchRequest {
|
|
1181
|
-
const url = new URL(String(options.endpoint));
|
|
1182
|
-
url.searchParams.set("q", input.query);
|
|
1183
|
-
url.searchParams.set("limit", String(input.maxResults ?? options.defaultMaxResults ?? 10));
|
|
1184
|
-
|
|
1185
|
-
return {
|
|
1186
|
-
url,
|
|
1187
|
-
init: {
|
|
1188
|
-
method: "GET",
|
|
1189
|
-
...(options.headers ? { headers: options.headers } : {})
|
|
1190
|
-
}
|
|
1191
|
-
};
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
async function defaultWebSearchResponseParser(response: Response): Promise<WebSearchToolOutput> {
|
|
1195
|
-
const payload: unknown = await response.json();
|
|
1196
|
-
const resultValues = Array.isArray(payload)
|
|
1197
|
-
? payload
|
|
1198
|
-
: isJsonObject(payload) && Array.isArray(payload.results)
|
|
1199
|
-
? payload.results
|
|
1200
|
-
: undefined;
|
|
1201
|
-
|
|
1202
|
-
if (!resultValues) {
|
|
1203
|
-
throw {
|
|
1204
|
-
code: "backend-error",
|
|
1205
|
-
message: "Web search backend response must contain a results array.",
|
|
1206
|
-
retryable: false
|
|
1207
|
-
} satisfies RuntimeToolAdapterError;
|
|
1208
|
-
}
|
|
1209
|
-
|
|
1210
|
-
return {
|
|
1211
|
-
results: resultValues.map(normalizeWebSearchResult)
|
|
1212
|
-
};
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
function codeExecPermissionsFor(
|
|
1216
|
-
languages: readonly CodeExecToolLanguage[],
|
|
1217
|
-
allowNetwork: boolean
|
|
1218
|
-
): readonly RuntimeToolPermission[] {
|
|
1219
|
-
return [
|
|
1220
|
-
{
|
|
1221
|
-
kind: "code-execution",
|
|
1222
|
-
sandbox: "caller-provided",
|
|
1223
|
-
languages,
|
|
1224
|
-
allowNetwork
|
|
1225
|
-
}
|
|
1226
|
-
];
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
function codeExecInputSchemaFor(languages: readonly CodeExecToolLanguage[]): RuntimeToolInputSchema {
|
|
1230
|
-
return {
|
|
1231
|
-
kind: "json-schema",
|
|
1232
|
-
...(codeExecInputSchema.description ? { description: codeExecInputSchema.description } : {}),
|
|
1233
|
-
schema: {
|
|
1234
|
-
type: "object",
|
|
1235
|
-
properties: {
|
|
1236
|
-
language: {
|
|
1237
|
-
type: "string",
|
|
1238
|
-
enum: Array.from(languages)
|
|
1239
|
-
},
|
|
1240
|
-
code: { type: "string" },
|
|
1241
|
-
timeoutMs: { type: "number", minimum: 1 }
|
|
1242
|
-
},
|
|
1243
|
-
required: ["language", "code"],
|
|
1244
|
-
additionalProperties: false
|
|
1245
|
-
}
|
|
1246
|
-
};
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
async function executeSandboxWithPolicy(
|
|
1250
|
-
execute: CodeExecSandboxExecutor,
|
|
1251
|
-
input: Readonly<CodeExecToolInput>,
|
|
1252
|
-
context: RuntimeToolExecutionContext,
|
|
1253
|
-
timeoutMs: number | undefined
|
|
1254
|
-
): Promise<CodeExecToolOutput> {
|
|
1255
|
-
if (context.abortSignal?.aborted) {
|
|
1256
|
-
throw {
|
|
1257
|
-
code: "aborted",
|
|
1258
|
-
message: "Code execution was aborted before the sandbox started.",
|
|
1259
|
-
retryable: true
|
|
1260
|
-
} satisfies RuntimeToolAdapterError;
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
const execution = Promise.resolve().then(() => execute(input, context));
|
|
1264
|
-
|
|
1265
|
-
if (timeoutMs === undefined && context.abortSignal === undefined) {
|
|
1266
|
-
return await execution;
|
|
1267
|
-
}
|
|
1268
|
-
|
|
1269
|
-
return await new Promise<CodeExecToolOutput>((resolve, reject) => {
|
|
1270
|
-
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
|
1271
|
-
|
|
1272
|
-
const cleanup = (): void => {
|
|
1273
|
-
if (timeoutId !== undefined) {
|
|
1274
|
-
clearTimeout(timeoutId);
|
|
1275
|
-
}
|
|
1276
|
-
context.abortSignal?.removeEventListener("abort", abortHandler);
|
|
1277
|
-
};
|
|
1278
|
-
|
|
1279
|
-
const abortHandler = (): void => {
|
|
1280
|
-
cleanup();
|
|
1281
|
-
reject({
|
|
1282
|
-
code: "aborted",
|
|
1283
|
-
message: "Code execution was aborted.",
|
|
1284
|
-
retryable: true
|
|
1285
|
-
} satisfies RuntimeToolAdapterError);
|
|
1286
|
-
};
|
|
1287
|
-
|
|
1288
|
-
if (context.abortSignal) {
|
|
1289
|
-
context.abortSignal.addEventListener("abort", abortHandler, { once: true });
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
if (timeoutMs !== undefined) {
|
|
1293
|
-
timeoutId = setTimeout(() => {
|
|
1294
|
-
cleanup();
|
|
1295
|
-
reject({
|
|
1296
|
-
code: "timeout",
|
|
1297
|
-
message: `Code execution exceeded timeout of ${timeoutMs}ms.`,
|
|
1298
|
-
retryable: true,
|
|
1299
|
-
detail: {
|
|
1300
|
-
timeoutMs
|
|
1301
|
-
}
|
|
1302
|
-
} satisfies RuntimeToolAdapterError);
|
|
1303
|
-
}, timeoutMs);
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
execution.then(
|
|
1307
|
-
(output) => {
|
|
1308
|
-
cleanup();
|
|
1309
|
-
resolve(output);
|
|
1310
|
-
},
|
|
1311
|
-
(error: unknown) => {
|
|
1312
|
-
cleanup();
|
|
1313
|
-
reject(error);
|
|
1314
|
-
}
|
|
1315
|
-
);
|
|
1316
|
-
});
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
function normalizeWebSearchResult(value: unknown): WebSearchToolResult {
|
|
1320
|
-
if (!isJsonObject(value)) {
|
|
1321
|
-
throw {
|
|
1322
|
-
code: "backend-error",
|
|
1323
|
-
message: "Web search result must be a JSON object.",
|
|
1324
|
-
retryable: false
|
|
1325
|
-
} satisfies RuntimeToolAdapterError;
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
const title = jsonString(value.title, "title");
|
|
1329
|
-
const url = jsonString(value.url, "url");
|
|
1330
|
-
const snippet = optionalJsonString(value.snippet, "snippet");
|
|
1331
|
-
const metadata = optionalJsonObject(value.metadata, "metadata");
|
|
1332
|
-
|
|
1333
|
-
return {
|
|
1334
|
-
title,
|
|
1335
|
-
url,
|
|
1336
|
-
...(snippet !== undefined ? { snippet } : {}),
|
|
1337
|
-
...(metadata !== undefined ? { metadata } : {})
|
|
1338
|
-
};
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
function jsonString(value: JsonValue | undefined, fieldName: string): string {
|
|
1342
|
-
if (typeof value !== "string" || value.trim().length === 0) {
|
|
1343
|
-
throw {
|
|
1344
|
-
code: "backend-error",
|
|
1345
|
-
message: `Web search result ${fieldName} must be a non-empty string.`,
|
|
1346
|
-
retryable: false
|
|
1347
|
-
} satisfies RuntimeToolAdapterError;
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
return value;
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
function optionalJsonString(value: JsonValue | undefined, fieldName: string): string | undefined {
|
|
1354
|
-
if (value === undefined) {
|
|
1355
|
-
return undefined;
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
if (typeof value !== "string") {
|
|
1359
|
-
throw {
|
|
1360
|
-
code: "backend-error",
|
|
1361
|
-
message: `Web search result ${fieldName} must be a string when present.`,
|
|
1362
|
-
retryable: false
|
|
1363
|
-
} satisfies RuntimeToolAdapterError;
|
|
1364
|
-
}
|
|
1365
|
-
|
|
1366
|
-
return value;
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
function optionalJsonObject(value: JsonValue | undefined, fieldName: string): JsonObject | undefined {
|
|
1370
|
-
if (value === undefined) {
|
|
1371
|
-
return undefined;
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
if (!isJsonObject(value)) {
|
|
1375
|
-
throw {
|
|
1376
|
-
code: "backend-error",
|
|
1377
|
-
message: `Web search result ${fieldName} must be a JSON object when present.`,
|
|
1378
|
-
retryable: false
|
|
1379
|
-
} satisfies RuntimeToolAdapterError;
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
return value;
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
|
-
function isJsonObject(value: unknown): value is JsonObject {
|
|
1386
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1387
|
-
}
|
|
1388
|
-
|
|
1389
|
-
function validateWebSearchInput(input: Readonly<Partial<WebSearchToolInput>>): readonly RuntimeToolValidationIssue[] {
|
|
1390
|
-
const issues: RuntimeToolValidationIssue[] = [];
|
|
1391
|
-
|
|
1392
|
-
if (typeof input.query !== "string") {
|
|
1393
|
-
issues.push({
|
|
1394
|
-
code: input.query === undefined ? "missing-field" : "invalid-type",
|
|
1395
|
-
path: "query",
|
|
1396
|
-
message: "webSearch.query must be a string."
|
|
1397
|
-
});
|
|
1398
|
-
} else if (input.query.trim().length === 0) {
|
|
1399
|
-
issues.push({
|
|
1400
|
-
code: "invalid-value",
|
|
1401
|
-
path: "query",
|
|
1402
|
-
message: "webSearch.query must not be empty."
|
|
1403
|
-
});
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
if (input.maxResults !== undefined) {
|
|
1407
|
-
if (typeof input.maxResults !== "number" || !Number.isFinite(input.maxResults)) {
|
|
1408
|
-
issues.push({
|
|
1409
|
-
code: "invalid-type",
|
|
1410
|
-
path: "maxResults",
|
|
1411
|
-
message: "webSearch.maxResults must be a finite number."
|
|
1412
|
-
});
|
|
1413
|
-
} else if (input.maxResults < 1) {
|
|
1414
|
-
issues.push({
|
|
1415
|
-
code: "out-of-range",
|
|
1416
|
-
path: "maxResults",
|
|
1417
|
-
message: "webSearch.maxResults must be greater than or equal to 1.",
|
|
1418
|
-
detail: {
|
|
1419
|
-
minimum: 1
|
|
1420
|
-
}
|
|
1421
|
-
});
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
return issues;
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
|
-
function validateCodeExecInput(input: Readonly<Partial<CodeExecToolInput>>): readonly RuntimeToolValidationIssue[] {
|
|
1429
|
-
const issues: RuntimeToolValidationIssue[] = [];
|
|
1430
|
-
|
|
1431
|
-
if (typeof input.language !== "string") {
|
|
1432
|
-
issues.push({
|
|
1433
|
-
code: input.language === undefined ? "missing-field" : "invalid-type",
|
|
1434
|
-
path: "language",
|
|
1435
|
-
message: "codeExec.language must be a string."
|
|
1436
|
-
});
|
|
1437
|
-
} else if (!isCodeExecLanguage(input.language)) {
|
|
1438
|
-
issues.push({
|
|
1439
|
-
code: "invalid-value",
|
|
1440
|
-
path: "language",
|
|
1441
|
-
message: "codeExec.language must be one of javascript, typescript, python, bash, or shell.",
|
|
1442
|
-
detail: {
|
|
1443
|
-
allowed: ["javascript", "typescript", "python", "bash", "shell"]
|
|
1444
|
-
}
|
|
1445
|
-
});
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
if (typeof input.code !== "string") {
|
|
1449
|
-
issues.push({
|
|
1450
|
-
code: input.code === undefined ? "missing-field" : "invalid-type",
|
|
1451
|
-
path: "code",
|
|
1452
|
-
message: "codeExec.code must be a string."
|
|
1453
|
-
});
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
|
-
if (input.timeoutMs !== undefined) {
|
|
1457
|
-
if (typeof input.timeoutMs !== "number" || !Number.isFinite(input.timeoutMs)) {
|
|
1458
|
-
issues.push({
|
|
1459
|
-
code: "invalid-type",
|
|
1460
|
-
path: "timeoutMs",
|
|
1461
|
-
message: "codeExec.timeoutMs must be a finite number."
|
|
1462
|
-
});
|
|
1463
|
-
} else if (input.timeoutMs < 1) {
|
|
1464
|
-
issues.push({
|
|
1465
|
-
code: "out-of-range",
|
|
1466
|
-
path: "timeoutMs",
|
|
1467
|
-
message: "codeExec.timeoutMs must be greater than or equal to 1.",
|
|
1468
|
-
detail: {
|
|
1469
|
-
minimum: 1
|
|
1470
|
-
}
|
|
1471
|
-
});
|
|
1472
|
-
}
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
return issues;
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1478
|
-
function isCodeExecLanguage(value: string): value is CodeExecToolInput["language"] {
|
|
1479
|
-
return value === "javascript" || value === "typescript" || value === "python" || value === "bash" || value === "shell";
|
|
1480
|
-
}
|
|
1481
|
-
|
|
1482
|
-
function isRuntimeToolAdapterError(error: unknown): error is RuntimeToolAdapterError {
|
|
1483
|
-
if (typeof error !== "object" || error === null || !("code" in error) || !("message" in error)) {
|
|
1484
|
-
return false;
|
|
1485
|
-
}
|
|
1486
|
-
|
|
1487
|
-
const candidate = error as { readonly code: unknown; readonly message: unknown };
|
|
1488
|
-
return isRuntimeToolAdapterErrorCode(candidate.code) && typeof candidate.message === "string";
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1491
|
-
function isRuntimeToolAdapterErrorCode(value: unknown): value is RuntimeToolAdapterError["code"] {
|
|
1492
|
-
return (
|
|
1493
|
-
value === "invalid-input" ||
|
|
1494
|
-
value === "permission-denied" ||
|
|
1495
|
-
value === "timeout" ||
|
|
1496
|
-
value === "aborted" ||
|
|
1497
|
-
value === "unavailable" ||
|
|
1498
|
-
value === "backend-error" ||
|
|
1499
|
-
value === "unknown"
|
|
1500
|
-
);
|
|
1501
|
-
}
|
|
1502
|
-
|
|
1503
|
-
function removeUndefinedIdentityFields(
|
|
1504
|
-
identity: VercelAIToolIdentityOptions
|
|
1505
|
-
): VercelAIToolIdentityOptions | undefined {
|
|
1506
|
-
const normalized: VercelAIToolIdentityOptions = {
|
|
1507
|
-
...(identity.id !== undefined ? { id: identity.id } : {}),
|
|
1508
|
-
...(identity.namespace !== undefined ? { namespace: identity.namespace } : {}),
|
|
1509
|
-
...(identity.version !== undefined ? { version: identity.version } : {}),
|
|
1510
|
-
...(identity.description !== undefined ? { description: identity.description } : {})
|
|
1511
|
-
};
|
|
1512
|
-
|
|
1513
|
-
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
|
1514
|
-
}
|
|
1515
|
-
|
|
1516
|
-
function asJsonRuntimeVercelAITool(tool: VercelAIToolSetEntry): VercelAITool<JsonObject, JsonValue> {
|
|
1517
|
-
return tool as unknown as VercelAITool<JsonObject, JsonValue>;
|
|
1518
|
-
}
|