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