@yourgpt/llm-sdk 2.6.0-beta.2 → 2.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.
- package/LICENSE +21 -0
- package/README.md +87 -17
- package/dist/adapters/index.d.mts +11 -13
- package/dist/adapters/index.d.ts +11 -13
- package/dist/adapters/index.js +406 -114
- package/dist/adapters/index.mjs +406 -114
- package/dist/audio-K-Z3-Bce.d.mts +191 -0
- package/dist/audio-K-Z3-Bce.d.ts +191 -0
- package/dist/{base-BICaQaRS.d.mts → base-6LzczuCg.d.ts} +8 -1
- package/dist/{base-CpRPB8u8.d.ts → base-DySbTP8C.d.mts} +8 -1
- package/dist/decisions-CJzOt87t.d.mts +137 -0
- package/dist/decisions-CJzOt87t.d.ts +137 -0
- package/dist/fallback/index.d.mts +4 -4
- package/dist/fallback/index.d.ts +4 -4
- package/dist/http-BQxUT5A9.d.mts +9 -0
- package/dist/http-BQxUT5A9.d.ts +9 -0
- package/dist/index.d.mts +17 -9
- package/dist/index.d.ts +17 -9
- package/dist/index.js +698 -205
- package/dist/index.mjs +695 -206
- package/dist/providers/anthropic/index.d.mts +7 -4
- package/dist/providers/anthropic/index.d.ts +7 -4
- package/dist/providers/anthropic/index.js +389 -115
- package/dist/providers/anthropic/index.mjs +389 -115
- package/dist/providers/azure/index.d.mts +3 -3
- package/dist/providers/azure/index.d.ts +3 -3
- package/dist/providers/cloudflare/index.d.mts +11 -0
- package/dist/providers/cloudflare/index.d.ts +11 -0
- package/dist/providers/cloudflare/index.js +743 -0
- package/dist/providers/cloudflare/index.mjs +741 -0
- package/dist/providers/fireworks/index.d.mts +3 -3
- package/dist/providers/fireworks/index.d.ts +3 -3
- package/dist/providers/fireworks/index.js +181 -60
- package/dist/providers/fireworks/index.mjs +181 -60
- package/dist/providers/google/index.d.mts +3 -3
- package/dist/providers/google/index.d.ts +3 -3
- package/dist/providers/google/index.js +181 -60
- package/dist/providers/google/index.mjs +181 -60
- package/dist/providers/ollama/index.d.mts +4 -4
- package/dist/providers/ollama/index.d.ts +4 -4
- package/dist/providers/openai/index.d.mts +38 -6
- package/dist/providers/openai/index.d.ts +38 -6
- package/dist/providers/openai/index.js +1451 -85
- package/dist/providers/openai/index.mjs +1449 -86
- package/dist/providers/openrouter/index.d.mts +21 -4
- package/dist/providers/openrouter/index.d.ts +21 -4
- package/dist/providers/openrouter/index.js +1040 -131
- package/dist/providers/openrouter/index.mjs +1040 -132
- package/dist/providers/togetherai/index.d.mts +3 -3
- package/dist/providers/togetherai/index.d.ts +3 -3
- package/dist/providers/togetherai/index.js +181 -60
- package/dist/providers/togetherai/index.mjs +181 -60
- package/dist/providers/typesafe/index.d.mts +8 -0
- package/dist/providers/typesafe/index.d.ts +8 -0
- package/dist/providers/typesafe/index.js +735 -0
- package/dist/providers/typesafe/index.mjs +733 -0
- package/dist/providers/xai/index.d.mts +3 -3
- package/dist/providers/xai/index.d.ts +3 -3
- package/dist/providers/xai/index.js +181 -60
- package/dist/providers/xai/index.mjs +181 -60
- package/dist/{types-DCFqkJAy.d.ts → types-B0y6VZSQ.d.ts} +1 -1
- package/dist/{types-DHQEMFHA.d.mts → types-BXQMtaCX.d.ts} +17 -3
- package/dist/{types-C3RgRbEC.d.mts → types-BY6BVhFg.d.mts} +1 -1
- package/dist/{types-Dikj3En4.d.ts → types-C7_qVSSd.d.mts} +17 -3
- package/dist/{types-Dg1Bcg1k.d.mts → types-D7lzMMLu.d.mts} +13 -1
- package/dist/{types-Dg1Bcg1k.d.ts → types-D7lzMMLu.d.ts} +13 -1
- package/dist/yourgpt/index.d.mts +1 -1
- package/dist/yourgpt/index.d.ts +1 -1
- package/docs/decisions.md +174 -0
- package/docs/media.md +201 -0
- package/docs/multimodal-and-audio.md +9 -2
- package/package.json +34 -12
- package/dist/audio-BBSwnjo8.d.mts +0 -92
- package/dist/audio-BBSwnjo8.d.ts +0 -92
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { cors } from 'hono/cors';
|
|
3
3
|
|
|
4
|
+
// src/core/openai-responses.ts
|
|
5
|
+
function responseReplayMetadata(metadata) {
|
|
6
|
+
const response = metadata?.openai?.response;
|
|
7
|
+
if (!response) return metadata;
|
|
8
|
+
const output = response.output.map((item) => {
|
|
9
|
+
const fields = ["type", "id", "status"];
|
|
10
|
+
switch (item.type) {
|
|
11
|
+
case "reasoning":
|
|
12
|
+
fields.push("encrypted_content");
|
|
13
|
+
break;
|
|
14
|
+
case "message":
|
|
15
|
+
fields.push("role", "phase");
|
|
16
|
+
break;
|
|
17
|
+
case "function_call":
|
|
18
|
+
fields.push("call_id", "name", "namespace", "arguments");
|
|
19
|
+
break;
|
|
20
|
+
case "tool_search_call":
|
|
21
|
+
fields.push("call_id", "execution", "arguments");
|
|
22
|
+
break;
|
|
23
|
+
case "tool_search_output":
|
|
24
|
+
fields.push("call_id", "tools");
|
|
25
|
+
break;
|
|
26
|
+
case "web_search_call":
|
|
27
|
+
fields.push("action");
|
|
28
|
+
break;
|
|
29
|
+
default:
|
|
30
|
+
return stripItemDiagnostics(item);
|
|
31
|
+
}
|
|
32
|
+
const replay = Object.fromEntries(
|
|
33
|
+
fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
|
|
34
|
+
);
|
|
35
|
+
if (item.type === "reasoning") replay.summary = [];
|
|
36
|
+
if (item.type === "message")
|
|
37
|
+
replay.content = Array.isArray(item.content) ? item.content.flatMap(
|
|
38
|
+
(part) => part?.type === "output_text" && typeof part.text === "string" ? [{ type: "output_text", text: part.text, annotations: [] }] : part?.type === "refusal" && typeof part.refusal === "string" ? [{ type: "refusal", refusal: part.refusal }] : []
|
|
39
|
+
) : [];
|
|
40
|
+
return stripItemDiagnostics(replay);
|
|
41
|
+
});
|
|
42
|
+
return { openai: { response: { output, refusals: [] } } };
|
|
43
|
+
}
|
|
44
|
+
function stripItemDiagnostics(item) {
|
|
45
|
+
const {
|
|
46
|
+
usage: _usage,
|
|
47
|
+
logprobs: _logprobs,
|
|
48
|
+
metadata: _metadata,
|
|
49
|
+
...state
|
|
50
|
+
} = item;
|
|
51
|
+
return state;
|
|
52
|
+
}
|
|
53
|
+
|
|
4
54
|
// src/core/tool-output.ts
|
|
5
55
|
var imageTypes = /* @__PURE__ */ new Set([
|
|
6
56
|
"image/png",
|
|
@@ -100,7 +150,22 @@ function zodToJsonSchema(schema) {
|
|
|
100
150
|
case "ZodString":
|
|
101
151
|
return { type: "string", description };
|
|
102
152
|
case "ZodNumber":
|
|
103
|
-
return {
|
|
153
|
+
return {
|
|
154
|
+
type: def.checks?.some(
|
|
155
|
+
(check) => check.kind === "int"
|
|
156
|
+
) ? "integer" : "number",
|
|
157
|
+
description
|
|
158
|
+
};
|
|
159
|
+
case "ZodNull":
|
|
160
|
+
return { type: "null", description };
|
|
161
|
+
case "ZodAny":
|
|
162
|
+
case "ZodUnknown":
|
|
163
|
+
return { description };
|
|
164
|
+
case "ZodEffects":
|
|
165
|
+
return {
|
|
166
|
+
...zodToJsonSchema(def.schema),
|
|
167
|
+
...description ? { description } : {}
|
|
168
|
+
};
|
|
104
169
|
case "ZodBoolean":
|
|
105
170
|
return { type: "boolean", description };
|
|
106
171
|
case "ZodEnum": {
|
|
@@ -121,10 +186,13 @@ function zodToJsonSchema(schema) {
|
|
|
121
186
|
const properties = {};
|
|
122
187
|
const required = [];
|
|
123
188
|
for (const [key, value] of Object.entries(shapeObj)) {
|
|
124
|
-
properties
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
189
|
+
Object.defineProperty(properties, key, {
|
|
190
|
+
value: zodToJsonSchema(value),
|
|
191
|
+
enumerable: true,
|
|
192
|
+
configurable: true,
|
|
193
|
+
writable: true
|
|
194
|
+
});
|
|
195
|
+
if (!acceptsMissingInput(value)) {
|
|
128
196
|
required.push(key);
|
|
129
197
|
}
|
|
130
198
|
}
|
|
@@ -135,8 +203,13 @@ function zodToJsonSchema(schema) {
|
|
|
135
203
|
description
|
|
136
204
|
};
|
|
137
205
|
}
|
|
138
|
-
case "ZodOptional":
|
|
139
206
|
case "ZodNullable": {
|
|
207
|
+
return {
|
|
208
|
+
anyOf: [zodToJsonSchema(def.innerType), { type: "null" }],
|
|
209
|
+
description
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
case "ZodOptional": {
|
|
140
213
|
const innerType = def.innerType;
|
|
141
214
|
return zodToJsonSchema(innerType);
|
|
142
215
|
}
|
|
@@ -146,6 +219,7 @@ function zodToJsonSchema(schema) {
|
|
|
146
219
|
}
|
|
147
220
|
case "ZodLiteral": {
|
|
148
221
|
const value = def.value;
|
|
222
|
+
if (value === null) return { type: "null", description };
|
|
149
223
|
if (typeof value === "string") {
|
|
150
224
|
return { type: "string", enum: [value], description };
|
|
151
225
|
}
|
|
@@ -169,12 +243,21 @@ function zodToJsonSchema(schema) {
|
|
|
169
243
|
if (stringLiterals.length === options.length) {
|
|
170
244
|
return { type: "string", enum: stringLiterals, description };
|
|
171
245
|
}
|
|
172
|
-
return zodToJsonSchema
|
|
246
|
+
return { anyOf: options.map(zodToJsonSchema), description };
|
|
173
247
|
}
|
|
174
248
|
default:
|
|
175
249
|
return { type: "string", description };
|
|
176
250
|
}
|
|
177
251
|
}
|
|
252
|
+
function acceptsMissingInput(schema) {
|
|
253
|
+
const def = schema._def;
|
|
254
|
+
if (["ZodOptional", "ZodDefault", "ZodAny", "ZodUnknown"].includes(def.typeName))
|
|
255
|
+
return true;
|
|
256
|
+
if (def.typeName === "ZodNullable") return acceptsMissingInput(def.innerType);
|
|
257
|
+
if (def.typeName === "ZodEffects") return acceptsMissingInput(def.schema);
|
|
258
|
+
if (def.typeName === "ZodUnion") return def.options.some(acceptsMissingInput);
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
178
261
|
function formatToolsForOpenAI(tools) {
|
|
179
262
|
return Object.entries(tools).map(([name, toolDef]) => ({
|
|
180
263
|
type: "function",
|
|
@@ -205,6 +288,27 @@ function formatToolsForGoogle(tools) {
|
|
|
205
288
|
}
|
|
206
289
|
|
|
207
290
|
// src/core/provider-error.ts
|
|
291
|
+
function invalidProviderResponse(message) {
|
|
292
|
+
return Object.assign(new Error(message), {
|
|
293
|
+
name: "InvalidProviderResponseError",
|
|
294
|
+
status: 502,
|
|
295
|
+
code: "INVALID_PROVIDER_RESPONSE"
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
function providerErrorEvent(error, code) {
|
|
299
|
+
const details = error ?? {};
|
|
300
|
+
const event = {
|
|
301
|
+
type: "error",
|
|
302
|
+
message: error instanceof Error ? error.message : String(error),
|
|
303
|
+
code,
|
|
304
|
+
...typeof details.status === "number" ? { status: details.status } : {},
|
|
305
|
+
...typeof details.code === "string" ? { providerCode: details.code } : {},
|
|
306
|
+
...typeof details.param === "string" ? { param: details.param } : {},
|
|
307
|
+
...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
|
|
308
|
+
};
|
|
309
|
+
Object.defineProperty(event, "cause", { value: error, enumerable: false });
|
|
310
|
+
return event;
|
|
311
|
+
}
|
|
208
312
|
function throwIfAborted(signal) {
|
|
209
313
|
if (!signal?.aborted) return;
|
|
210
314
|
const error = new Error("The operation was aborted");
|
|
@@ -212,9 +316,42 @@ function throwIfAborted(signal) {
|
|
|
212
316
|
throw error;
|
|
213
317
|
}
|
|
214
318
|
|
|
319
|
+
// src/core/tool-validation.ts
|
|
320
|
+
function parseToolArguments(value) {
|
|
321
|
+
let args = value;
|
|
322
|
+
if (typeof value === "string") {
|
|
323
|
+
try {
|
|
324
|
+
args = JSON.parse(value || "{}");
|
|
325
|
+
} catch {
|
|
326
|
+
throw invalidProviderResponse("Tool arguments are not valid JSON");
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (args === null || typeof args !== "object" || Array.isArray(args))
|
|
330
|
+
throw invalidProviderResponse("Tool arguments must be a JSON object");
|
|
331
|
+
return args;
|
|
332
|
+
}
|
|
333
|
+
function validateToolCalls(calls) {
|
|
334
|
+
const ids = /* @__PURE__ */ new Set();
|
|
335
|
+
for (const call of calls) {
|
|
336
|
+
if (!call || typeof call.id !== "string" || !call.id || typeof call.name !== "string" || !call.name || ids.has(call.id))
|
|
337
|
+
throw invalidProviderResponse(
|
|
338
|
+
"Tool calls have missing or duplicate identities"
|
|
339
|
+
);
|
|
340
|
+
ids.add(call.id);
|
|
341
|
+
if (typeof call.args === "string")
|
|
342
|
+
throw invalidProviderResponse("Parsed tool arguments must be an object");
|
|
343
|
+
parseToolArguments(call.args);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function validateMaxSteps(value) {
|
|
347
|
+
if (!Number.isSafeInteger(value) || value < 1)
|
|
348
|
+
throw new Error("maxSteps must be a positive safe integer");
|
|
349
|
+
}
|
|
350
|
+
|
|
215
351
|
// src/core/generate-text.ts
|
|
216
352
|
async function generateText(params) {
|
|
217
353
|
const { model, tools, maxSteps = 1, signal } = params;
|
|
354
|
+
validateMaxSteps(maxSteps);
|
|
218
355
|
if (params.responseFormat && model.capabilities.supportsJsonMode === false) {
|
|
219
356
|
console.warn(
|
|
220
357
|
`[llm-sdk] ${model.provider}/${model.modelId} does not support structured output (responseFormat); the request will be sent but the provider may ignore it.`
|
|
@@ -238,12 +375,14 @@ async function generateText(params) {
|
|
|
238
375
|
signal
|
|
239
376
|
});
|
|
240
377
|
throwIfAborted(signal);
|
|
378
|
+
const toolCalls = result.toolCalls ?? [];
|
|
379
|
+
validateToolCalls(toolCalls);
|
|
380
|
+
allToolCalls.push(...toolCalls);
|
|
241
381
|
const stepToolResults = [];
|
|
242
|
-
if (
|
|
243
|
-
|
|
244
|
-
for (const call of result.toolCalls) {
|
|
382
|
+
if (toolCalls.length > 0 && tools) {
|
|
383
|
+
for (const call of toolCalls) {
|
|
245
384
|
throwIfAborted(signal);
|
|
246
|
-
const toolDef = tools[call.name];
|
|
385
|
+
const toolDef = Object.prototype.hasOwnProperty.call(tools, call.name) ? tools[call.name] : void 0;
|
|
247
386
|
if (!toolDef) {
|
|
248
387
|
const errorResult = {
|
|
249
388
|
toolCallId: call.id,
|
|
@@ -286,7 +425,8 @@ async function generateText(params) {
|
|
|
286
425
|
}
|
|
287
426
|
steps.push({
|
|
288
427
|
text: result.text,
|
|
289
|
-
|
|
428
|
+
...result.reasoningText !== void 0 ? { reasoningText: result.reasoningText } : {},
|
|
429
|
+
toolCalls,
|
|
290
430
|
toolResults: stepToolResults,
|
|
291
431
|
finishReason: result.finishReason,
|
|
292
432
|
usage: result.usage,
|
|
@@ -295,16 +435,16 @@ async function generateText(params) {
|
|
|
295
435
|
const assistantMessage = {
|
|
296
436
|
role: "assistant",
|
|
297
437
|
content: result.text || null,
|
|
298
|
-
...
|
|
299
|
-
...result.providerMetadata ? { providerMetadata: result.providerMetadata } : {}
|
|
438
|
+
...toolCalls.length ? { toolCalls } : {},
|
|
439
|
+
...result.providerMetadata ? { providerMetadata: responseReplayMetadata(result.providerMetadata) } : {}
|
|
300
440
|
};
|
|
301
441
|
messages = [...messages, assistantMessage];
|
|
302
|
-
if (
|
|
442
|
+
if (toolCalls.length === 0 || !tools) break;
|
|
303
443
|
for (const tr of stepToolResults) {
|
|
304
444
|
const toolMessage = {
|
|
305
445
|
role: "tool",
|
|
306
446
|
toolCallId: tr.toolCallId,
|
|
307
|
-
content: tr.modelOutput ? "[Tool returned content]" : JSON.stringify(tr.result),
|
|
447
|
+
content: tr.modelOutput ? "[Tool returned content]" : JSON.stringify(tr.result ?? null),
|
|
308
448
|
...tr.modelOutput ? { modelOutput: tr.modelOutput } : {}
|
|
309
449
|
};
|
|
310
450
|
messages = [...messages, toolMessage];
|
|
@@ -313,6 +453,7 @@ async function generateText(params) {
|
|
|
313
453
|
const lastStep = steps[steps.length - 1];
|
|
314
454
|
return {
|
|
315
455
|
text: lastStep?.text ?? "",
|
|
456
|
+
...lastStep?.reasoningText !== void 0 ? { reasoningText: lastStep.reasoningText } : {},
|
|
316
457
|
providerMetadata: lastStep?.providerMetadata,
|
|
317
458
|
usage: sumUsage(steps),
|
|
318
459
|
finishReason: lastStep?.finishReason ?? "stop",
|
|
@@ -359,9 +500,250 @@ function sumUsage(steps) {
|
|
|
359
500
|
);
|
|
360
501
|
}
|
|
361
502
|
|
|
503
|
+
// src/core/image.ts
|
|
504
|
+
async function generateImage({
|
|
505
|
+
model,
|
|
506
|
+
...options
|
|
507
|
+
}) {
|
|
508
|
+
options.signal?.throwIfAborted();
|
|
509
|
+
if (typeof options.prompt !== "string" || !options.prompt.trim())
|
|
510
|
+
throw new MediaAPIError("Image prompt must not be empty", "invalid_input");
|
|
511
|
+
const result = await model.doGenerate(options);
|
|
512
|
+
options.signal?.throwIfAborted();
|
|
513
|
+
if (!result.images?.length || result.images.some(
|
|
514
|
+
(image) => !(image.uint8Array instanceof Uint8Array) || !image.uint8Array.length
|
|
515
|
+
))
|
|
516
|
+
throw new MediaAPIError(
|
|
517
|
+
"Image provider returned empty images",
|
|
518
|
+
"invalid_response"
|
|
519
|
+
);
|
|
520
|
+
return result;
|
|
521
|
+
}
|
|
522
|
+
var marker = /* @__PURE__ */ Symbol.for("@yourgpt/llm-sdk/MediaAPIError");
|
|
523
|
+
var _a;
|
|
524
|
+
var MediaAPIError = class extends Error {
|
|
525
|
+
constructor(message, code, status, requestId) {
|
|
526
|
+
super(message);
|
|
527
|
+
this.code = code;
|
|
528
|
+
this.status = status;
|
|
529
|
+
this.requestId = requestId;
|
|
530
|
+
this[_a] = true;
|
|
531
|
+
this.name = "MediaAPIError";
|
|
532
|
+
}
|
|
533
|
+
static [(_a = marker, Symbol.hasInstance)](value) {
|
|
534
|
+
return !!value && typeof value === "object" && value[marker] === true;
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
// src/core/decision-validation.ts
|
|
539
|
+
function decisionInputError(message) {
|
|
540
|
+
throw new DecisionAPIError(message, "invalid_input");
|
|
541
|
+
}
|
|
542
|
+
function decisionResponseError(message) {
|
|
543
|
+
throw new DecisionAPIError(message, "invalid_response");
|
|
544
|
+
}
|
|
545
|
+
function isDecisionRecord(value) {
|
|
546
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
547
|
+
return false;
|
|
548
|
+
const proto = Object.getPrototypeOf(value);
|
|
549
|
+
return proto === Object.prototype || proto === null;
|
|
550
|
+
}
|
|
551
|
+
function json(value, seen = /* @__PURE__ */ new Set(), depth = 0) {
|
|
552
|
+
if (depth > 64) return false;
|
|
553
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
554
|
+
return true;
|
|
555
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
556
|
+
if (typeof value !== "object" || !Array.isArray(value) && !isDecisionRecord(value) || seen.has(value))
|
|
557
|
+
return false;
|
|
558
|
+
seen.add(value);
|
|
559
|
+
const valid = Object.getOwnPropertySymbols(value).length === 0 && (Array.isArray(value) ? Array.from(value) : Object.values(value)).every(
|
|
560
|
+
(item) => json(item, seen, depth + 1)
|
|
561
|
+
);
|
|
562
|
+
seen.delete(value);
|
|
563
|
+
return valid;
|
|
564
|
+
}
|
|
565
|
+
function input(value) {
|
|
566
|
+
return (typeof value === "string" || Array.isArray(value) || isDecisionRecord(value)) && json(value);
|
|
567
|
+
}
|
|
568
|
+
function assertDecisionKeys(value, allowed, label) {
|
|
569
|
+
if (Object.keys(value).some((key) => !allowed.includes(key)))
|
|
570
|
+
decisionInputError(`${label} contains an unsupported field`);
|
|
571
|
+
}
|
|
572
|
+
function validateDecisionInput(options) {
|
|
573
|
+
if (!isDecisionRecord(options))
|
|
574
|
+
decisionInputError("Decisions options must be an object");
|
|
575
|
+
assertDecisionKeys(
|
|
576
|
+
options,
|
|
577
|
+
["state", "questions", "images", "signal", "timeoutMs", "providerOptions"],
|
|
578
|
+
"Decisions options"
|
|
579
|
+
);
|
|
580
|
+
if (!input(options.state))
|
|
581
|
+
decisionInputError(
|
|
582
|
+
"state must be finite, acyclic JSON text, object, or array (maximum depth 64)"
|
|
583
|
+
);
|
|
584
|
+
if (!isDecisionRecord(options.questions) || Object.keys(options.questions).length === 0)
|
|
585
|
+
decisionInputError("questions must be a nonempty map");
|
|
586
|
+
for (const [id, question] of Object.entries(options.questions)) {
|
|
587
|
+
if (!id.length || !isDecisionRecord(question) || !input(question.instructions))
|
|
588
|
+
decisionInputError(
|
|
589
|
+
"Every question needs a nonempty ID and JSON-compatible instructions"
|
|
590
|
+
);
|
|
591
|
+
assertDecisionKeys(
|
|
592
|
+
question,
|
|
593
|
+
["type", "instructions", "criteria"],
|
|
594
|
+
"Question"
|
|
595
|
+
);
|
|
596
|
+
if (question.type === "boolean") {
|
|
597
|
+
if (question.criteria !== void 0 && (!isDecisionRecord(question.criteria) || Object.entries(question.criteria).some(
|
|
598
|
+
([key, value]) => !["true", "false"].includes(key) || !input(value)
|
|
599
|
+
)))
|
|
600
|
+
decisionInputError("Boolean criteria may describe only true and false");
|
|
601
|
+
} else if (question.type === "choice") {
|
|
602
|
+
if (!isDecisionRecord(question.criteria) || Object.keys(question.criteria).length < 2 || Object.keys(question.criteria).length > 255 || Object.entries(question.criteria).some(
|
|
603
|
+
([key, value]) => !key.length || value !== null && !input(value)
|
|
604
|
+
))
|
|
605
|
+
decisionInputError(
|
|
606
|
+
"Choice criteria require 2\u2013255 named options with JSON descriptions or null"
|
|
607
|
+
);
|
|
608
|
+
} else if (question.type === "score") {
|
|
609
|
+
if (!Array.isArray(question.criteria) || question.criteria.length < 2 || !Array.from(question.criteria).every(input))
|
|
610
|
+
decisionInputError(
|
|
611
|
+
"Score criteria require at least two ordered JSON descriptions"
|
|
612
|
+
);
|
|
613
|
+
} else
|
|
614
|
+
decisionInputError("Question type must be boolean, choice, or score");
|
|
615
|
+
}
|
|
616
|
+
if (options.timeoutMs !== void 0 && (!Number.isInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 2147483647))
|
|
617
|
+
decisionInputError("timeoutMs must be a positive 32-bit integer");
|
|
618
|
+
if (options.providerOptions !== void 0 && (!isDecisionRecord(options.providerOptions) || !json(options.providerOptions)))
|
|
619
|
+
decisionInputError("providerOptions must be a JSON object");
|
|
620
|
+
if (options.images !== void 0 && (!Array.isArray(options.images) || !Array.from(options.images).every(
|
|
621
|
+
(image) => isDecisionRecord(image) && image.data instanceof Uint8Array
|
|
622
|
+
)))
|
|
623
|
+
decisionInputError(
|
|
624
|
+
"Decision images must contain encoded bytes; hosted image URLs are unsupported"
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
function probability(value) {
|
|
628
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
|
|
629
|
+
}
|
|
630
|
+
function exactKeys(value, keys) {
|
|
631
|
+
return Object.keys(value).length === keys.length && keys.every((key) => Object.prototype.hasOwnProperty.call(value, key));
|
|
632
|
+
}
|
|
633
|
+
function validateDecisionResult(questions, result) {
|
|
634
|
+
if (!isDecisionRecord(result) || !isDecisionRecord(result.answers) || !exactKeys(result.answers, Object.keys(questions)))
|
|
635
|
+
decisionResponseError(
|
|
636
|
+
"Decisions must return exactly one answer per question"
|
|
637
|
+
);
|
|
638
|
+
const rounding = result.rounding;
|
|
639
|
+
let pError = 0, sError = 0;
|
|
640
|
+
if (rounding !== void 0) {
|
|
641
|
+
if (!isDecisionRecord(rounding) || ![rounding.probabilityDecimals, rounding.scoreDecimals].every(
|
|
642
|
+
(v) => typeof v === "number" && Number.isInteger(v) && v >= 0 && v <= 15
|
|
643
|
+
))
|
|
644
|
+
decisionResponseError("Invalid decision rounding precision");
|
|
645
|
+
pError = 0.5 * 10 ** -rounding.probabilityDecimals;
|
|
646
|
+
sError = 0.5 * 10 ** -rounding.scoreDecimals;
|
|
647
|
+
}
|
|
648
|
+
const epsilon = 1e-6;
|
|
649
|
+
for (const [id, question] of Object.entries(questions)) {
|
|
650
|
+
const answer = result.answers[id];
|
|
651
|
+
if (!isDecisionRecord(answer))
|
|
652
|
+
decisionResponseError("Invalid decision answer");
|
|
653
|
+
if (answer.type === "refusal") continue;
|
|
654
|
+
if (answer.type !== question.type)
|
|
655
|
+
decisionResponseError("Decision answer type does not match its question");
|
|
656
|
+
if (answer.confidence !== void 0 && !probability(answer.confidence))
|
|
657
|
+
decisionResponseError(
|
|
658
|
+
"Confidence must be finite and between zero and one"
|
|
659
|
+
);
|
|
660
|
+
if (question.type === "boolean") {
|
|
661
|
+
if (!probability(answer.probability))
|
|
662
|
+
decisionResponseError(
|
|
663
|
+
"Boolean probability must be between zero and one"
|
|
664
|
+
);
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
const keys = question.type === "choice" ? Object.keys(question.criteria) : question.criteria.map((_, index) => String(index));
|
|
668
|
+
if (question.type === "choice" && (typeof answer.choice !== "string" || !keys.includes(answer.choice)))
|
|
669
|
+
decisionResponseError("Decision selected an unknown choice");
|
|
670
|
+
if (question.type === "score" && (typeof answer.score !== "number" || !Number.isFinite(answer.score) || answer.score < 0 || answer.score > keys.length - 1))
|
|
671
|
+
decisionResponseError("Decision score is outside its ordered levels");
|
|
672
|
+
if (answer.probabilities === void 0) continue;
|
|
673
|
+
const distribution = answer.probabilities;
|
|
674
|
+
if (!isDecisionRecord(distribution) || !exactKeys(distribution, keys) || !Object.values(distribution).every(probability))
|
|
675
|
+
decisionResponseError(
|
|
676
|
+
"Decision distribution must contain every option exactly once with finite probabilities"
|
|
677
|
+
);
|
|
678
|
+
const values = Object.values(distribution);
|
|
679
|
+
if (Math.abs(values.reduce((a, b) => a + b, 0) - 1) > epsilon + keys.length * pError)
|
|
680
|
+
decisionResponseError("Decision probabilities do not sum to one");
|
|
681
|
+
if (question.type === "choice") {
|
|
682
|
+
if (values.some(
|
|
683
|
+
(v) => v > distribution[answer.choice] + epsilon + 2 * pError
|
|
684
|
+
))
|
|
685
|
+
decisionResponseError(
|
|
686
|
+
"Decision choice is not a highest-probability option"
|
|
687
|
+
);
|
|
688
|
+
} else {
|
|
689
|
+
const mean = keys.reduce(
|
|
690
|
+
(sum, key) => sum + Number(key) * distribution[key],
|
|
691
|
+
0
|
|
692
|
+
);
|
|
693
|
+
const tolerance = epsilon + sError + pError * keys.reduce((sum, key) => sum + Number(key), 0);
|
|
694
|
+
if (Math.abs(answer.score - mean) > tolerance)
|
|
695
|
+
decisionResponseError(
|
|
696
|
+
"Decision score does not match its probability-weighted levels"
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/core/decisions.ts
|
|
703
|
+
var decisionErrorMarker = /* @__PURE__ */ Symbol.for("yourgpt.llm-sdk.DecisionAPIError");
|
|
704
|
+
var _a2, _b;
|
|
705
|
+
var DecisionAPIError = class extends (_b = Error, _a2 = decisionErrorMarker, _b) {
|
|
706
|
+
constructor(message, code, status, requestId) {
|
|
707
|
+
super(message);
|
|
708
|
+
this.code = code;
|
|
709
|
+
this.status = status;
|
|
710
|
+
this.requestId = requestId;
|
|
711
|
+
this.name = "DecisionAPIError";
|
|
712
|
+
this[_a2] = true;
|
|
713
|
+
}
|
|
714
|
+
/** Works across CJS/ESM and separately bundled provider entry points. */
|
|
715
|
+
static isInstance(error) {
|
|
716
|
+
return typeof error === "object" && error !== null && /* @__PURE__ */ Symbol.for("yourgpt.llm-sdk.DecisionAPIError") in error;
|
|
717
|
+
}
|
|
718
|
+
/** Advisory only: this SDK does not retry Decisions automatically. */
|
|
719
|
+
get retryable() {
|
|
720
|
+
return this.code === "network_error" || this.code === "http_error" && (this.status === 408 || this.status === 429 || this.status != null && this.status >= 500);
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
async function experimental_decide(options) {
|
|
724
|
+
const { model, ...request } = options;
|
|
725
|
+
validateDecisionInput(request);
|
|
726
|
+
request.signal?.throwIfAborted();
|
|
727
|
+
const result = await model.doDecide(request);
|
|
728
|
+
request.signal?.throwIfAborted();
|
|
729
|
+
validateDecisionResult(request.questions, result);
|
|
730
|
+
return result;
|
|
731
|
+
}
|
|
732
|
+
|
|
362
733
|
// src/core/stream-text.ts
|
|
363
734
|
async function streamText(params) {
|
|
364
|
-
const { model, tools, maxSteps = 1, signal } = params;
|
|
735
|
+
const { model, tools, maxSteps = 1, signal: callerSignal } = params;
|
|
736
|
+
validateMaxSteps(maxSteps);
|
|
737
|
+
const controller = new AbortController();
|
|
738
|
+
const signal = controller.signal;
|
|
739
|
+
const relayAbort = () => controller.abort(callerSignal?.reason);
|
|
740
|
+
if (callerSignal?.aborted) relayAbort();
|
|
741
|
+
else callerSignal?.addEventListener("abort", relayAbort, { once: true });
|
|
742
|
+
const cleanup = () => callerSignal?.removeEventListener("abort", relayAbort);
|
|
743
|
+
const cancel = () => {
|
|
744
|
+
controller.abort();
|
|
745
|
+
cleanup();
|
|
746
|
+
};
|
|
365
747
|
if (params.responseFormat && model.capabilities.supportsJsonMode === false) {
|
|
366
748
|
console.warn(
|
|
367
749
|
`[llm-sdk] ${model.provider}/${model.modelId} does not support structured output (responseFormat); the request will be sent but the provider may ignore it.`
|
|
@@ -388,6 +770,7 @@ async function streamText(params) {
|
|
|
388
770
|
let stepProviderMetadata;
|
|
389
771
|
const toolCalls = [];
|
|
390
772
|
let stepFinishReason = "stop";
|
|
773
|
+
let receivedFinish = false;
|
|
391
774
|
try {
|
|
392
775
|
for await (const chunk of model.doStream({
|
|
393
776
|
messages,
|
|
@@ -401,6 +784,9 @@ async function streamText(params) {
|
|
|
401
784
|
})) {
|
|
402
785
|
throwIfAborted(signal);
|
|
403
786
|
switch (chunk.type) {
|
|
787
|
+
case "reasoning-delta":
|
|
788
|
+
yield chunk;
|
|
789
|
+
break;
|
|
404
790
|
case "text-delta":
|
|
405
791
|
stepText += chunk.text;
|
|
406
792
|
fullText += chunk.text;
|
|
@@ -414,6 +800,11 @@ async function streamText(params) {
|
|
|
414
800
|
};
|
|
415
801
|
break;
|
|
416
802
|
case "finish":
|
|
803
|
+
if (receivedFinish)
|
|
804
|
+
throw invalidProviderResponse(
|
|
805
|
+
"Model stream returned multiple finish events"
|
|
806
|
+
);
|
|
807
|
+
receivedFinish = true;
|
|
417
808
|
stepProviderMetadata = chunk.providerMetadata;
|
|
418
809
|
finalProviderMetadata = chunk.providerMetadata;
|
|
419
810
|
stepFinishReason = chunk.finishReason;
|
|
@@ -431,6 +822,12 @@ async function streamText(params) {
|
|
|
431
822
|
return;
|
|
432
823
|
}
|
|
433
824
|
}
|
|
825
|
+
throwIfAborted(signal);
|
|
826
|
+
if (!receivedFinish)
|
|
827
|
+
throw invalidProviderResponse(
|
|
828
|
+
"Model stream ended without a finish event"
|
|
829
|
+
);
|
|
830
|
+
validateToolCalls(toolCalls);
|
|
434
831
|
} catch (error) {
|
|
435
832
|
yield {
|
|
436
833
|
type: "error",
|
|
@@ -450,13 +847,13 @@ async function streamText(params) {
|
|
|
450
847
|
role: "assistant",
|
|
451
848
|
content: stepText || null,
|
|
452
849
|
...toolCalls.length ? { toolCalls } : {},
|
|
453
|
-
...stepProviderMetadata ? { providerMetadata: stepProviderMetadata } : {}
|
|
850
|
+
...stepProviderMetadata ? { providerMetadata: responseReplayMetadata(stepProviderMetadata) } : {}
|
|
454
851
|
}
|
|
455
852
|
];
|
|
456
853
|
if (toolCalls.length === 0 || !tools) break;
|
|
457
854
|
for (const call of toolCalls) {
|
|
458
855
|
throwIfAborted(signal);
|
|
459
|
-
const toolDef = tools[call.name];
|
|
856
|
+
const toolDef = Object.prototype.hasOwnProperty.call(tools, call.name) ? tools[call.name] : void 0;
|
|
460
857
|
if (!toolDef) {
|
|
461
858
|
const errorResult = { error: `Tool not found: ${call.name}` };
|
|
462
859
|
yield {
|
|
@@ -497,7 +894,7 @@ async function streamText(params) {
|
|
|
497
894
|
{
|
|
498
895
|
role: "tool",
|
|
499
896
|
toolCallId: call.id,
|
|
500
|
-
content: modelOutput ? "[Tool returned content]" : JSON.stringify(result),
|
|
897
|
+
content: modelOutput ? "[Tool returned content]" : JSON.stringify(result ?? null),
|
|
501
898
|
...modelOutput ? { modelOutput } : {}
|
|
502
899
|
}
|
|
503
900
|
];
|
|
@@ -539,11 +936,17 @@ async function streamText(params) {
|
|
|
539
936
|
pending = (async () => {
|
|
540
937
|
try {
|
|
541
938
|
const next = await source.next();
|
|
542
|
-
if (next.done)
|
|
543
|
-
|
|
939
|
+
if (next.done) {
|
|
940
|
+
finished = true;
|
|
941
|
+
cleanup();
|
|
942
|
+
} else {
|
|
943
|
+
parts.push(next.value);
|
|
944
|
+
if (next.value.type === "error") cleanup();
|
|
945
|
+
}
|
|
544
946
|
} catch (error) {
|
|
545
947
|
failure = error;
|
|
546
948
|
finished = true;
|
|
949
|
+
cleanup();
|
|
547
950
|
}
|
|
548
951
|
})();
|
|
549
952
|
}
|
|
@@ -594,7 +997,7 @@ async function streamText(params) {
|
|
|
594
997
|
return consumeStream().then(() => finalFinishReason);
|
|
595
998
|
},
|
|
596
999
|
toTextStreamResponse(options) {
|
|
597
|
-
const stream = createTextStreamReadable(createTextStream());
|
|
1000
|
+
const stream = createTextStreamReadable(createTextStream(), cancel);
|
|
598
1001
|
return new Response(stream, {
|
|
599
1002
|
status: options?.status ?? 200,
|
|
600
1003
|
headers: {
|
|
@@ -606,7 +1009,7 @@ async function streamText(params) {
|
|
|
606
1009
|
});
|
|
607
1010
|
},
|
|
608
1011
|
toDataStreamResponse(options) {
|
|
609
|
-
const stream = createDataStreamReadable(sharedStream());
|
|
1012
|
+
const stream = createDataStreamReadable(sharedStream(), cancel);
|
|
610
1013
|
return new Response(stream, {
|
|
611
1014
|
status: options?.status ?? 200,
|
|
612
1015
|
headers: {
|
|
@@ -643,35 +1046,51 @@ function formatToolsForProvider2(tools, provider) {
|
|
|
643
1046
|
return formatToolsForOpenAI(tools);
|
|
644
1047
|
}
|
|
645
1048
|
}
|
|
646
|
-
function createTextStreamReadable(textStream) {
|
|
1049
|
+
function createTextStreamReadable(textStream, abort) {
|
|
647
1050
|
const encoder = new TextEncoder();
|
|
1051
|
+
const iterator = textStream[Symbol.asyncIterator]();
|
|
1052
|
+
let cancelled = false;
|
|
648
1053
|
return new ReadableStream({
|
|
649
|
-
async
|
|
1054
|
+
async pull(controller) {
|
|
650
1055
|
try {
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
controller.
|
|
1056
|
+
const next = await iterator.next();
|
|
1057
|
+
if (cancelled) return;
|
|
1058
|
+
if (next.done) controller.close();
|
|
1059
|
+
else controller.enqueue(encoder.encode(next.value));
|
|
655
1060
|
} catch (error) {
|
|
656
|
-
controller.error(error);
|
|
1061
|
+
if (!cancelled) controller.error(error);
|
|
657
1062
|
}
|
|
1063
|
+
},
|
|
1064
|
+
cancel() {
|
|
1065
|
+
cancelled = true;
|
|
1066
|
+
abort();
|
|
1067
|
+
void iterator.return?.().catch(() => {
|
|
1068
|
+
});
|
|
658
1069
|
}
|
|
659
1070
|
});
|
|
660
1071
|
}
|
|
661
|
-
function createDataStreamReadable(fullStream) {
|
|
1072
|
+
function createDataStreamReadable(fullStream, abort) {
|
|
662
1073
|
const encoder = new TextEncoder();
|
|
1074
|
+
const iterator = fullStream[Symbol.asyncIterator]();
|
|
1075
|
+
let cancelled = false;
|
|
663
1076
|
return new ReadableStream({
|
|
664
|
-
async
|
|
1077
|
+
async pull(controller) {
|
|
665
1078
|
try {
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
1079
|
+
const next = await iterator.next();
|
|
1080
|
+
if (cancelled) return;
|
|
1081
|
+
if (next.done) {
|
|
1082
|
+
controller.enqueue(encoder.encode("data: [DONE]\n\n"));
|
|
1083
|
+
controller.close();
|
|
1084
|
+
return;
|
|
671
1085
|
}
|
|
672
|
-
|
|
673
|
-
controller.
|
|
1086
|
+
if (next.value.type === "error") throw next.value.error;
|
|
1087
|
+
controller.enqueue(
|
|
1088
|
+
encoder.encode(`data: ${JSON.stringify(next.value)}
|
|
1089
|
+
|
|
1090
|
+
`)
|
|
1091
|
+
);
|
|
674
1092
|
} catch (error) {
|
|
1093
|
+
if (cancelled) return;
|
|
675
1094
|
const errorData = JSON.stringify({
|
|
676
1095
|
type: "error",
|
|
677
1096
|
error: error instanceof Error ? error.message : String(error)
|
|
@@ -680,7 +1099,15 @@ function createDataStreamReadable(fullStream) {
|
|
|
680
1099
|
|
|
681
1100
|
`));
|
|
682
1101
|
controller.close();
|
|
1102
|
+
void iterator.return?.().catch(() => {
|
|
1103
|
+
});
|
|
683
1104
|
}
|
|
1105
|
+
},
|
|
1106
|
+
cancel() {
|
|
1107
|
+
cancelled = true;
|
|
1108
|
+
abort();
|
|
1109
|
+
void iterator.return?.().catch(() => {
|
|
1110
|
+
});
|
|
684
1111
|
}
|
|
685
1112
|
});
|
|
686
1113
|
}
|
|
@@ -782,17 +1209,32 @@ function createTextStreamHeaders() {
|
|
|
782
1209
|
};
|
|
783
1210
|
}
|
|
784
1211
|
function formatSSEData(event) {
|
|
785
|
-
|
|
1212
|
+
const safeEvent = { ...event };
|
|
1213
|
+
if ("providerMetadata" in safeEvent)
|
|
1214
|
+
safeEvent.providerMetadata = responseReplayMetadata(
|
|
1215
|
+
safeEvent.providerMetadata
|
|
1216
|
+
);
|
|
1217
|
+
if (safeEvent.type === "done" && safeEvent.messages)
|
|
1218
|
+
safeEvent.messages = safeEvent.messages.map((message) => ({
|
|
1219
|
+
...message,
|
|
1220
|
+
...message.providerMetadata ? { providerMetadata: responseReplayMetadata(message.providerMetadata) } : {}
|
|
1221
|
+
}));
|
|
1222
|
+
return `data: ${JSON.stringify(safeEvent)}
|
|
786
1223
|
|
|
787
1224
|
`;
|
|
788
1225
|
}
|
|
789
|
-
function createEventStream(generator) {
|
|
1226
|
+
function createEventStream(generator, options) {
|
|
790
1227
|
const encoder = new TextEncoder();
|
|
791
1228
|
return new ReadableStream({
|
|
792
1229
|
async start(controller) {
|
|
793
1230
|
try {
|
|
794
1231
|
for await (const event of generator) {
|
|
795
|
-
|
|
1232
|
+
let clientEvent = event;
|
|
1233
|
+
if (event.type === "done" && !options?.includeUsage) {
|
|
1234
|
+
const { usage: _usage, ...withoutUsage } = event;
|
|
1235
|
+
clientEvent = withoutUsage;
|
|
1236
|
+
}
|
|
1237
|
+
const data = formatSSEData(clientEvent);
|
|
796
1238
|
controller.enqueue(encoder.encode(data));
|
|
797
1239
|
}
|
|
798
1240
|
} catch (error) {
|
|
@@ -933,7 +1375,9 @@ var StreamResult = class {
|
|
|
933
1375
|
...createSSEHeaders(),
|
|
934
1376
|
...options?.headers
|
|
935
1377
|
};
|
|
936
|
-
return new Response(createEventStream(this.generator), {
|
|
1378
|
+
return new Response(createEventStream(this.generator, options), {
|
|
1379
|
+
headers
|
|
1380
|
+
});
|
|
937
1381
|
}
|
|
938
1382
|
/**
|
|
939
1383
|
* Alias for toResponse() - returns SSE Response
|
|
@@ -1199,6 +1643,9 @@ var StreamResult = class {
|
|
|
1199
1643
|
}
|
|
1200
1644
|
break;
|
|
1201
1645
|
}
|
|
1646
|
+
case "error":
|
|
1647
|
+
collected.error = { message: event.message, code: event.code };
|
|
1648
|
+
break;
|
|
1202
1649
|
case "done":
|
|
1203
1650
|
if (event.messages) {
|
|
1204
1651
|
collected.messages.push(...event.messages);
|
|
@@ -1665,7 +2112,7 @@ function buildToolResultForAI(tool2, result, args) {
|
|
|
1665
2112
|
return aiContext ?? `[Tool ${tool2?.name ?? "unknown"} executed successfully]`;
|
|
1666
2113
|
case "full":
|
|
1667
2114
|
default:
|
|
1668
|
-
const fullData = JSON.stringify(result);
|
|
2115
|
+
const fullData = JSON.stringify(result ?? null);
|
|
1669
2116
|
return aiContext ? `${aiContext}
|
|
1670
2117
|
|
|
1671
2118
|
Full data: ${fullData}` : fullData;
|
|
@@ -2345,7 +2792,8 @@ var Runtime = class {
|
|
|
2345
2792
|
const systemPrompt = request.systemPrompt || this.config.systemPrompt || "";
|
|
2346
2793
|
let accumulatedText = "";
|
|
2347
2794
|
const toolCalls = [];
|
|
2348
|
-
|
|
2795
|
+
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
2796
|
+
const endedToolIds = /* @__PURE__ */ new Set();
|
|
2349
2797
|
const serverToolResults = [];
|
|
2350
2798
|
const toolContextData = "toolContext" in this.config ? this.config.toolContext : void 0;
|
|
2351
2799
|
let adapterProviderMetadata;
|
|
@@ -2370,142 +2818,151 @@ var Runtime = class {
|
|
|
2370
2818
|
debug
|
|
2371
2819
|
};
|
|
2372
2820
|
const stream = this.adapter.stream(completionRequest);
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2821
|
+
try {
|
|
2822
|
+
for await (const event of stream) {
|
|
2823
|
+
throwIfAborted(signal);
|
|
2824
|
+
switch (event.type) {
|
|
2825
|
+
case "message:start":
|
|
2826
|
+
yield event;
|
|
2827
|
+
break;
|
|
2828
|
+
case "message:end":
|
|
2829
|
+
yield {
|
|
2830
|
+
...event,
|
|
2831
|
+
providerMetadata: responseReplayMetadata(event.providerMetadata)
|
|
2832
|
+
};
|
|
2833
|
+
break;
|
|
2834
|
+
case "message:delta":
|
|
2835
|
+
accumulatedText += event.content;
|
|
2836
|
+
yield event;
|
|
2837
|
+
break;
|
|
2838
|
+
case "action:start":
|
|
2839
|
+
if (!event.id || !event.name || pendingToolCalls.has(event.id) || toolCalls.some((call) => call.id === event.id))
|
|
2840
|
+
throw invalidProviderResponse(
|
|
2841
|
+
"Tool calls have missing or duplicate identities"
|
|
2842
|
+
);
|
|
2843
|
+
pendingToolCalls.set(event.id, {
|
|
2844
|
+
id: event.id,
|
|
2845
|
+
name: event.name,
|
|
2846
|
+
...event.extra_content ? { extra_content: event.extra_content } : {}
|
|
2847
|
+
});
|
|
2848
|
+
if (debug) {
|
|
2849
|
+
console.log(`[Copilot SDK] Tool call started: ${event.name}`);
|
|
2850
|
+
}
|
|
2851
|
+
yield event;
|
|
2852
|
+
break;
|
|
2853
|
+
case "action:args": {
|
|
2854
|
+
const current = pendingToolCalls.get(event.id);
|
|
2855
|
+
if (!current)
|
|
2856
|
+
throw invalidProviderResponse(
|
|
2857
|
+
"Tool arguments have no matching call"
|
|
2858
|
+
);
|
|
2859
|
+
toolCalls.push({
|
|
2860
|
+
...current,
|
|
2861
|
+
args: parseToolArguments(event.args)
|
|
2862
|
+
});
|
|
2863
|
+
pendingToolCalls.delete(event.id);
|
|
2864
|
+
yield event;
|
|
2865
|
+
break;
|
|
2394
2866
|
}
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2867
|
+
case "action:end": {
|
|
2868
|
+
const tc = toolCalls.find((t) => t.id === event.id);
|
|
2869
|
+
const eventName = event.name;
|
|
2870
|
+
if (!tc || eventName && eventName !== tc.name || endedToolIds.has(event.id))
|
|
2871
|
+
throw invalidProviderResponse(
|
|
2872
|
+
"Tool completion has no matching unexecuted call"
|
|
2873
|
+
);
|
|
2874
|
+
endedToolIds.add(event.id);
|
|
2875
|
+
const toolName = tc.name;
|
|
2876
|
+
const tool2 = toolName ? selectedToolMap.get(toolName) : void 0;
|
|
2877
|
+
if (tool2?.location === "server" && tool2.handler) {
|
|
2401
2878
|
if (debug) {
|
|
2402
2879
|
console.log(
|
|
2403
|
-
`[Copilot SDK]
|
|
2404
|
-
parsedArgs
|
|
2880
|
+
`[Copilot SDK] Executing server-side tool: ${toolName}`
|
|
2405
2881
|
);
|
|
2406
2882
|
}
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
console.error(
|
|
2415
|
-
"[Copilot SDK] Failed to parse tool args:",
|
|
2416
|
-
event.args,
|
|
2417
|
-
e
|
|
2883
|
+
const args = tc.args;
|
|
2884
|
+
const toolContext = buildToolContext(
|
|
2885
|
+
event.id,
|
|
2886
|
+
signal,
|
|
2887
|
+
request.threadId,
|
|
2888
|
+
_httpRequest,
|
|
2889
|
+
toolContextData
|
|
2418
2890
|
);
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2891
|
+
try {
|
|
2892
|
+
throwIfAborted(signal);
|
|
2893
|
+
const result = await tool2.handler(args, toolContext);
|
|
2894
|
+
throwIfAborted(signal);
|
|
2895
|
+
const modelOutput = resolveToolOutput(
|
|
2896
|
+
result,
|
|
2897
|
+
tool2.toModelOutput?.(result)
|
|
2898
|
+
);
|
|
2899
|
+
serverToolResults.push({
|
|
2900
|
+
id: event.id,
|
|
2901
|
+
name: toolName,
|
|
2902
|
+
args,
|
|
2903
|
+
result,
|
|
2904
|
+
modelOutput,
|
|
2905
|
+
tool: tool2
|
|
2906
|
+
});
|
|
2907
|
+
yield {
|
|
2908
|
+
type: "action:end",
|
|
2909
|
+
id: event.id,
|
|
2910
|
+
name: toolName,
|
|
2911
|
+
result,
|
|
2912
|
+
modelOutput
|
|
2913
|
+
};
|
|
2914
|
+
} catch (error) {
|
|
2915
|
+
throwIfAborted(signal);
|
|
2916
|
+
const errorResult = {
|
|
2917
|
+
success: false,
|
|
2918
|
+
error: error instanceof Error ? error.message : "Tool execution failed"
|
|
2919
|
+
};
|
|
2920
|
+
serverToolResults.push({
|
|
2921
|
+
id: event.id,
|
|
2922
|
+
name: toolName,
|
|
2923
|
+
args,
|
|
2924
|
+
result: errorResult,
|
|
2925
|
+
tool: tool2
|
|
2926
|
+
});
|
|
2927
|
+
yield {
|
|
2928
|
+
type: "action:end",
|
|
2929
|
+
id: event.id,
|
|
2930
|
+
name: toolName,
|
|
2931
|
+
error: error instanceof Error ? error.message : "Tool execution failed"
|
|
2932
|
+
};
|
|
2933
|
+
}
|
|
2934
|
+
} else {
|
|
2935
|
+
yield event;
|
|
2425
2936
|
}
|
|
2426
|
-
|
|
2937
|
+
break;
|
|
2427
2938
|
}
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
}
|
|
2439
|
-
const tc = toolCalls.find((t) => t.id === event.id);
|
|
2440
|
-
const args = tc?.args ?? {};
|
|
2441
|
-
const toolContext = buildToolContext(
|
|
2442
|
-
event.id,
|
|
2443
|
-
signal,
|
|
2444
|
-
request.threadId,
|
|
2445
|
-
_httpRequest,
|
|
2446
|
-
toolContextData
|
|
2939
|
+
case "citation":
|
|
2940
|
+
yield event;
|
|
2941
|
+
break;
|
|
2942
|
+
case "error":
|
|
2943
|
+
yield event;
|
|
2944
|
+
return;
|
|
2945
|
+
// Exit on error
|
|
2946
|
+
case "done":
|
|
2947
|
+
adapterProviderMetadata = responseReplayMetadata(
|
|
2948
|
+
event.providerMetadata
|
|
2447
2949
|
);
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
const modelOutput = resolveToolOutput(
|
|
2451
|
-
result,
|
|
2452
|
-
tool2.toModelOutput?.(result)
|
|
2453
|
-
);
|
|
2454
|
-
serverToolResults.push({
|
|
2455
|
-
id: event.id,
|
|
2456
|
-
name: toolName,
|
|
2457
|
-
args,
|
|
2458
|
-
result,
|
|
2459
|
-
modelOutput,
|
|
2460
|
-
tool: tool2
|
|
2461
|
-
});
|
|
2462
|
-
yield {
|
|
2463
|
-
type: "action:end",
|
|
2464
|
-
id: event.id,
|
|
2465
|
-
name: toolName,
|
|
2466
|
-
result,
|
|
2467
|
-
modelOutput
|
|
2468
|
-
};
|
|
2469
|
-
} catch (error) {
|
|
2470
|
-
const errorResult = {
|
|
2471
|
-
success: false,
|
|
2472
|
-
error: error instanceof Error ? error.message : "Tool execution failed"
|
|
2473
|
-
};
|
|
2474
|
-
serverToolResults.push({
|
|
2475
|
-
id: event.id,
|
|
2476
|
-
name: toolName,
|
|
2477
|
-
args,
|
|
2478
|
-
result: errorResult,
|
|
2479
|
-
tool: tool2
|
|
2480
|
-
});
|
|
2481
|
-
yield {
|
|
2482
|
-
type: "action:end",
|
|
2483
|
-
id: event.id,
|
|
2484
|
-
name: toolName,
|
|
2485
|
-
error: error instanceof Error ? error.message : "Tool execution failed"
|
|
2486
|
-
};
|
|
2950
|
+
if (event.usage) {
|
|
2951
|
+
adapterUsage = event.usage;
|
|
2487
2952
|
}
|
|
2488
|
-
|
|
2953
|
+
break;
|
|
2954
|
+
default:
|
|
2489
2955
|
yield event;
|
|
2490
|
-
}
|
|
2491
|
-
break;
|
|
2492
2956
|
}
|
|
2493
|
-
case "citation":
|
|
2494
|
-
yield event;
|
|
2495
|
-
break;
|
|
2496
|
-
case "error":
|
|
2497
|
-
yield event;
|
|
2498
|
-
return;
|
|
2499
|
-
// Exit on error
|
|
2500
|
-
case "done":
|
|
2501
|
-
adapterProviderMetadata = event.providerMetadata;
|
|
2502
|
-
if (event.usage) {
|
|
2503
|
-
adapterUsage = event.usage;
|
|
2504
|
-
}
|
|
2505
|
-
break;
|
|
2506
|
-
default:
|
|
2507
|
-
yield event;
|
|
2508
2957
|
}
|
|
2958
|
+
throwIfAborted(signal);
|
|
2959
|
+
if (pendingToolCalls.size || toolCalls.some((call) => !endedToolIds.has(call.id)))
|
|
2960
|
+
throw invalidProviderResponse(
|
|
2961
|
+
"Stream ended with incomplete tool calls"
|
|
2962
|
+
);
|
|
2963
|
+
} catch (error) {
|
|
2964
|
+
yield providerErrorEvent(error, "RUNTIME_STREAM_ERROR");
|
|
2965
|
+
return;
|
|
2509
2966
|
}
|
|
2510
2967
|
if (toolCalls.length > 0) {
|
|
2511
2968
|
if (debug) {
|
|
@@ -2614,7 +3071,18 @@ var Runtime = class {
|
|
|
2614
3071
|
nextToolSearchState,
|
|
2615
3072
|
_iteration + 1
|
|
2616
3073
|
)) {
|
|
2617
|
-
|
|
3074
|
+
if (event.type === "done" && adapterUsage) {
|
|
3075
|
+
const promptTokens = adapterUsage.prompt_tokens + (event.usage?.prompt_tokens ?? 0);
|
|
3076
|
+
const completionTokens = adapterUsage.completion_tokens + (event.usage?.completion_tokens ?? 0);
|
|
3077
|
+
yield {
|
|
3078
|
+
...event,
|
|
3079
|
+
usage: {
|
|
3080
|
+
prompt_tokens: promptTokens,
|
|
3081
|
+
completion_tokens: completionTokens,
|
|
3082
|
+
total_tokens: (adapterUsage.total_tokens ?? adapterUsage.prompt_tokens + adapterUsage.completion_tokens) + (event.usage?.total_tokens ?? (event.usage?.prompt_tokens ?? 0) + (event.usage?.completion_tokens ?? 0))
|
|
3083
|
+
}
|
|
3084
|
+
};
|
|
3085
|
+
} else yield event;
|
|
2618
3086
|
}
|
|
2619
3087
|
return;
|
|
2620
3088
|
}
|
|
@@ -2750,6 +3218,8 @@ var Runtime = class {
|
|
|
2750
3218
|
};
|
|
2751
3219
|
try {
|
|
2752
3220
|
const result = await this.adapter.complete(completionRequest);
|
|
3221
|
+
throwIfAborted(signal);
|
|
3222
|
+
validateToolCalls(result.toolCalls);
|
|
2753
3223
|
if (result.usage) {
|
|
2754
3224
|
accumulatedUsage.prompt_tokens += result.usage.promptTokens;
|
|
2755
3225
|
accumulatedUsage.completion_tokens += result.usage.completionTokens;
|
|
@@ -2769,7 +3239,7 @@ var Runtime = class {
|
|
|
2769
3239
|
}
|
|
2770
3240
|
yield {
|
|
2771
3241
|
type: "message:end",
|
|
2772
|
-
providerMetadata: result.providerMetadata
|
|
3242
|
+
providerMetadata: responseReplayMetadata(result.providerMetadata)
|
|
2773
3243
|
};
|
|
2774
3244
|
if (result.toolCalls.length > 0) {
|
|
2775
3245
|
const serverToolCalls = [];
|
|
@@ -2803,6 +3273,7 @@ var Runtime = class {
|
|
|
2803
3273
|
const serverToolResults = [];
|
|
2804
3274
|
const toolContextData = "toolContext" in this.config ? this.config.toolContext : void 0;
|
|
2805
3275
|
for (const tc of serverToolCalls) {
|
|
3276
|
+
throwIfAborted(signal);
|
|
2806
3277
|
const tool2 = selectedToolMap.get(tc.name);
|
|
2807
3278
|
if (tool2?.handler) {
|
|
2808
3279
|
if (debug) {
|
|
@@ -2817,6 +3288,7 @@ var Runtime = class {
|
|
|
2817
3288
|
);
|
|
2818
3289
|
try {
|
|
2819
3290
|
const toolResult = await tool2.handler(tc.args, toolContext);
|
|
3291
|
+
throwIfAborted(signal);
|
|
2820
3292
|
const modelOutput = resolveToolOutput(
|
|
2821
3293
|
toolResult,
|
|
2822
3294
|
tool2.toModelOutput?.(toolResult)
|
|
@@ -2837,6 +3309,7 @@ var Runtime = class {
|
|
|
2837
3309
|
modelOutput
|
|
2838
3310
|
};
|
|
2839
3311
|
} catch (error) {
|
|
3312
|
+
throwIfAborted(signal);
|
|
2840
3313
|
const errorResult = {
|
|
2841
3314
|
success: false,
|
|
2842
3315
|
error: error instanceof Error ? error.message : "Tool execution failed"
|
|
@@ -2870,7 +3343,11 @@ var Runtime = class {
|
|
|
2870
3343
|
const assistantMessage = {
|
|
2871
3344
|
role: "assistant",
|
|
2872
3345
|
content: result.content || null,
|
|
2873
|
-
...result.providerMetadata ? {
|
|
3346
|
+
...result.providerMetadata ? {
|
|
3347
|
+
providerMetadata: responseReplayMetadata(
|
|
3348
|
+
result.providerMetadata
|
|
3349
|
+
)
|
|
3350
|
+
} : {},
|
|
2874
3351
|
tool_calls: result.toolCalls.map((tc) => ({
|
|
2875
3352
|
id: tc.id,
|
|
2876
3353
|
type: "function",
|
|
@@ -2900,7 +3377,11 @@ var Runtime = class {
|
|
|
2900
3377
|
const assistantWithToolCalls = {
|
|
2901
3378
|
role: "assistant",
|
|
2902
3379
|
content: result.content || null,
|
|
2903
|
-
...result.providerMetadata ? {
|
|
3380
|
+
...result.providerMetadata ? {
|
|
3381
|
+
providerMetadata: responseReplayMetadata(
|
|
3382
|
+
result.providerMetadata
|
|
3383
|
+
)
|
|
3384
|
+
} : {},
|
|
2904
3385
|
tool_calls: result.toolCalls.map((tc) => ({
|
|
2905
3386
|
id: tc.id,
|
|
2906
3387
|
type: "function",
|
|
@@ -2932,7 +3413,11 @@ var Runtime = class {
|
|
|
2932
3413
|
const assistantMessage = {
|
|
2933
3414
|
role: "assistant",
|
|
2934
3415
|
content: result.content || null,
|
|
2935
|
-
...result.providerMetadata ? {
|
|
3416
|
+
...result.providerMetadata ? {
|
|
3417
|
+
providerMetadata: responseReplayMetadata(
|
|
3418
|
+
result.providerMetadata
|
|
3419
|
+
)
|
|
3420
|
+
} : {},
|
|
2936
3421
|
tool_calls: clientToolCalls.map((tc) => ({
|
|
2937
3422
|
id: tc.id,
|
|
2938
3423
|
type: "function",
|
|
@@ -2962,7 +3447,11 @@ var Runtime = class {
|
|
|
2962
3447
|
newMessages.push({
|
|
2963
3448
|
role: "assistant",
|
|
2964
3449
|
content: result.content,
|
|
2965
|
-
...result.providerMetadata ? {
|
|
3450
|
+
...result.providerMetadata ? {
|
|
3451
|
+
providerMetadata: responseReplayMetadata(
|
|
3452
|
+
result.providerMetadata
|
|
3453
|
+
)
|
|
3454
|
+
} : {}
|
|
2966
3455
|
});
|
|
2967
3456
|
}
|
|
2968
3457
|
if (debug) {
|
|
@@ -3483,20 +3972,11 @@ function parseToolCalls(response) {
|
|
|
3483
3972
|
const message = choices?.[0]?.message;
|
|
3484
3973
|
const toolCalls = message?.tool_calls || [];
|
|
3485
3974
|
return toolCalls.map((tc) => {
|
|
3486
|
-
|
|
3487
|
-
try {
|
|
3488
|
-
input = JSON.parse(tc.function.arguments);
|
|
3489
|
-
} catch (e) {
|
|
3490
|
-
console.error(
|
|
3491
|
-
"Failed to parse tool arguments:",
|
|
3492
|
-
tc.function.arguments,
|
|
3493
|
-
e
|
|
3494
|
-
);
|
|
3495
|
-
}
|
|
3975
|
+
const input2 = parseToolArguments(tc.function.arguments);
|
|
3496
3976
|
return {
|
|
3497
3977
|
id: tc.id,
|
|
3498
3978
|
name: tc.function.name,
|
|
3499
|
-
input
|
|
3979
|
+
input: input2
|
|
3500
3980
|
};
|
|
3501
3981
|
});
|
|
3502
3982
|
}
|
|
@@ -3577,7 +4057,7 @@ function parseToolCalls2(response) {
|
|
|
3577
4057
|
return content.filter((block) => block?.type === "tool_use").map((block) => ({
|
|
3578
4058
|
id: block.id,
|
|
3579
4059
|
name: block.name,
|
|
3580
|
-
input: block.input
|
|
4060
|
+
input: parseToolArguments(block.input)
|
|
3581
4061
|
}));
|
|
3582
4062
|
}
|
|
3583
4063
|
function extractTextContent2(response) {
|
|
@@ -3911,7 +4391,11 @@ async function* runAgentLoop(options) {
|
|
|
3911
4391
|
providerTools,
|
|
3912
4392
|
providerToolOptions
|
|
3913
4393
|
);
|
|
4394
|
+
throwIfAborted(signal);
|
|
3914
4395
|
const toolCalls = formatter.parseToolCalls(response);
|
|
4396
|
+
validateToolCalls(
|
|
4397
|
+
toolCalls.map((call) => ({ ...call, args: call.input }))
|
|
4398
|
+
);
|
|
3915
4399
|
const textContent = formatter.extractTextContent(response);
|
|
3916
4400
|
if (textContent) {
|
|
3917
4401
|
const messageId = generateMessageId();
|
|
@@ -3926,15 +4410,13 @@ async function* runAgentLoop(options) {
|
|
|
3926
4410
|
toolCalls.map((tc) => tc.name)
|
|
3927
4411
|
);
|
|
3928
4412
|
}
|
|
3929
|
-
const results =
|
|
4413
|
+
const results = yield* executeToolCalls(
|
|
3930
4414
|
toolCalls,
|
|
3931
4415
|
effectiveSelectedTools,
|
|
3932
4416
|
executeServerTool,
|
|
3933
4417
|
waitForClientToolResult,
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
},
|
|
3937
|
-
debug
|
|
4418
|
+
debug,
|
|
4419
|
+
signal
|
|
3938
4420
|
);
|
|
3939
4421
|
for (const result of results) {
|
|
3940
4422
|
const toolCall = toolCalls.find((tc) => tc.id === result.toolCallId);
|
|
@@ -4023,9 +4505,10 @@ function buildConversation(messages, systemPrompt) {
|
|
|
4023
4505
|
}
|
|
4024
4506
|
return conversation;
|
|
4025
4507
|
}
|
|
4026
|
-
async function executeToolCalls(toolCalls, tools, executeServerTool, waitForClientToolResult,
|
|
4508
|
+
async function* executeToolCalls(toolCalls, tools, executeServerTool, waitForClientToolResult, debug, signal) {
|
|
4027
4509
|
const results = [];
|
|
4028
4510
|
for (const toolCall of toolCalls) {
|
|
4511
|
+
throwIfAborted(signal);
|
|
4029
4512
|
const tool2 = tools.find((t) => t.name === toolCall.name);
|
|
4030
4513
|
if (!tool2) {
|
|
4031
4514
|
if (debug) {
|
|
@@ -4042,22 +4525,26 @@ async function executeToolCalls(toolCalls, tools, executeServerTool, waitForClie
|
|
|
4042
4525
|
});
|
|
4043
4526
|
continue;
|
|
4044
4527
|
}
|
|
4045
|
-
|
|
4528
|
+
yield {
|
|
4046
4529
|
type: "action:start",
|
|
4047
4530
|
id: toolCall.id,
|
|
4048
4531
|
name: toolCall.name,
|
|
4049
4532
|
hidden: tool2.hidden ?? false
|
|
4050
|
-
}
|
|
4051
|
-
|
|
4533
|
+
};
|
|
4534
|
+
yield {
|
|
4052
4535
|
type: "action:args",
|
|
4053
4536
|
id: toolCall.id,
|
|
4054
4537
|
args: JSON.stringify(toolCall.input)
|
|
4055
|
-
}
|
|
4538
|
+
};
|
|
4056
4539
|
try {
|
|
4057
4540
|
let response;
|
|
4541
|
+
throwIfAborted(signal);
|
|
4058
4542
|
if (tool2.location === "server") {
|
|
4059
4543
|
if (tool2.handler) {
|
|
4060
|
-
response = await tool2.handler(toolCall.input
|
|
4544
|
+
response = await tool2.handler(toolCall.input, {
|
|
4545
|
+
signal,
|
|
4546
|
+
toolCallId: toolCall.id
|
|
4547
|
+
});
|
|
4061
4548
|
} else if (executeServerTool) {
|
|
4062
4549
|
response = await executeServerTool(toolCall.name, toolCall.input);
|
|
4063
4550
|
} else {
|
|
@@ -4080,12 +4567,13 @@ async function executeToolCalls(toolCalls, tools, executeServerTool, waitForClie
|
|
|
4080
4567
|
};
|
|
4081
4568
|
}
|
|
4082
4569
|
}
|
|
4083
|
-
|
|
4570
|
+
throwIfAborted(signal);
|
|
4571
|
+
yield {
|
|
4084
4572
|
type: "action:end",
|
|
4085
4573
|
id: toolCall.id,
|
|
4086
4574
|
name: toolCall.name,
|
|
4087
4575
|
result: response
|
|
4088
|
-
}
|
|
4576
|
+
};
|
|
4089
4577
|
results.push({
|
|
4090
4578
|
toolCallId: toolCall.id,
|
|
4091
4579
|
content: JSON.stringify(response),
|
|
@@ -4093,13 +4581,14 @@ async function executeToolCalls(toolCalls, tools, executeServerTool, waitForClie
|
|
|
4093
4581
|
error: response.error
|
|
4094
4582
|
});
|
|
4095
4583
|
} catch (error) {
|
|
4584
|
+
throwIfAborted(signal);
|
|
4096
4585
|
const errorMessage = error instanceof Error ? error.message : "Tool execution failed";
|
|
4097
|
-
|
|
4586
|
+
yield {
|
|
4098
4587
|
type: "action:end",
|
|
4099
4588
|
id: toolCall.id,
|
|
4100
4589
|
name: toolCall.name,
|
|
4101
4590
|
error: errorMessage
|
|
4102
|
-
}
|
|
4591
|
+
};
|
|
4103
4592
|
results.push({
|
|
4104
4593
|
toolCallId: toolCall.id,
|
|
4105
4594
|
content: JSON.stringify({
|
|
@@ -4116,17 +4605,17 @@ async function executeToolCalls(toolCalls, tools, executeServerTool, waitForClie
|
|
|
4116
4605
|
|
|
4117
4606
|
// src/core/audio.ts
|
|
4118
4607
|
var audioErrorMarker = /* @__PURE__ */ Symbol.for("@yourgpt/llm-sdk/AudioAPIError");
|
|
4119
|
-
var
|
|
4608
|
+
var _a3;
|
|
4120
4609
|
var AudioAPIError = class extends Error {
|
|
4121
4610
|
constructor(message, code, status, requestId) {
|
|
4122
4611
|
super(message);
|
|
4123
4612
|
this.code = code;
|
|
4124
4613
|
this.status = status;
|
|
4125
4614
|
this.requestId = requestId;
|
|
4126
|
-
this[
|
|
4615
|
+
this[_a3] = true;
|
|
4127
4616
|
this.name = "AudioAPIError";
|
|
4128
4617
|
}
|
|
4129
|
-
static [(
|
|
4618
|
+
static [(_a3 = audioErrorMarker, Symbol.hasInstance)](value) {
|
|
4130
4619
|
return !!value && typeof value === "object" && value[audioErrorMarker] === true;
|
|
4131
4620
|
}
|
|
4132
4621
|
};
|
|
@@ -4161,6 +4650,6 @@ async function transcribe({
|
|
|
4161
4650
|
return result;
|
|
4162
4651
|
}
|
|
4163
4652
|
|
|
4164
|
-
export { AudioAPIError, DEFAULT_CAPABILITIES, DEFAULT_MAX_ITERATIONS, GenerateResult, Runtime, StreamResult, buildProviderToolOptions, createEventStream, createExpressHandler, createExpressMiddleware, createHonoApp, createNextHandler, createNodeHandler, createRuntime, createSSEHeaders, createSSEResponse, createStreamResult, createTextStreamHeaders, createTextStreamResponse, extractInputMessages, formatSSEData, formatToolsForAnthropic, formatToolsForGoogle, formatToolsForOpenAI, generateMessageId, generateSpeech, generateText, generateThreadId, generateToolCallId, mapOutputMessages, pipeSSEToResponse, pipeTextToResponse, runAgentLoop, searchTools, selectTools, shouldExposeToolSearch, streamText, tool, transcribe };
|
|
4653
|
+
export { AudioAPIError, DEFAULT_CAPABILITIES, DEFAULT_MAX_ITERATIONS, DecisionAPIError, GenerateResult, MediaAPIError, Runtime, StreamResult, buildProviderToolOptions, createEventStream, createExpressHandler, createExpressMiddleware, createHonoApp, createNextHandler, createNodeHandler, createRuntime, createSSEHeaders, createSSEResponse, createStreamResult, createTextStreamHeaders, createTextStreamResponse, experimental_decide, extractInputMessages, formatSSEData, formatToolsForAnthropic, formatToolsForGoogle, formatToolsForOpenAI, generateImage, generateMessageId, generateSpeech, generateText, generateThreadId, generateToolCallId, mapOutputMessages, pipeSSEToResponse, pipeTextToResponse, runAgentLoop, searchTools, selectTools, shouldExposeToolSearch, streamText, tool, transcribe };
|
|
4165
4654
|
//# sourceMappingURL=index.mjs.map
|
|
4166
4655
|
//# sourceMappingURL=index.mjs.map
|