@yourgpt/llm-sdk 2.6.0-beta.3 → 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.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -10
  3. package/dist/adapters/index.d.mts +11 -13
  4. package/dist/adapters/index.d.ts +11 -13
  5. package/dist/adapters/index.js +327 -100
  6. package/dist/adapters/index.mjs +327 -100
  7. package/dist/audio-K-Z3-Bce.d.mts +191 -0
  8. package/dist/audio-K-Z3-Bce.d.ts +191 -0
  9. package/dist/{base-BICaQaRS.d.mts → base-6LzczuCg.d.ts} +8 -1
  10. package/dist/{base-CpRPB8u8.d.ts → base-DySbTP8C.d.mts} +8 -1
  11. package/dist/decisions-CJzOt87t.d.mts +137 -0
  12. package/dist/decisions-CJzOt87t.d.ts +137 -0
  13. package/dist/fallback/index.d.mts +4 -4
  14. package/dist/fallback/index.d.ts +4 -4
  15. package/dist/http-BQxUT5A9.d.mts +9 -0
  16. package/dist/http-BQxUT5A9.d.ts +9 -0
  17. package/dist/index.d.mts +14 -8
  18. package/dist/index.d.ts +14 -8
  19. package/dist/index.js +599 -195
  20. package/dist/index.mjs +596 -196
  21. package/dist/providers/anthropic/index.d.mts +7 -4
  22. package/dist/providers/anthropic/index.d.ts +7 -4
  23. package/dist/providers/anthropic/index.js +383 -102
  24. package/dist/providers/anthropic/index.mjs +383 -102
  25. package/dist/providers/azure/index.d.mts +3 -3
  26. package/dist/providers/azure/index.d.ts +3 -3
  27. package/dist/providers/cloudflare/index.d.mts +11 -0
  28. package/dist/providers/cloudflare/index.d.ts +11 -0
  29. package/dist/providers/cloudflare/index.js +743 -0
  30. package/dist/providers/cloudflare/index.mjs +741 -0
  31. package/dist/providers/fireworks/index.d.mts +3 -3
  32. package/dist/providers/fireworks/index.d.ts +3 -3
  33. package/dist/providers/fireworks/index.js +108 -59
  34. package/dist/providers/fireworks/index.mjs +108 -59
  35. package/dist/providers/google/index.d.mts +3 -3
  36. package/dist/providers/google/index.d.ts +3 -3
  37. package/dist/providers/google/index.js +108 -59
  38. package/dist/providers/google/index.mjs +108 -59
  39. package/dist/providers/ollama/index.d.mts +4 -4
  40. package/dist/providers/ollama/index.d.ts +4 -4
  41. package/dist/providers/openai/index.d.mts +38 -6
  42. package/dist/providers/openai/index.d.ts +38 -6
  43. package/dist/providers/openai/index.js +1378 -84
  44. package/dist/providers/openai/index.mjs +1376 -85
  45. package/dist/providers/openrouter/index.d.mts +21 -4
  46. package/dist/providers/openrouter/index.d.ts +21 -4
  47. package/dist/providers/openrouter/index.js +967 -130
  48. package/dist/providers/openrouter/index.mjs +967 -131
  49. package/dist/providers/togetherai/index.d.mts +3 -3
  50. package/dist/providers/togetherai/index.d.ts +3 -3
  51. package/dist/providers/togetherai/index.js +108 -59
  52. package/dist/providers/togetherai/index.mjs +108 -59
  53. package/dist/providers/typesafe/index.d.mts +8 -0
  54. package/dist/providers/typesafe/index.d.ts +8 -0
  55. package/dist/providers/typesafe/index.js +735 -0
  56. package/dist/providers/typesafe/index.mjs +733 -0
  57. package/dist/providers/xai/index.d.mts +3 -3
  58. package/dist/providers/xai/index.d.ts +3 -3
  59. package/dist/providers/xai/index.js +108 -59
  60. package/dist/providers/xai/index.mjs +108 -59
  61. package/dist/{types-DCFqkJAy.d.ts → types-B0y6VZSQ.d.ts} +1 -1
  62. package/dist/{types-DHQEMFHA.d.mts → types-BXQMtaCX.d.ts} +17 -3
  63. package/dist/{types-C3RgRbEC.d.mts → types-BY6BVhFg.d.mts} +1 -1
  64. package/dist/{types-Dikj3En4.d.ts → types-C7_qVSSd.d.mts} +17 -3
  65. package/dist/{types-Dg1Bcg1k.d.mts → types-D7lzMMLu.d.mts} +13 -1
  66. package/dist/{types-Dg1Bcg1k.d.ts → types-D7lzMMLu.d.ts} +13 -1
  67. package/dist/yourgpt/index.d.mts +1 -1
  68. package/dist/yourgpt/index.d.ts +1 -1
  69. package/docs/decisions.md +174 -0
  70. package/docs/media.md +201 -0
  71. package/docs/multimodal-and-audio.md +9 -2
  72. package/package.json +34 -12
  73. package/dist/audio-BBSwnjo8.d.mts +0 -92
  74. package/dist/audio-BBSwnjo8.d.ts +0 -92
