@yourgpt/llm-sdk 2.6.0-beta.1 → 2.6.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +112 -0
  2. package/dist/adapters/index.d.mts +5 -5
  3. package/dist/adapters/index.d.ts +5 -5
  4. package/dist/adapters/index.js +372 -39
  5. package/dist/adapters/index.mjs +372 -39
  6. package/dist/audio-BBSwnjo8.d.mts +92 -0
  7. package/dist/audio-BBSwnjo8.d.ts +92 -0
  8. package/dist/{base-CkeT7u-O.d.mts → base-BICaQaRS.d.mts} +7 -3
  9. package/dist/{base-BdTpUAWI.d.ts → base-CpRPB8u8.d.ts} +7 -3
  10. package/dist/fallback/index.d.mts +4 -4
  11. package/dist/fallback/index.d.ts +4 -4
  12. package/dist/index.d.mts +17 -35
  13. package/dist/index.d.ts +17 -35
  14. package/dist/index.js +229 -60
  15. package/dist/index.mjs +227 -61
  16. package/dist/providers/anthropic/index.d.mts +3 -3
  17. package/dist/providers/anthropic/index.d.ts +3 -3
  18. package/dist/providers/anthropic/index.js +123 -7
  19. package/dist/providers/anthropic/index.mjs +123 -7
  20. package/dist/providers/azure/index.d.mts +3 -3
  21. package/dist/providers/azure/index.d.ts +3 -3
  22. package/dist/providers/azure/index.js +101 -4
  23. package/dist/providers/azure/index.mjs +101 -4
  24. package/dist/providers/fireworks/index.d.mts +3 -3
  25. package/dist/providers/fireworks/index.d.ts +3 -3
  26. package/dist/providers/fireworks/index.js +321 -31
  27. package/dist/providers/fireworks/index.mjs +321 -31
  28. package/dist/providers/google/index.d.mts +3 -3
  29. package/dist/providers/google/index.d.ts +3 -3
  30. package/dist/providers/google/index.js +321 -31
  31. package/dist/providers/google/index.mjs +321 -31
  32. package/dist/providers/ollama/index.d.mts +4 -4
  33. package/dist/providers/ollama/index.d.ts +4 -4
  34. package/dist/providers/ollama/index.js +87 -2
  35. package/dist/providers/ollama/index.mjs +87 -2
  36. package/dist/providers/openai/index.d.mts +25 -6
  37. package/dist/providers/openai/index.d.ts +25 -6
  38. package/dist/providers/openai/index.js +750 -40
  39. package/dist/providers/openai/index.mjs +749 -41
  40. package/dist/providers/openrouter/index.d.mts +3 -3
  41. package/dist/providers/openrouter/index.d.ts +3 -3
  42. package/dist/providers/openrouter/index.js +321 -31
  43. package/dist/providers/openrouter/index.mjs +321 -31
  44. package/dist/providers/togetherai/index.d.mts +3 -3
  45. package/dist/providers/togetherai/index.d.ts +3 -3
  46. package/dist/providers/togetherai/index.js +321 -31
  47. package/dist/providers/togetherai/index.mjs +321 -31
  48. package/dist/providers/xai/index.d.mts +3 -3
  49. package/dist/providers/xai/index.d.ts +3 -3
  50. package/dist/providers/xai/index.js +321 -31
  51. package/dist/providers/xai/index.mjs +321 -31
  52. package/dist/{types-BWRYIvl_.d.mts → types-C3RgRbEC.d.mts} +1 -1
  53. package/dist/{types-CpXcT-tY.d.ts → types-DCFqkJAy.d.ts} +1 -1
  54. package/dist/{types-NOswlhm9.d.mts → types-DHQEMFHA.d.mts} +3 -3
  55. package/dist/{types-BW3csYo5.d.mts → types-Dg1Bcg1k.d.mts} +106 -3
  56. package/dist/{types-BW3csYo5.d.ts → types-Dg1Bcg1k.d.ts} +106 -3
  57. package/dist/{types-DA54bSmX.d.ts → types-Dikj3En4.d.ts} +3 -3
  58. package/dist/yourgpt/index.d.mts +1 -1
  59. package/dist/yourgpt/index.d.ts +1 -1
  60. package/docs/multimodal-and-audio.md +170 -0
  61. package/package.json +3 -2
package/dist/index.mjs CHANGED
@@ -1,13 +1,87 @@
1
1
  import { Hono } from 'hono';
