@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.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -17
  3. package/dist/adapters/index.d.mts +11 -13
  4. package/dist/adapters/index.d.ts +11 -13
  5. package/dist/adapters/index.js +406 -114
  6. package/dist/adapters/index.mjs +406 -114
  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 +17 -9
  18. package/dist/index.d.ts +17 -9
  19. package/dist/index.js +698 -205
  20. package/dist/index.mjs +695 -206
  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 +389 -115
  24. package/dist/providers/anthropic/index.mjs +389 -115
  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 +181 -60
  34. package/dist/providers/fireworks/index.mjs +181 -60
  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 +181 -60
  38. package/dist/providers/google/index.mjs +181 -60
  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 +1451 -85
  44. package/dist/providers/openai/index.mjs +1449 -86
  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 +1040 -131
  48. package/dist/providers/openrouter/index.mjs +1040 -132
  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 +181 -60
  52. package/dist/providers/togetherai/index.mjs +181 -60
  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 +181 -60
  60. package/dist/providers/xai/index.mjs +181 -60
  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
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-Dg1Bcg1k.mjs';
2
- import { X as XAIProviderConfig, A as AIProvider } from '../../types-DHQEMFHA.mjs';
1
+ import { L as LanguageModel } from '../../types-D7lzMMLu.mjs';
2
+ import { X as XAIProviderConfig, A as AIProvider } from '../../types-C7_qVSSd.mjs';
3
3
  import 'zod';
4
- import '../../base-BICaQaRS.mjs';
4
+ import '../../base-DySbTP8C.mjs';
5
5
 
6
6
  /**
7
7
  * xAI Provider - Modern Pattern
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-Dg1Bcg1k.js';
2
- import { X as XAIProviderConfig, A as AIProvider } from '../../types-Dikj3En4.js';
1
+ import { L as LanguageModel } from '../../types-D7lzMMLu.js';
2
+ import { X as XAIProviderConfig, A as AIProvider } from '../../types-BXQMtaCX.js';
3
3
  import 'zod';
4
- import '../../base-CpRPB8u8.js';
4
+ import '../../base-6LzczuCg.js';
5
5
 
6
6
  /**
7
7
  * xAI Provider - Modern Pattern
@@ -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",
@@ -617,6 +631,63 @@ function formatMessagesForXAI(messages) {
617
631
  });
618
632
  }
619
633
 
634
+ // src/core/provider-error.ts
635
+ function invalidProviderResponse(message) {
636
+ return Object.assign(new Error(message), {
637
+ name: "InvalidProviderResponseError",
638
+ status: 502,
639
+ code: "INVALID_PROVIDER_RESPONSE"
640
+ });
641
+ }
642
+ function providerErrorEvent(error, code) {
643
+ const details = error ?? {};
644
+ const event = {
645
+ type: "error",
646
+ message: error instanceof Error ? error.message : String(error),
647
+ code,
648
+ ...typeof details.status === "number" ? { status: details.status } : {},
649
+ ...typeof details.code === "string" ? { providerCode: details.code } : {},
650
+ ...typeof details.param === "string" ? { param: details.param } : {},
651
+ ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
652
+ };
653
+ Object.defineProperty(event, "cause", { value: error, enumerable: false });
654
+ return event;
655
+ }
656
+ function throwIfAborted(signal) {
657
+ if (!signal?.aborted) return;
658
+ const error = new Error("The operation was aborted");
659
+ error.name = "AbortError";
660
+ throw error;
661
+ }
662
+
663
+ // src/core/tool-validation.ts
664
+ function parseToolArguments(value) {
665
+ let args = value;
666
+ if (typeof value === "string") {
667
+ try {
668
+ args = JSON.parse(value || "{}");
669
+ } catch {
670
+ throw invalidProviderResponse("Tool arguments are not valid JSON");
671
+ }
672
+ }
673
+ if (args === null || typeof args !== "object" || Array.isArray(args))
674
+ throw invalidProviderResponse("Tool arguments must be a JSON object");
675
+ return args;
676
+ }
677
+ function validateToolCalls(calls) {
678
+ const ids = /* @__PURE__ */ new Set();
679
+ for (const call of calls) {
680
+ if (!call || typeof call.id !== "string" || !call.id || typeof call.name !== "string" || !call.name || ids.has(call.id))
681
+ throw invalidProviderResponse(
682
+ "Tool calls have missing or duplicate identities"
683
+ );
684
+ ids.add(call.id);
685
+ if (typeof call.args === "string")
686
+ throw invalidProviderResponse("Parsed tool arguments must be an object");
687
+ parseToolArguments(call.args);
688
+ }
689
+ }
690
+
620
691
  // src/core/openai-responses.ts
621
692
  function resolveOpenAITransport(defaults, overrides) {
622
693
  return {
@@ -664,6 +735,54 @@ function responseMetadata(response) {
664
735
  }
665
736
  };
666
737
  }