@@ -113,6 +113,19 @@ function capabilities(model) {
113
113
  const supportsNone = major === 5 && minor >= 1 && !chat || /^gpt-6-(?:sol|luna)(?:-\d{4}-\d{2}-\d{2})?$/i.test(model);
114
114
  return { major, minor, reasoning, supportsNone };
115
115
  }
116
+ function filterOpenAIResponseInclude(model, include, options = {}) {
117
+ const c = capabilities(model);
118
+ let result = include;
119
+ if (options.parameterPolicy !== "passthrough" && c.reasoning && !(options.reasoningEffort === "none" && c.supportsNone) && include.includes("message.output_text.logprobs")) {
120
+ result = include.filter(
121
+ (value) => value !== "message.output_text.logprobs"
122
+ );
123
+ (options.onWarning ?? console.warn)(
124
+ `[llm-sdk] ${model}: omitted message.output_text.logprobs because reasoning is enabled.`
125
+ );
126
+ }
127
+ return result.length ? result : void 0;
128
+ }
116
129
  function requiresOpenAIResponses(model, baseUrl, options = {}) {
117
130
  if (options.parameterPolicy === "passthrough") return false;
118
131
  const c = capabilities(model);
@@ -274,6 +287,7 @@ function toOpenAIResponseFormat(rf) {
274
287
  };
275
288
  }
276
289
  function toOpenAIResponsesTextFormat(rf) {
290
+ if (rf?.type === "json_object") return { type: "json_object" };
277
291
  if (!rf || rf.type !== "json_schema") return void 0;
278
292
  return {
279
293
  type: "json_schema",
@@ -668,6 +682,63 @@ function formatMessagesForGoogle(messages) {
668
682
  });
669
683
  }
670
684
 
685
+ // src/core/provider-error.ts
686
+ function invalidProviderResponse(message) {
687
+ return Object.assign(new Error(message), {
688
+ name: "InvalidProviderResponseError",
689
+ status: 502,
690
+ code: "INVALID_PROVIDER_RESPONSE"
691
+ });
692
+ }
693
+ function providerErrorEvent(error, code) {
694
+ const details = error ?? {};
695
+ const event = {
696
+ type: "error",
697
+ message: error instanceof Error ? error.message : String(error),
698
+ code,
699
+ ...typeof details.status === "number" ? { status: details.status } : {},
700
+ ...typeof details.code === "string" ? { providerCode: details.code } : {},
701
+ ...typeof details.param === "string" ? { param: details.param } : {},
702
+ ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
703
+ };
704
+ Object.defineProperty(event, "cause", { value: error, enumerable: false });
705
+ return event;
706
+ }
707
+ function throwIfAborted(signal) {
708
+ if (!signal?.aborted) return;
709
+ const error = new Error("The operation was aborted");
710
+ error.name = "AbortError";
711
+ throw error;
712
+ }
713
+
714
+ // src/core/tool-validation.ts
715
+ function parseToolArguments(value) {
716
+ let args = value;
717
+ if (typeof value === "string") {
718
+ try {
719
+ args = JSON.parse(value || "{}");
720
+ } catch {
721
+ throw invalidProviderResponse("Tool arguments are not valid JSON");
722
+ }
723
+ }
724
+ if (args === null || typeof args !== "object" || Array.isArray(args))
725
+ throw invalidProviderResponse("Tool arguments must be a JSON object");
726
+ return args;
727
+ }
728
+ function validateToolCalls(calls) {
729
+ const ids = /* @__PURE__ */ new Set();
730
+ for (const call of calls) {
731
+ if (!call || typeof call.id !== "string" || !call.id || typeof call.name !== "string" || !call.name || ids.has(call.id))
732
+ throw invalidProviderResponse(
733
+ "Tool calls have missing or duplicate identities"
734
+ );
735
+ ids.add(call.id);
736
+ if (typeof call.args === "string")
737
+ throw invalidProviderResponse("Parsed tool arguments must be an object");
738
+ parseToolArguments(call.args);
739
+ }
740
+ }
741
+
671
742
  // src/core/openai-responses.ts