2
2
  import { cors } from 'hono/cors';
3
3
 
4
+ // src/core/tool-output.ts
5
+ var imageTypes = /* @__PURE__ */ new Set([
6
+ "image/png",
7
+ "image/jpeg",
8
+ "image/webp",
9
+ "image/gif"
10
+ ]);
11
+ function normalizeToolOutput(value) {
12
+ const output = value;
13
+ if (output?.type !== "content" || !Array.isArray(output.content) || !output.content.length) {
14
+ throw new Error("Tool model output must contain a nonempty content array");
15
+ }
16
+ return {
17
+ type: "content",
18
+ content: output.content.map((part) => {
19
+ if (part?.type === "text" && typeof part.text === "string")
20
+ return { type: "text", text: part.text };
21
+ if (part?.type !== "image")
22
+ throw new Error("Unsupported tool output content type");
23
+ const sources = ["data", "url", "fileId"].filter((key) => key in part);
24
+ if (sources.length !== 1)
25
+ throw new Error(
26
+ "Tool image requires exactly one of data, url, or fileId"
27
+ );
28
+ if ("fileId" in part) {
29
+ if (part.provider !== "openai" || typeof part.fileId !== "string" || !part.fileId.trim())
30
+ throw new Error(
31
+ "Tool image file references must name the openai provider and fileId"
32
+ );
33
+ return { type: "image", fileId: part.fileId, provider: "openai" };
34
+ }
35
+ if ("url" in part) {
36
+ let url;
37
+ try {
38
+ url = new URL(part.url);
39
+ } catch {
40
+ throw new Error("Invalid tool image URL");
41
+ }
42
+ if (!["https:", "http:"].includes(url.protocol) || url.username || url.password)
43
+ throw new Error(
44
+ "Tool image URL must use HTTP(S) without credentials"
45
+ );
46
+ return { type: "image", url: url.href };
47
+ }
48
+ if (!("data" in part) || !imageTypes.has(part.mediaType))
49
+ throw new Error("Unsupported tool image media type");
50
+ let data = part.data instanceof Uint8Array ? Buffer.from(part.data).toString("base64") : part.data;
51
+ if (typeof data !== "string")
52
+ throw new Error("Tool image data must be base64 or bytes");
53
+ if (data.startsWith("data:")) {
54
+ const match = /^data:([^;,]+);base64,(.+)$/.exec(data);
55
+ if (!match || match[1] !== part.mediaType)
56
+ throw new Error(
57
+ "Tool image data URL media type does not match mediaType"
58
+ );
59
+ data = match[2];
60
+ }
61
+ if (!data.length || data.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(data))
62
+ throw new Error("Invalid tool image base64 data");
63
+ if (Buffer.byteLength(data, "base64") > 20 * 1024 * 1024)
64
+ throw new Error("Tool image exceeds 20 MiB");
65
+ if (Buffer.from(data, "base64").toString("base64") !== data)
66
+ throw new Error("Invalid tool image base64 data");
67
+ return { type: "image", data, mediaType: part.mediaType };
68
+ })
69
+ };
70
+ }
71
+ function resolveToolOutput(result, mapped) {
72
+ if (mapped !== void 0) return normalizeToolOutput(mapped);
73
+ const content = result?._aiContent;
74
+ return content !== void 0 ? normalizeToolOutput({ type: "content", content }) : void 0;
75
+ }
76
+
4
77
  // src/core/tool.ts
5
78
  function tool(config) {
6
79
  return {
7
80
  description: config.description,
8
81
  parameters: config.parameters,
9
82
  execute: config.execute,
10
- hidden: config.hidden
83
+ hidden: config.hidden,
84
+ toModelOutput: config.toModelOutput
11
85
  };
12
86
  }