738
+ function responseReplayMetadata(metadata) {
739
+ const response = metadata?.openai?.response;
740
+ if (!response) return metadata;
741
+ const output = response.output.map((item) => {
742
+ const fields = ["type", "id", "status"];
743
+ switch (item.type) {
744
+ case "reasoning":
745
+ fields.push("encrypted_content");
746
+ break;
747
+ case "message":
748
+ fields.push("role", "phase");
749
+ break;
750
+ case "function_call":
751
+ fields.push("call_id", "name", "namespace", "arguments");
752
+ break;
753
+ case "tool_search_call":
754
+ fields.push("call_id", "execution", "arguments");
755
+ break;
756
+ case "tool_search_output":
757
+ fields.push("call_id", "tools");
758
+ break;
759
+ case "web_search_call":
760
+ fields.push("action");
761
+ break;
762
+ default:
763
+ return stripItemDiagnostics(item);
764
+ }
765
+ const replay = Object.fromEntries(
766
+ fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
767
+ );
768
+ if (item.type === "reasoning") replay.summary = [];
769
+ if (item.type === "message")
770
+ replay.content = Array.isArray(item.content) ? item.content.flatMap(
771
+ (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 }] : []
772
+ ) : [];
773
+ return stripItemDiagnostics(replay);
774
+ });
775
+ return { openai: { response: { output, refusals: [] } } };
776
+ }
777
+ function stripItemDiagnostics(item) {
778
+ const {
779
+ usage: _usage,
780
+ logprobs: _logprobs,
781
+ metadata: _metadata,
782
+ ...state
783
+ } = item;
784
+ return state;
785
+ }
667
786
  function getResponseReplay(metadata) {
668
787
  const response = metadata?.openai?.response;
669
788
  if (response === void 0) return void 0;
@@ -672,29 +791,7 @@ function getResponseReplay(metadata) {
672
791
  "Invalid OpenAI Responses replay metadata: output must contain typed items"
673
792
  );
674
793
  }
675
- return response.output;
676
- }
677
-
678
- // src/core/provider-error.ts
679
- function providerErrorEvent(error, code) {
680
- const details = error ?? {};
681
- const event = {
682
- type: "error",
683
- message: error instanceof Error ? error.message : String(error),
684
- code,
685
- ...typeof details.status === "number" ? { status: details.status } : {},
686
- ...typeof details.code === "string" ? { providerCode: details.code } : {},
687
- ...typeof details.param === "string" ? { param: details.param } : {},
688
- ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
689
- };
690
- Object.defineProperty(event, "cause", { value: error, enumerable: false });
691
- return event;
692
- }
693
- function throwIfAborted(signal) {
694
- if (!signal?.aborted) return;
695
- const error = new Error("The operation was aborted");
696
- error.name = "AbortError";
697
- throw error;
794
+ return responseReplayMetadata(metadata)?.openai?.response?.output;
698
795
  }
699
796
 
700
797
  // src/core/utils.ts
@@ -704,9 +801,6 @@ function generateId(prefix = "id") {
704
801
  function generateMessageId() {
705
802
  return generateId("msg");
706
803
  }
707
- function generateToolCallId() {
708
- return generateId("call");
709
- }
710
804
 
711
805
  // src/adapters/openai.ts
712
806
  var OpenAIAdapter = class _OpenAIAdapter {
@@ -730,6 +824,8 @@ var OpenAIAdapter = class _OpenAIAdapter {
730
824
  apiKey: this.config.apiKey,
731
825
  baseURL: this.config.baseUrl,
732
826
  organization: this.config.organization,
827
+ project: this.config.project,
828
+ timeout: this.config.timeout,
733
829
  defaultHeaders: this.config.headers
734
830
  });
735
831
  }