672
743
  function resolveOpenAITransport(defaults, overrides) {
673
744
  return {
@@ -774,35 +845,6 @@ function getResponseReplay(metadata) {
774
845
  return responseReplayMetadata(metadata)?.openai?.response?.output;
775
846
  }
776
847
 
777
- // src/core/provider-error.ts
778
- function invalidProviderResponse(message) {
779
- return Object.assign(new Error(message), {
780
- name: "InvalidProviderResponseError",
781
- status: 502,
782
- code: "INVALID_PROVIDER_RESPONSE"
783
- });
784
- }
785
- function providerErrorEvent(error, code) {
786
- const details = error ?? {};
787
- const event = {
788
- type: "error",
789
- message: error instanceof Error ? error.message : String(error),
790
- code,
791
- ...typeof details.status === "number" ? { status: details.status } : {},
792
- ...typeof details.code === "string" ? { providerCode: details.code } : {},
793
- ...typeof details.param === "string" ? { param: details.param } : {},
794
- ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
795
- };
796
- Object.defineProperty(event, "cause", { value: error, enumerable: false });
797
- return event;
798
- }
799
- function throwIfAborted(signal) {
800
- if (!signal?.aborted) return;
801
- const error = new Error("The operation was aborted");
802
- error.name = "AbortError";
803
- throw error;
804
- }
805
-
806
848
  // src/core/utils.ts
807
849
  function generateId(prefix = "id") {
808
850
  return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
@@ -810,9 +852,6 @@ function generateId(prefix = "id") {
810
852
  function generateMessageId() {
811
853
  return generateId("msg");
812
854
  }
813
- function generateToolCallId() {
814
- return generateId("call");
815
- }
816
855
 
817
856
  // src/adapters/openai.ts
818
857
  var OpenAIAdapter = class _OpenAIAdapter {
@@ -836,6 +875,8 @@ var OpenAIAdapter = class _OpenAIAdapter {
836
875
  apiKey: this.config.apiKey,
837
876
  baseURL: this.config.baseUrl,
838
877
  organization: this.config.organization,
878
+ project: this.config.project,
879
+ timeout: this.config.timeout,
839
880
  defaultHeaders: this.config.headers
840
881
  });
841
882
  }
@@ -1117,6 +1158,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
1117
1158
  request.config?.responseFormat
1118
1159
  );
1119
1160
  const modelIdForPayload = request.config?.model || this.model;
1161
+ const include = filterOpenAIResponseInclude(
1162
+ modelIdForPayload,
1163
+ [
1164
+ .../* @__PURE__ */ new Set([
1165
+ ...options?.include ?? [],
1166
+ ...options?.store === false ? ["reasoning.encrypted_content"] : []
1167
+ ])
1168
+ ],
1169
+ this.parameterOptions(request)
1170
+ );
1120
1171
  const payload = {
1121
1172
  model: modelIdForPayload,
1122
1173
  instructions: request.systemPrompt,
@@ -1140,14 +1191,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
1140
1191
  ...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
1141
1192
  ...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
1142
1193
  ...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
1143
- ...options?.store === false || options?.include ? {
1144
- include: [
1145
- .../* @__PURE__ */ new Set([
1146
- ...options?.include ?? [],
1147
- ...options?.store === false ? ["reasoning.encrypted_content"] : []
1148
- ])
1149
- ]
1150
- } : {},
1194
+ ...include ? { include } : {},
1151
1195
  ...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
1152
1196
  stream
1153
1197
  };
@@ -1518,15 +1562,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1518
1562
  }
1519
1563
  throwIfAborted(request.signal);
1520
1564
  if (!finishReason)
1521
- throw new Error("OpenAI stream ended without a finish reason");
1565
+ throw invalidProviderResponse(
1566
+ "OpenAI stream ended without a finish reason"
1567
+ );
1522
1568
  if (toolCalls.size && !["tool_calls", "function_call"].includes(finishReason)) {
1523
- throw new Error("OpenAI stream ended with incomplete tool calls");
1524
- }
1525
- for (const call of toolCalls.values()) {
1526
- if (!call.id || !call.name)
1527
- throw new Error("OpenAI stream contains an incomplete tool call");
1528
- JSON.parse(call.arguments || "{}");
1569
+ throw invalidProviderResponse(
1570
+ "OpenAI stream ended with incomplete tool calls"
1571
+ );
1529
1572
  }
1573
+ validateToolCalls(
1574
+ [...toolCalls.values()].map((call) => ({
1575
+ ...call,
1576
+ args: parseToolArguments(call.arguments)
1577
+ }))
1578
+ );
1530
1579
  for (const call of toolCalls.values()) {
1531
1580
  yield {
1532
1581
  type: "action:start",
@@ -1610,20 +1659,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1610
1659
  logProviderPayload("openai", "response payload", response, request.debug);
1611
1660
  const choice = response.choices?.[0];
1612
1661
  const message = choice?.message;
1662
+ const toolCalls = (message?.tool_calls ?? []).map((toolCall) => ({
1663
+ id: toolCall.id,
1664
+ name: toolCall.function?.name,
1665
+ args: parseToolArguments(toolCall.function?.arguments ?? "{}"),
1666
+ ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1667
+ }));
1668
+ validateToolCalls(toolCalls);
1669
+ if (toolCalls.length && choice?.finish_reason && !["tool_calls", "function_call"].includes(choice.finish_reason))
1670
+ throw invalidProviderResponse(
1671
+ "OpenAI response ended with incomplete tool calls"
1672
+ );
1613
1673
  return {
1614
1674
  content: message?.content ?? "",
1615
- toolCalls: message?.tool_calls?.map((toolCall) => ({
1616
- id: toolCall.id ?? generateToolCallId(),
1617
- name: toolCall.function?.name ?? "",
1618
- args: (() => {
1619
- try {
1620
- return JSON.parse(toolCall.function?.arguments ?? "{}");
1621
- } catch {
1622
- return {};
1623
- }
1624
- })(),
1625
- ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1626
- })) ?? [],
1675
+ toolCalls,
1627
1676
  usage: response.usage ? {
1628
1677
  promptTokens: response.usage.prompt_tokens,
1629
1678
  completionTokens: response.usage.completion_tokens,
@@ -111,6 +111,19 @@ function capabilities(model) {
111
111
  const supportsNone = major === 5 && minor >= 1 && !chat || /^gpt-6-(?:sol|luna)(?:-\d{4}-\d{2}-\d{2})?$/i.test(model);
112
112
  return { major, minor, reasoning, supportsNone };
113
113
  }
114
+ function filterOpenAIResponseInclude(model, include, options = {}) {
115
+ const c = capabilities(model);
116
+ let result = include;
117
+ if (options.parameterPolicy !== "passthrough" && c.reasoning && !(options.reasoningEffort === "none" && c.supportsNone) && include.includes("message.output_text.logprobs")) {
118
+ result = include.filter(
119
+ (value) => value !== "message.output_text.logprobs"
120
+ );
121
+ (options.onWarning ?? console.warn)(
122
+ `[llm-sdk] ${model}: omitted message.output_text.logprobs because reasoning is enabled.`
123
+ );
124
+ }
125
+ return result.length ? result : void 0;
126
+ }
114
127
  function requiresOpenAIResponses(model, baseUrl, options = {}) {
115
128
  if (options.parameterPolicy === "passthrough") return false;
116
129
  const c = capabilities(model);
@@ -272,6 +285,7 @@ function toOpenAIResponseFormat(rf) {
272
285
  };
273
286
  }
274
287
  function toOpenAIResponsesTextFormat(rf) {
288
+ if (rf?.type === "json_object") return { type: "json_object" };
275
289
  if (!rf || rf.type !== "json_schema") return void 0;
276
290
  return {
277
291
  type: "json_schema",
@@ -666,6 +680,63 @@ function formatMessagesForGoogle(messages) {
666
680
  });
667
681
  }
668
682
 
683
+ // src/core/provider-error.ts
684
+ function invalidProviderResponse(message) {
685
+ return Object.assign(new Error(message), {
686
+ name: "InvalidProviderResponseError",
687
+ status: 502,
688
+ code: "INVALID_PROVIDER_RESPONSE"
689
+ });
690
+ }
691
+ function providerErrorEvent(error, code) {
692
+ const details = error ?? {};
693
+ const event = {
694
+ type: "error",
695
+ message: error instanceof Error ? error.message : String(error),
696
+ code,
697
+ ...typeof details.status === "number" ? { status: details.status } : {},
698
+ ...typeof details.code === "string" ? { providerCode: details.code } : {},
699
+ ...typeof details.param === "string" ? { param: details.param } : {},
700
+ ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
701
+ };
702
+ Object.defineProperty(event, "cause", { value: error, enumerable: false });
703
+ return event;
704
+ }
705
+ function throwIfAborted(signal) {
706
+ if (!signal?.aborted) return;
707
+ const error = new Error("The operation was aborted");
708
+ error.name = "AbortError";
709
+ throw error;
710
+ }
711
+
712
+ // src/core/tool-validation.ts
713
+ function parseToolArguments(value) {
714
+ let args = value;
715
+ if (typeof value === "string") {
716
+ try {
717
+ args = JSON.parse(value || "{}");
718
+ } catch {
719
+ throw invalidProviderResponse("Tool arguments are not valid JSON");
720
+ }
721
+ }
722
+ if (args === null || typeof args !== "object" || Array.isArray(args))
723
+ throw invalidProviderResponse("Tool arguments must be a JSON object");
724
+ return args;
725
+ }
726
+ function validateToolCalls(calls) {
727
+ const ids = /* @__PURE__ */ new Set();
728
+ for (const call of calls) {
729
+ if (!call || typeof call.id !== "string" || !call.id || typeof call.name !== "string" || !call.name || ids.has(call.id))
730
+ throw invalidProviderResponse(
731
+ "Tool calls have missing or duplicate identities"
732
+ );
733
+ ids.add(call.id);
734
+ if (typeof call.args === "string")
735
+ throw invalidProviderResponse("Parsed tool arguments must be an object");
736
+ parseToolArguments(call.args);
737
+ }
738
+ }
739
+
669
740
  // src/core/openai-responses.ts
670
741
  function resolveOpenAITransport(defaults, overrides) {
671
742
  return {
@@ -772,35 +843,6 @@ function getResponseReplay(metadata) {
772
843
  return responseReplayMetadata(metadata)?.openai?.response?.output;
773
844
  }
774
845
 
775
- // src/core/provider-error.ts
776
- function invalidProviderResponse(message) {
777
- return Object.assign(new Error(message), {
778
- name: "InvalidProviderResponseError",
779
- status: 502,
780
- code: "INVALID_PROVIDER_RESPONSE"
781
- });
782
- }
783
- function providerErrorEvent(error, code) {
784
- const details = error ?? {};
785
- const event = {
786
- type: "error",
787
- message: error instanceof Error ? error.message : String(error),
788
- code,
789
- ...typeof details.status === "number" ? { status: details.status } : {},
790
- ...typeof details.code === "string" ? { providerCode: details.code } : {},
791
- ...typeof details.param === "string" ? { param: details.param } : {},
792
- ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
793
- };
794
- Object.defineProperty(event, "cause", { value: error, enumerable: false });
795
- return event;
796
- }
797
- function throwIfAborted(signal) {
798
- if (!signal?.aborted) return;
799
- const error = new Error("The operation was aborted");
800
- error.name = "AbortError";
801
- throw error;
802
- }
803
-
804
846
  // src/core/utils.ts
805
847
  function generateId(prefix = "id") {
806
848
  return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
@@ -808,9 +850,6 @@ function generateId(prefix = "id") {
808
850
  function generateMessageId() {
809
851
  return generateId("msg");
810
852
  }
811
- function generateToolCallId() {
812
- return generateId("call");
813
- }
814
853
 
815
854
  // src/adapters/openai.ts
816
855
  var OpenAIAdapter = class _OpenAIAdapter {
@@ -834,6 +873,8 @@ var OpenAIAdapter = class _OpenAIAdapter {
834
873
  apiKey: this.config.apiKey,
835
874
  baseURL: this.config.baseUrl,
836
875
  organization: this.config.organization,
876
+ project: this.config.project,
877
+ timeout: this.config.timeout,
837
878
  defaultHeaders: this.config.headers
838
879
  });
839
880
  }
@@ -1115,6 +1156,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
1115
1156
  request.config?.responseFormat
1116
1157
  );
1117
1158
  const modelIdForPayload = request.config?.model || this.model;
1159
+ const include = filterOpenAIResponseInclude(
1160
+ modelIdForPayload,
1161
+ [
1162
+ .../* @__PURE__ */ new Set([
1163
+ ...options?.include ?? [],
1164
+ ...options?.store === false ? ["reasoning.encrypted_content"] : []
1165
+ ])
1166
+ ],
1167
+ this.parameterOptions(request)
1168
+ );
1118
1169
  const payload = {
1119
1170
  model: modelIdForPayload,
1120
1171
  instructions: request.systemPrompt,
@@ -1138,14 +1189,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
1138
1189
  ...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
1139
1190
  ...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
1140
1191
  ...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
1141
- ...options?.store === false || options?.include ? {
1142
- include: [
1143
- .../* @__PURE__ */ new Set([
1144
- ...options?.include ?? [],
1145
- ...options?.store === false ? ["reasoning.encrypted_content"] : []
1146
- ])
1147
- ]
1148
- } : {},
1192
+ ...include ? { include } : {},
1149
1193
  ...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
1150
1194
  stream
1151
1195
  };
@@ -1516,15 +1560,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1516
1560
  }
1517
1561
  throwIfAborted(request.signal);
1518
1562
  if (!finishReason)
1519
- throw new Error("OpenAI stream ended without a finish reason");
1563
+ throw invalidProviderResponse(
1564
+ "OpenAI stream ended without a finish reason"
1565
+ );
1520
1566
  if (toolCalls.size && !["tool_calls", "function_call"].includes(finishReason)) {
1521
- throw new Error("OpenAI stream ended with incomplete tool calls");
1522
- }
1523
- for (const call of toolCalls.values()) {
1524
- if (!call.id || !call.name)
1525
- throw new Error("OpenAI stream contains an incomplete tool call");
1526
- JSON.parse(call.arguments || "{}");
1567
+ throw invalidProviderResponse(
1568
+ "OpenAI stream ended with incomplete tool calls"
1569
+ );
1527
1570
  }
1571
+ validateToolCalls(
1572
+ [...toolCalls.values()].map((call) => ({
1573
+ ...call,
1574
+ args: parseToolArguments(call.arguments)
1575
+ }))
1576
+ );
1528
1577
  for (const call of toolCalls.values()) {
1529
1578
  yield {
1530
1579
  type: "action:start",
@@ -1608,20 +1657,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1608
1657
  logProviderPayload("openai", "response payload", response, request.debug);
1609
1658
  const choice = response.choices?.[0];
1610
1659
  const message = choice?.message;
1660
+ const toolCalls = (message?.tool_calls ?? []).map((toolCall) => ({
1661
+ id: toolCall.id,
1662
+ name: toolCall.function?.name,
1663
+ args: parseToolArguments(toolCall.function?.arguments ?? "{}"),
1664
+ ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1665
+ }));
1666
+ validateToolCalls(toolCalls);
1667
+ if (toolCalls.length && choice?.finish_reason && !["tool_calls", "function_call"].includes(choice.finish_reason))
1668
+ throw invalidProviderResponse(
1669
+ "OpenAI response ended with incomplete tool calls"
1670
+ );
1611
1671
  return {
1612
1672
  content: message?.content ?? "",
1613
- toolCalls: message?.tool_calls?.map((toolCall) => ({
1614
- id: toolCall.id ?? generateToolCallId(),
1615
- name: toolCall.function?.name ?? "",
1616
- args: (() => {
1617
- try {
1618
- return JSON.parse(toolCall.function?.arguments ?? "{}");
1619
- } catch {
1620
- return {};
1621
- }
1622
- })(),
1623
- ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1624
- })) ?? [],
1673
+ toolCalls,
1625
1674
  usage: response.usage ? {
1626
1675
  promptTokens: response.usage.prompt_tokens,
1627
1676
  completionTokens: response.usage.completion_tokens,
@@ -1,8 +1,8 @@
1
- import { c as OllamaProviderConfig, A as AIProvider } from '../../types-DHQEMFHA.mjs';
2
- export { d as OllamaModelOptions } from '../../types-DHQEMFHA.mjs';
3
- import '../../types-Dg1Bcg1k.mjs';
1
+ import { c as OllamaProviderConfig, A as AIProvider } from '../../types-C7_qVSSd.mjs';
2
+ export { d as OllamaModelOptions } from '../../types-C7_qVSSd.mjs';
3
+ import '../../types-D7lzMMLu.mjs';
4
4
  import 'zod';
5
- import '../../base-BICaQaRS.mjs';
5
+ import '../../base-DySbTP8C.mjs';
6
6
 
7
7
  /**
8
8
  * Ollama Provider
@@ -1,8 +1,8 @@
1
- import { c as OllamaProviderConfig, A as AIProvider } from '../../types-Dikj3En4.js';
2
- export { d as OllamaModelOptions } from '../../types-Dikj3En4.js';
3
- import '../../types-Dg1Bcg1k.js';
1
+ import { c as OllamaProviderConfig, A as AIProvider } from '../../types-BXQMtaCX.js';
2
+ export { d as OllamaModelOptions } from '../../types-BXQMtaCX.js';
3
+ import '../../types-D7lzMMLu.js';
4
4
  import 'zod';
5
- import '../../base-CpRPB8u8.js';
5
+ import '../../base-6LzczuCg.js';
6
6
 
7
7
  /**
8
8
  * Ollama Provider
@@ -1,9 +1,11 @@
1
- import { ae as OpenAIParameterOptions, O as OpenAITransportOptions, L as LanguageModel } from '../../types-Dg1Bcg1k.mjs';
2
- export { h as OpenAIReasoningEffort, ab as OpenAIResponseItem, ac as OpenAIResponseMetadata, aa as OpenAIResponsesOptions, P as ProviderMetadata } from '../../types-Dg1Bcg1k.mjs';
3
- import { O as OpenAIProviderConfig, A as AIProvider } from '../../types-DHQEMFHA.mjs';
4
- import { S as SpeechModel, T as TranscriptionModel } from '../../audio-BBSwnjo8.mjs';
1
+ import { ae as OpenAIParameterOptions, O as OpenAITransportOptions, L as LanguageModel } from '../../types-D7lzMMLu.mjs';
2
+ export { h as OpenAIReasoningEffort, ab as OpenAIResponseItem, ac as OpenAIResponseMetadata, aa as OpenAIResponsesOptions, P as ProviderMetadata } from '../../types-D7lzMMLu.mjs';
3
+ import { j as DecisionModel } from '../../decisions-CJzOt87t.mjs';
4
+ import { D as DecisionProviderOptions } from '../../http-BQxUT5A9.mjs';
5
+ import { O as OpenAIProviderConfig, A as AIProvider } from '../../types-C7_qVSSd.mjs';
6
+ import { S as SpeechModel, T as TranscriptionModel, c as ImageModel, f as RealtimeModel } from '../../audio-K-Z3-Bce.mjs';
5
7
  import 'zod';
6
- import '../../base-BICaQaRS.mjs';
8
+ import '../../base-DySbTP8C.mjs';
7
9
 
8
10
  interface OpenAIProviderOptions extends OpenAIParameterOptions, OpenAITransportOptions {
9
11
  /** API key (defaults to OPENAI_API_KEY env var) */
@@ -36,6 +38,13 @@ interface OpenAIProviderOptions extends OpenAIParameterOptions, OpenAITransportO
36
38
  */
37
39
  declare function openai(modelId: string, options?: OpenAIProviderOptions): LanguageModel;
38
40
 
41
+ interface OpenAIDecisionProviderOptions extends DecisionProviderOptions {
42
+ organization?: string;
43
+ project?: string;
44
+ }
45
+ /** Native /v1/decisions. Independent of the optional OpenAI npm client. */
46
+ declare function openaiDecision(modelId?: string, options?: OpenAIDecisionProviderOptions): DecisionModel;
47
+
39
48
  interface OpenAIAudioProviderOptions {
40
49
  apiKey?: string;
41
50
  baseUrl?: string;
@@ -54,6 +63,29 @@ declare function openaiSpeech(modelId?: string, config?: OpenAIAudioProviderOpti
54
63
  /** Recorded-file transcription. Timestamp and diarization options are model-gated. */
55
64
  declare function openaiTranscription(modelId?: string, config?: OpenAIAudioProviderOptions): TranscriptionModel;
56
65
 
66
+ interface OpenAIMediaProviderOptions {
67
+ apiKey?: string;
68
+ baseUrl?: string;
69
+ organization?: string;
70
+ project?: string;
71
+ fetch?: typeof globalThis.fetch;
72
+ }
73
+
74
+ interface OpenAIImageOptions {
75
+ quality?: "auto" | "low" | "medium" | "high" | "xhigh" | "max";
76
+ background?: "auto" | "opaque" | "transparent";
77
+ outputFormat?: "png" | "jpeg" | "webp";
78
+ outputCompression?: number;
79
+ moderation?: "auto" | "low";
80
+ inputFidelity?: "high" | "low";
81
+ safetyIdentifier?: string;
82
+ }
83
+ /** Server-side Images API generation/editing. Does not change chat or Responses models. */
84
+ declare function openaiImage(modelId?: string, config?: OpenAIMediaProviderOptions): ImageModel;
85
+
86
+ /** OpenAI GA Realtime. GPT-Live has a different protocol and is intentionally rejected. */
87
+ declare function openaiRealtime(modelId?: string, config?: OpenAIMediaProviderOptions): RealtimeModel;
88
+
57
89
  /**
58
90
  * OpenAI Provider
59
91
  *
@@ -86,4 +118,4 @@ declare function openaiTranscription(modelId?: string, config?: OpenAIAudioProvi
86
118
  declare function createOpenAI(config?: OpenAIProviderConfig): AIProvider;
87
119
  declare const createOpenAIProvider: typeof createOpenAI;
88
120
 
89
- export { type OpenAIAudioProviderOptions, OpenAIParameterOptions, type OpenAIProviderOptions, type OpenAITranscriptionOptions, OpenAITransportOptions, createOpenAI, openai as createOpenAIModel, createOpenAIProvider, openai, openaiSpeech, openaiTranscription };
121
+ export { type OpenAIAudioProviderOptions, type OpenAIDecisionProviderOptions, type OpenAIImageOptions, type OpenAIMediaProviderOptions, OpenAIParameterOptions, type OpenAIProviderOptions, type OpenAITranscriptionOptions, OpenAITransportOptions, createOpenAI, openai as createOpenAIModel, createOpenAIProvider, openai, openaiDecision, openaiImage, openaiRealtime, openaiSpeech, openaiTranscription };
@@ -1,9 +1,11 @@
1
- import { ae as OpenAIParameterOptions, O as OpenAITransportOptions, L as LanguageModel } from '../../types-Dg1Bcg1k.js';
2
- export { h as OpenAIReasoningEffort, ab as OpenAIResponseItem, ac as OpenAIResponseMetadata, aa as OpenAIResponsesOptions, P as ProviderMetadata } from '../../types-Dg1Bcg1k.js';
3
- import { O as OpenAIProviderConfig, A as AIProvider } from '../../types-Dikj3En4.js';
4
- import { S as SpeechModel, T as TranscriptionModel } from '../../audio-BBSwnjo8.js';
1
+ import { ae as OpenAIParameterOptions, O as OpenAITransportOptions, L as LanguageModel } from '../../types-D7lzMMLu.js';
2
+ export { h as OpenAIReasoningEffort, ab as OpenAIResponseItem, ac as OpenAIResponseMetadata, aa as OpenAIResponsesOptions, P as ProviderMetadata } from '../../types-D7lzMMLu.js';
3
+ import { j as DecisionModel } from '../../decisions-CJzOt87t.js';
4
+ import { D as DecisionProviderOptions } from '../../http-BQxUT5A9.js';
5
+ import { O as OpenAIProviderConfig, A as AIProvider } from '../../types-BXQMtaCX.js';
6
+ import { S as SpeechModel, T as TranscriptionModel, c as ImageModel, f as RealtimeModel } from '../../audio-K-Z3-Bce.js';
5
7
  import 'zod';
6
- import '../../base-CpRPB8u8.js';
8
+ import '../../base-6LzczuCg.js';
7
9
 
8
10
  interface OpenAIProviderOptions extends OpenAIParameterOptions, OpenAITransportOptions {
9
11
  /** API key (defaults to OPENAI_API_KEY env var) */
@@ -36,6 +38,13 @@ interface OpenAIProviderOptions extends OpenAIParameterOptions, OpenAITransportO
36
38
  */
37
39
  declare function openai(modelId: string, options?: OpenAIProviderOptions): LanguageModel;
38
40
 
41
+ interface OpenAIDecisionProviderOptions extends DecisionProviderOptions {
42
+ organization?: string;
43
+ project?: string;
44
+ }
45
+ /** Native /v1/decisions. Independent of the optional OpenAI npm client. */
46
+ declare function openaiDecision(modelId?: string, options?: OpenAIDecisionProviderOptions): DecisionModel;
47
+
39
48
  interface OpenAIAudioProviderOptions {
40
49
  apiKey?: string;
41
50
  baseUrl?: string;
@@ -54,6 +63,29 @@ declare function openaiSpeech(modelId?: string, config?: OpenAIAudioProviderOpti
54
63
  /** Recorded-file transcription. Timestamp and diarization options are model-gated. */
55
64
  declare function openaiTranscription(modelId?: string, config?: OpenAIAudioProviderOptions): TranscriptionModel;
56
65
 
66
+ interface OpenAIMediaProviderOptions {
67
+ apiKey?: string;
68
+ baseUrl?: string;
69
+ organization?: string;
70
+ project?: string;
71
+ fetch?: typeof globalThis.fetch;
72
+ }
73
+
74
+ interface OpenAIImageOptions {
75
+ quality?: "auto" | "low" | "medium" | "high" | "xhigh" | "max";
76
+ background?: "auto" | "opaque" | "transparent";
77
+ outputFormat?: "png" | "jpeg" | "webp";
78
+ outputCompression?: number;
79
+ moderation?: "auto" | "low";
80
+ inputFidelity?: "high" | "low";
81
+ safetyIdentifier?: string;
82
+ }
83
+ /** Server-side Images API generation/editing. Does not change chat or Responses models. */
84
+ declare function openaiImage(modelId?: string, config?: OpenAIMediaProviderOptions): ImageModel;
85
+
86
+ /** OpenAI GA Realtime. GPT-Live has a different protocol and is intentionally rejected. */
87
+ declare function openaiRealtime(modelId?: string, config?: OpenAIMediaProviderOptions): RealtimeModel;
88
+
57
89
  /**
58
90
  * OpenAI Provider
59
91
  *
@@ -86,4 +118,4 @@ declare function openaiTranscription(modelId?: string, config?: OpenAIAudioProvi
86
118
  declare function createOpenAI(config?: OpenAIProviderConfig): AIProvider;
87
119
  declare const createOpenAIProvider: typeof createOpenAI;
88
120
 
89
- export { type OpenAIAudioProviderOptions, OpenAIParameterOptions, type OpenAIProviderOptions, type OpenAITranscriptionOptions, OpenAITransportOptions, createOpenAI, openai as createOpenAIModel, createOpenAIProvider, openai, openaiSpeech, openaiTranscription };
121
+ export { type OpenAIAudioProviderOptions, type OpenAIDecisionProviderOptions, type OpenAIImageOptions, type OpenAIMediaProviderOptions, OpenAIParameterOptions, type OpenAIProviderOptions, type OpenAITranscriptionOptions, OpenAITransportOptions, createOpenAI, openai as createOpenAIModel, createOpenAIProvider, openai, openaiDecision, openaiImage, openaiRealtime, openaiSpeech, openaiTranscription };