13
87
  function toolToJsonSchema(toolDef) {
@@ -155,6 +229,7 @@ async function generateText(params) {
155
229
  const formattedTools = tools ? formatToolsForProvider(tools, model.provider) : void 0;
156
230
  const result = await model.doGenerate({
157
231
  messages,
232
+ openai: params.openai,
158
233
  tools: formattedTools,
159
234
  temperature: params.temperature,
160
235
  reasoningEffort: params.reasoningEffort,
@@ -188,7 +263,11 @@ async function generateText(params) {
188
263
  throwIfAborted(signal);
189
264
  const result2 = {
190
265
  toolCallId: call.id,
191
- result: toolResult
266
+ result: toolResult,
267
+ modelOutput: resolveToolOutput(
268
+ toolResult,
269
+ toolDef.toModelOutput?.(toolResult)
270
+ )
192
271
  };
193
272
  stepToolResults.push(result2);
194
273
  allToolResults.push(result2);
@@ -210,22 +289,23 @@ async function generateText(params) {
210
289
  toolCalls: result.toolCalls,
211
290
  toolResults: stepToolResults,
212
291
  finishReason: result.finishReason,
213
- usage: result.usage
292
+ usage: result.usage,
293
+ providerMetadata: result.providerMetadata
214
294
  });
215
- if (!result.toolCalls || result.toolCalls.length === 0) {
216
- break;
217
- }
218
295
  const assistantMessage = {
219
296
  role: "assistant",
220
297
  content: result.text || null,
221
- toolCalls: result.toolCalls
298
+ ...result.toolCalls.length ? { toolCalls: result.toolCalls } : {},
299
+ ...result.providerMetadata ? { providerMetadata: result.providerMetadata } : {}
222
300
  };
223
301
  messages = [...messages, assistantMessage];
302
+ if (!result.toolCalls || result.toolCalls.length === 0) break;
224
303
  for (const tr of stepToolResults) {
225
304
  const toolMessage = {
226
305
  role: "tool",
227
306
  toolCallId: tr.toolCallId,
228
- content: JSON.stringify(tr.result)
307
+ content: tr.modelOutput ? "[Tool returned content]" : JSON.stringify(tr.result),
308
+ ...tr.modelOutput ? { modelOutput: tr.modelOutput } : {}
229
309
  };
230
310
  messages = [...messages, toolMessage];
231
311
  }
@@ -233,6 +313,7 @@ async function generateText(params) {
233
313
  const lastStep = steps[steps.length - 1];
234
314
  return {
235
315
  text: lastStep?.text ?? "",
316
+ providerMetadata: lastStep?.providerMetadata,
236
317
  usage: sumUsage(steps),
237
318
  finishReason: lastStep?.finishReason ?? "stop",
238
319
  steps,
@@ -286,6 +367,8 @@ async function streamText(params) {
286
367
  `[llm-sdk] ${model.provider}/${model.modelId} does not support structured output (responseFormat); the request will be sent but the provider may ignore it.`
287
368
  );
288
369
  }
370
+ let messages = buildMessages2(params);
371
+ let finalProviderMetadata;
289
372
  let fullText = "";
290
373
  let finalUsage = {
291
374
  promptTokens: 0,
@@ -294,7 +377,6 @@ async function streamText(params) {
294
377
  };
295
378
  let finalFinishReason = "stop";
296
379
  async function* createFullStream() {
297
- let messages = buildMessages2(params);
298
380
  for (let step = 0; step < maxSteps; step++) {
299
381
  yield { type: "step-start", step };
300
382
  if (signal?.aborted) {
@@ -303,11 +385,13 @@ async function streamText(params) {
303
385
  }
304
386
  const formattedTools = tools ? formatToolsForProvider2(tools, model.provider) : void 0;
305
387
  let stepText = "";
388
+ let stepProviderMetadata;
306
389
  const toolCalls = [];
307
390
  let stepFinishReason = "stop";
308
391
  try {
309
392
  for await (const chunk of model.doStream({
310
393
  messages,
394
+ openai: params.openai,
311
395
  tools: formattedTools,
312
396
  temperature: params.temperature,
313
397
  reasoningEffort: params.reasoningEffort,
@@ -330,6 +414,8 @@ async function streamText(params) {
330
414
  };
331
415
  break;
332
416
  case "finish":
417
+ stepProviderMetadata = chunk.providerMetadata;
418
+ finalProviderMetadata = chunk.providerMetadata;
333
419
  stepFinishReason = chunk.finishReason;
334
420
  finalFinishReason = chunk.finishReason;
335
421
  if (chunk.usage) {
@@ -352,16 +438,22 @@ async function streamText(params) {
352
438
  };
353
439
  return;
354
440
  }
355
- yield { type: "step-finish", step, finishReason: stepFinishReason };
356
- if (toolCalls.length === 0 || !tools) {
357
- break;
358
- }
359
- const assistantMessage = {
360
- role: "assistant",
361
- content: stepText || null,
362
- toolCalls
441
+ yield {
442
+ type: "step-finish",
443
+ step,
444
+ finishReason: stepFinishReason,
445
+ providerMetadata: stepProviderMetadata
363
446
  };
364
- messages = [...messages, assistantMessage];
447
+ messages = [
448
+ ...messages,
449
+ {
450
+ role: "assistant",
451
+ content: stepText || null,
452
+ ...toolCalls.length ? { toolCalls } : {},
453
+ ...stepProviderMetadata ? { providerMetadata: stepProviderMetadata } : {}
454
+ }
455
+ ];
456
+ if (toolCalls.length === 0 || !tools) break;
365
457
  for (const call of toolCalls) {
366
458
  throwIfAborted(signal);
367
459
  const toolDef = tools[call.name];
@@ -390,13 +482,23 @@ async function streamText(params) {
390
482
  messages
391
483
  });
392
484
  throwIfAborted(signal);
393
- yield { type: "tool-result", toolCallId: call.id, result };
485
+ const modelOutput = resolveToolOutput(
486
+ result,
487
+ toolDef.toModelOutput?.(result)
488
+ );
489
+ yield {
490
+ type: "tool-result",
491
+ toolCallId: call.id,
492
+ result,
493
+ modelOutput
494
+ };
394
495
  messages = [
395
496
  ...messages,
396
497
  {
397
498
  role: "tool",
398
499
  toolCallId: call.id,
399
- content: JSON.stringify(result)
500
+ content: modelOutput ? "[Tool returned content]" : JSON.stringify(result),
501
+ ...modelOutput ? { modelOutput } : {}
400
502
  }
401
503
  ];
402
504
  } catch (error) {
@@ -423,7 +525,8 @@ async function streamText(params) {
423
525
  yield {
424
526
  type: "finish",
425
527
  finishReason: finalFinishReason,
426
- usage: finalUsage
528
+ usage: finalUsage,
529
+ providerMetadata: finalProviderMetadata
427
530
  };
428
531
  }
429
532
  const source = createFullStream();
@@ -475,6 +578,12 @@ async function streamText(params) {
475
578
  return {
476
579
  textStream: createTextStream(),
477
580
  fullStream: sharedStream(),
581
+ get response() {
582
+ return consumeStream().then(() => ({ messages }));
583
+ },
584
+ get providerMetadata() {
585
+ return consumeStream().then(() => finalProviderMetadata);
586
+ },
478
587
  get text() {
479
588
  return consumeStream().then(() => fullText);
480
589
  },
@@ -598,6 +707,7 @@ function createMessage(partial) {
598
707
  tool_calls: partial.tool_calls,
599
708
  tool_call_id: partial.tool_call_id,
600
709
  metadata: partial.metadata,
710
+ providerMetadata: partial.providerMetadata,
601
711
  created_at: partial.created_at ?? /* @__PURE__ */ new Date()
602
712
  };
603
713
  }
@@ -646,7 +756,13 @@ function mapOutputMessages(resultMessages) {
646
756
  role: m.role,
647
757
  content: m.content ?? "",
648
758
  toolCalls: m.tool_calls,
649
- toolCallId: m.tool_call_id
759
+ toolCallId: m.tool_call_id,
760
+ ...m.providerMetadata || m.modelOutput ? {
761
+ metadata: {
762
+ ...m.providerMetadata ? { providerMetadata: m.providerMetadata } : {},
763
+ ...m.modelOutput ? { modelOutput: m.modelOutput } : {}
764
+ }
765
+ } : {}
650
766
  }));
651
767
  }
652
768
 
@@ -1536,9 +1652,6 @@ function buildProviderToolOptions(params) {
1536
1652
  function buildToolResultForAI(tool2, result, args) {
1537
1653
  const typedResult = result;
1538
1654
  const responseMode = typedResult?._aiResponseMode ?? tool2?.aiResponseMode ?? "full";
1539
- if (typedResult?._aiContent && typedResult._aiContent.length > 0) {
1540
- return typedResult._aiContent;
1541
- }
1542
1655
  let aiContext;
1543
1656
  if (typedResult?._aiContext) {
1544
1657
  aiContext = typedResult._aiContext;
@@ -1558,25 +1671,6 @@ function buildToolResultForAI(tool2, result, args) {
1558
1671
  Full data: ${fullData}` : fullData;
1559
1672
  }
1560
1673
  }
1561
- function serializeToolResultContent(content) {
1562
- if (typeof content === "string") {
1563
- return content;
1564
- }
1565
- return content.map((item) => {
1566
- if (item.type === "image") {
1567
- return {
1568
- type: "image_url",
1569
- image_url: {
1570
- url: `data:${item.mediaType};base64,${item.data}`
1571
- }
1572
- };
1573
- }
1574
- return {
1575
- type: "text",
1576
- text: item.text
1577
- };
1578
- });
1579
- }
1580
1674
  function extractHeaders(request) {
1581
1675
  if (!request) return {};
1582
1676
  const headers = {};
@@ -1633,7 +1727,11 @@ var Runtime = class {
1633
1727
  const messages = request.messages.map(
1634
1728
  (m, i) => createMessage({
1635
1729
  role: m.role,
1636
- content: m.content
1730
+ content: m.content,
1731
+ providerMetadata: m.providerMetadata,
1732
+ modelOutput: m.modelOutput,
1733
+ tool_calls: m.tool_calls,
1734
+ tool_call_id: m.tool_call_id
1637
1735
  })
1638
1736
  );
1639
1737
  const allActions = [...this.actions.values()];
@@ -2250,6 +2348,7 @@ var Runtime = class {
2250
2348
  let currentToolCall = null;
2251
2349
  const serverToolResults = [];
2252
2350
  const toolContextData = "toolContext" in this.config ? this.config.toolContext : void 0;
2351
+ let adapterProviderMetadata;
2253
2352
  let adapterUsage;
2254
2353
  const completionRequest = {
2255
2354
  messages: [],
@@ -2348,18 +2447,24 @@ var Runtime = class {
2348
2447
  );
2349
2448
  try {
2350
2449
  const result = await tool2.handler(args, toolContext);
2450
+ const modelOutput = resolveToolOutput(
2451
+ result,
2452
+ tool2.toModelOutput?.(result)
2453
+ );
2351
2454
  serverToolResults.push({
2352
2455
  id: event.id,
2353
2456
  name: toolName,
2354
2457
  args,
2355
2458
  result,
2459
+ modelOutput,
2356
2460
  tool: tool2
2357
2461
  });
2358
2462
  yield {
2359
2463
  type: "action:end",
2360
2464
  id: event.id,
2361
2465
  name: toolName,
2362
- result
2466
+ result,
2467
+ modelOutput
2363
2468
  };
2364
2469
  } catch (error) {
2365
2470
  const errorResult = {
@@ -2393,6 +2498,7 @@ var Runtime = class {
2393
2498
  return;
2394
2499
  // Exit on error
2395
2500
  case "done":
2501
+ adapterProviderMetadata = event.providerMetadata;
2396
2502
  if (event.usage) {
2397
2503
  adapterUsage = event.usage;
2398
2504
  }
@@ -2413,11 +2519,11 @@ var Runtime = class {
2413
2519
  (tc) => !serverToolIds.has(tc.id)
2414
2520
  );
2415
2521
  const serverToolResultMessages = serverToolResults.map((tr) => {
2416
- const aiContent = buildToolResultForAI(tr.tool, tr.result, tr.args);
2417
- const content = typeof aiContent === "string" ? aiContent : JSON.stringify(serializeToolResultContent(aiContent));
2522
+ const content = tr.modelOutput ? "[Tool returned content]" : buildToolResultForAI(tr.tool, tr.result, tr.args);
2418
2523
  return {
2419
2524
  role: "tool",
2420
2525
  content,
2526
+ ...tr.modelOutput ? { modelOutput: tr.modelOutput } : {},
2421
2527
  tool_call_id: tr.id
2422
2528
  };
2423
2529
  });
@@ -2430,6 +2536,7 @@ var Runtime = class {
2430
2536
  const assistantMessage = {
2431
2537
  role: "assistant",
2432
2538
  content: accumulatedText || null,
2539
+ ...adapterProviderMetadata ? { providerMetadata: adapterProviderMetadata } : {},
2433
2540
  tool_calls: toolCalls.map((tc) => ({
2434
2541
  id: tc.id,
2435
2542
  type: "function",
@@ -2464,6 +2571,7 @@ var Runtime = class {
2464
2571
  const assistantWithToolCalls = {
2465
2572
  role: "assistant",
2466
2573
  content: accumulatedText || null,
2574
+ ...adapterProviderMetadata ? { providerMetadata: adapterProviderMetadata } : {},
2467
2575
  tool_calls: serverToolResults.map((tr) => {
2468
2576
  const tc = toolCalls.find((t) => t.id === tr.id);
2469
2577
  return {
@@ -2514,6 +2622,7 @@ var Runtime = class {
2514
2622
  const assistantMessage = {
2515
2623
  role: "assistant",
2516
2624
  content: accumulatedText || null,
2625
+ ...adapterProviderMetadata ? { providerMetadata: adapterProviderMetadata } : {},
2517
2626
  tool_calls: clientToolCalls.map((tc) => ({
2518
2627
  id: tc.id,
2519
2628
  type: "function",
@@ -2539,10 +2648,11 @@ var Runtime = class {
2539
2648
  return;
2540
2649
  }
2541
2650
  }
2542
- if (accumulatedText) {
2651
+ if (accumulatedText || adapterProviderMetadata) {
2543
2652
  newMessages.push({
2544
2653
  role: "assistant",
2545
- content: accumulatedText
2654
+ content: accumulatedText,
2655
+ ...adapterProviderMetadata ? { providerMetadata: adapterProviderMetadata } : {}
2546
2656
  });
2547
2657
  }
2548
2658
  if (debug) {
@@ -2657,7 +2767,10 @@ var Runtime = class {
2657
2767
  content: result.content
2658
2768
  };
2659
2769
  }
2660
- yield { type: "message:end" };
2770
+ yield {
2771
+ type: "message:end",
2772
+ providerMetadata: result.providerMetadata
2773
+ };
2661
2774
  if (result.toolCalls.length > 0) {
2662
2775
  const serverToolCalls = [];
2663
2776
  const clientToolCalls = [];
@@ -2704,18 +2817,24 @@ var Runtime = class {
2704
2817
  );
2705
2818
  try {
2706
2819
  const toolResult = await tool2.handler(tc.args, toolContext);
2820
+ const modelOutput = resolveToolOutput(
2821
+ toolResult,
2822
+ tool2.toModelOutput?.(toolResult)
2823
+ );
2707
2824
  serverToolResults.push({
2708
2825
  id: tc.id,
2709
2826
  name: tc.name,
2710
2827
  args: tc.args,
2711
2828
  result: toolResult,
2829
+ modelOutput,
2712
2830
  tool: tool2
2713
2831
  });
2714
2832
  yield {
2715
2833
  type: "action:end",
2716
2834
  id: tc.id,
2717
2835
  name: tc.name,
2718
- result: toolResult
2836
+ result: toolResult,
2837
+ modelOutput
2719
2838
  };
2720
2839
  } catch (error) {
2721
2840
  const errorResult = {
@@ -2739,15 +2858,11 @@ var Runtime = class {
2739
2858
  }
2740
2859
  }
2741
2860
  const serverToolResultMessages = serverToolResults.map((tr) => {
2742
- const aiContent = buildToolResultForAI(
2743
- tr.tool,
2744
- tr.result,
2745
- tr.args
2746
- );
2747
- const content = typeof aiContent === "string" ? aiContent : JSON.stringify(serializeToolResultContent(aiContent));
2861
+ const content = tr.modelOutput ? "[Tool returned content]" : buildToolResultForAI(tr.tool, tr.result, tr.args);
2748
2862
  return {
2749
2863
  role: "tool",
2750
2864
  content,
2865
+ ...tr.modelOutput ? { modelOutput: tr.modelOutput } : {},
2751
2866
  tool_call_id: tr.id
2752
2867
  };
2753
2868
  });
@@ -2755,6 +2870,7 @@ var Runtime = class {
2755
2870
  const assistantMessage = {
2756
2871
  role: "assistant",
2757
2872
  content: result.content || null,
2873
+ ...result.providerMetadata ? { providerMetadata: result.providerMetadata } : {},
2758
2874
  tool_calls: result.toolCalls.map((tc) => ({
2759
2875
  id: tc.id,
2760
2876
  type: "function",
@@ -2784,6 +2900,7 @@ var Runtime = class {
2784
2900
  const assistantWithToolCalls = {
2785
2901
  role: "assistant",
2786
2902
  content: result.content || null,
2903
+ ...result.providerMetadata ? { providerMetadata: result.providerMetadata } : {},
2787
2904
  tool_calls: result.toolCalls.map((tc) => ({
2788
2905
  id: tc.id,
2789
2906
  type: "function",
@@ -2815,6 +2932,7 @@ var Runtime = class {
2815
2932
  const assistantMessage = {
2816
2933
  role: "assistant",
2817
2934
  content: result.content || null,
2935
+ ...result.providerMetadata ? { providerMetadata: result.providerMetadata } : {},
2818
2936
  tool_calls: clientToolCalls.map((tc) => ({
2819
2937
  id: tc.id,
2820
2938
  type: "function",
@@ -2840,10 +2958,11 @@ var Runtime = class {
2840
2958
  return;
2841
2959
  }
2842
2960
  }
2843
- if (result.content) {
2961
+ if (result.content || result.providerMetadata) {
2844
2962
  newMessages.push({
2845
2963
  role: "assistant",
2846
- content: result.content
2964
+ content: result.content,
2965
+ ...result.providerMetadata ? { providerMetadata: result.providerMetadata } : {}
2847
2966
  });
2848
2967
  }
2849
2968
  if (debug) {
@@ -3995,6 +4114,53 @@ async function executeToolCalls(toolCalls, tools, executeServerTool, waitForClie
3995
4114
  return results;
3996
4115
  }
3997
4116
 
3998
- export { 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, generateText, generateThreadId, generateToolCallId, mapOutputMessages, pipeSSEToResponse, pipeTextToResponse, runAgentLoop, searchTools, selectTools, shouldExposeToolSearch, streamText, tool };
4117
+ // src/core/audio.ts
4118
+ var audioErrorMarker = /* @__PURE__ */ Symbol.for("@yourgpt/llm-sdk/AudioAPIError");
4119
+ var _a;
4120
+ var AudioAPIError = class extends Error {
4121
+ constructor(message, code, status, requestId) {
4122
+ super(message);
4123
+ this.code = code;
4124
+ this.status = status;
4125
+ this.requestId = requestId;
4126
+ this[_a] = true;
4127
+ this.name = "AudioAPIError";
4128
+ }
4129
+ static [(_a = audioErrorMarker, Symbol.hasInstance)](value) {
4130
+ return !!value && typeof value === "object" && value[audioErrorMarker] === true;
4131
+ }
4132
+ };
4133
+ async function generateSpeech({
4134
+ model,
4135
+ ...options
4136
+ }) {
4137
+ options.signal?.throwIfAborted();
4138
+ if (typeof options.text !== "string" || !options.text.trim())
4139
+ throw new AudioAPIError("Speech text must not be empty", "invalid_input");
4140
+ const result = await model.doGenerate(options);
4141
+ options.signal?.throwIfAborted();
4142
+ if (!(result.audio?.uint8Array instanceof Uint8Array) || !result.audio.uint8Array.length)
4143
+ throw new AudioAPIError(
4144
+ "Speech provider returned empty audio",
4145
+ "invalid_response"
4146
+ );
4147
+ return result;
4148
+ }
4149
+ async function transcribe({
4150
+ model,
4151
+ ...options
4152
+ }) {
4153
+ options.signal?.throwIfAborted();
4154
+ const result = await model.doTranscribe(options);
4155
+ options.signal?.throwIfAborted();
4156
+ if (typeof result.text !== "string")
4157
+ throw new AudioAPIError(
4158
+ "Transcription provider returned an invalid transcript",
4159
+ "invalid_response"
4160
+ );
4161
+ return result;
4162
+ }
4163
+
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 };
3999
4165
  //# sourceMappingURL=index.mjs.map
4000
4166
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-BW3csYo5.mjs';
2
- import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-NOswlhm9.mjs';
1
+ import { L as LanguageModel } from '../../types-Dg1Bcg1k.mjs';
2
+ import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-DHQEMFHA.mjs';
3
3
  import 'zod';
4
- import '../../base-CkeT7u-O.mjs';
4
+ import '../../base-BICaQaRS.mjs';
5
5
 
6
6
  /**
7
7
  * Anthropic Provider - Modern Pattern
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-BW3csYo5.js';
2
- import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-DA54bSmX.js';
1
+ import { L as LanguageModel } from '../../types-Dg1Bcg1k.js';
2
+ import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-Dikj3En4.js';
3
3
  import 'zod';
4
- import '../../base-BdTpUAWI.js';
4
+ import '../../base-CpRPB8u8.js';
5
5
 
6
6
  /**
7
7
  * Anthropic Provider - Modern Pattern