@@ -852,7 +948,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
852
948
  formatRawMessages(messages, preserveProviderMetadata = false) {
853
949
  return messages.map((message) => {
854
950
  const { attachments, providerMetadata, modelOutput, ...rest } = message;
855
- let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput, String(message.content ?? "")) : message.content;
951
+ let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
856
952
  if (preserveProviderMetadata && modelOutput)
857
953
  rest.modelOutput = modelOutput;
858
954
  if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
@@ -955,17 +1051,32 @@ var OpenAIAdapter = class _OpenAIAdapter {
955
1051
  const seenCallIds = /* @__PURE__ */ new Set();
956
1052
  const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
957
1053
  if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
958
- throw new Error("Responses contains an incomplete function call");
1054
+ throw invalidProviderResponse(
1055
+ "Responses contains an incomplete function call"
1056
+ );
959
1057
  }
960
1058
  if (seenCallIds.has(item.call_id))
961
- throw new Error("Responses contains duplicate function call IDs");
1059
+ throw invalidProviderResponse(
1060
+ "Responses contains duplicate function call IDs"
1061
+ );
962
1062
  seenCallIds.add(item.call_id);
963
- const args = JSON.parse(item.arguments);
1063
+ let args;
1064
+ try {
1065
+ args = JSON.parse(item.arguments);
1066
+ } catch {
1067
+ throw invalidProviderResponse(
1068
+ "Responses function arguments must be valid JSON"
1069
+ );
1070
+ }
964
1071
  if (!args || typeof args !== "object" || Array.isArray(args))
965
- throw new Error(
1072
+ throw invalidProviderResponse(
966
1073
  "Responses function arguments must be a JSON object"
967
1074
  );
968
- return { id: item.call_id, name: item.name, args };
1075
+ return {
1076
+ id: item.call_id,
1077
+ name: item.name,
1078
+ args
1079
+ };
969
1080
  }) : [];
970
1081
  return {
971
1082
  content,
@@ -996,6 +1107,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
996
1107
  request.config?.responseFormat
997
1108
  );
998
1109
  const modelIdForPayload = request.config?.model || this.model;
1110
+ const include = filterOpenAIResponseInclude(
1111
+ modelIdForPayload,
1112
+ [
1113
+ .../* @__PURE__ */ new Set([
1114
+ ...options?.include ?? [],
1115
+ ...options?.store === false ? ["reasoning.encrypted_content"] : []
1116
+ ])
1117
+ ],
1118
+ this.parameterOptions(request)
1119
+ );
999
1120
  const payload = {
1000
1121
  model: modelIdForPayload,
1001
1122
  instructions: request.systemPrompt,
@@ -1019,14 +1140,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
1019
1140
  ...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
1020
1141
  ...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
1021
1142
  ...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
1022
- ...options?.store === false || options?.include ? {
1023
- include: [
1024
- .../* @__PURE__ */ new Set([
1025
- ...options?.include ?? [],
1026
- ...options?.store === false ? ["reasoning.encrypted_content"] : []
1027
- ])
1028
- ]
1029
- } : {},
1143
+ ...include ? { include } : {},
1030
1144
  ...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
1031
1145
  stream
1032
1146
  };
@@ -1208,7 +1322,9 @@ var OpenAIAdapter = class _OpenAIAdapter {
1208
1322
  const uniqueCalls = /* @__PURE__ */ new Map();
1209
1323
  for (const call of toolCalls.values()) {
1210
1324
  if (!call.id || !call.name)
1211
- throw new Error("Responses stream contains an incomplete tool call");
1325
+ throw invalidProviderResponse(
1326
+ "Responses stream contains an incomplete tool call"
1327
+ );
1212
1328
  uniqueCalls.set(call.id, call);
1213
1329
  }
1214
1330
  toolCalls.clear();
@@ -1395,15 +1511,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1395
1511
  }
1396
1512
  throwIfAborted(request.signal);
1397
1513
  if (!finishReason)
1398
- throw new Error("OpenAI stream ended without a finish reason");
1514
+ throw invalidProviderResponse(
1515
+ "OpenAI stream ended without a finish reason"
1516
+ );
1399
1517
  if (toolCalls.size && !["tool_calls", "function_call"].includes(finishReason)) {
1400
- throw new Error("OpenAI stream ended with incomplete tool calls");
1401
- }
1402
- for (const call of toolCalls.values()) {
1403
- if (!call.id || !call.name)
1404
- throw new Error("OpenAI stream contains an incomplete tool call");
1405
- JSON.parse(call.arguments || "{}");
1518
+ throw invalidProviderResponse(
1519
+ "OpenAI stream ended with incomplete tool calls"
1520
+ );
1406
1521
  }
1522
+ validateToolCalls(
1523
+ [...toolCalls.values()].map((call) => ({
1524
+ ...call,
1525
+ args: parseToolArguments(call.arguments)
1526
+ }))
1527
+ );
1407
1528
  for (const call of toolCalls.values()) {
1408
1529
  yield {
1409
1530
  type: "action:start",
@@ -1487,20 +1608,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1487
1608
  logProviderPayload("openai", "response payload", response, request.debug);
1488
1609
  const choice = response.choices?.[0];
1489
1610
  const message = choice?.message;
1611
+ const toolCalls = (message?.tool_calls ?? []).map((toolCall) => ({
1612
+ id: toolCall.id,
1613
+ name: toolCall.function?.name,
1614
+ args: parseToolArguments(toolCall.function?.arguments ?? "{}"),
1615
+ ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1616
+ }));
1617
+ validateToolCalls(toolCalls);
1618
+ if (toolCalls.length && choice?.finish_reason && !["tool_calls", "function_call"].includes(choice.finish_reason))
1619
+ throw invalidProviderResponse(
1620
+ "OpenAI response ended with incomplete tool calls"
1621
+ );
1490
1622
  return {
1491
1623
  content: message?.content ?? "",
1492
- toolCalls: message?.tool_calls?.map((toolCall) => ({
1493
- id: toolCall.id ?? generateToolCallId(),
1494
- name: toolCall.function?.name ?? "",
1495
- args: (() => {
1496
- try {
1497
- return JSON.parse(toolCall.function?.arguments ?? "{}");
1498
- } catch {
1499
- return {};
1500
- }
1501
- })(),
1502
- ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1503
- })) ?? [],
1624
+ toolCalls,
1504
1625
  usage: response.usage ? {
1505
1626
  promptTokens: response.usage.prompt_tokens,
1506
1627
  completionTokens: response.usage.completion_tokens,