@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 { A as AIProvider } from '../../types-DHQEMFHA.mjs';
1
+ import { L as LanguageModel } from '../../types-D7lzMMLu.mjs';
2
+ import { 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
  * Together AI Provider
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-Dg1Bcg1k.js';
2
- import { A as AIProvider } from '../../types-Dikj3En4.js';
1
+ import { L as LanguageModel } from '../../types-D7lzMMLu.js';
2
+ import { 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
  * Together AI Provider
@@ -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",
@@ -593,6 +607,63 @@ function formatMessages(messages) {
593
607
  });
594
608
  }
595
609
 
610
+ // src/core/provider-error.ts
611
+ function invalidProviderResponse(message) {
612
+ return Object.assign(new Error(message), {
613
+ name: "InvalidProviderResponseError",
614
+ status: 502,
615
+ code: "INVALID_PROVIDER_RESPONSE"
616
+ });
617
+ }
618
+ function providerErrorEvent(error, code) {
619
+ const details = error ?? {};
620
+ const event = {
621
+ type: "error",
622
+ message: error instanceof Error ? error.message : String(error),
623
+ code,
624
+ ...typeof details.status === "number" ? { status: details.status } : {},
625
+ ...typeof details.code === "string" ? { providerCode: details.code } : {},
626
+ ...typeof details.param === "string" ? { param: details.param } : {},
627
+ ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
628
+ };
629
+ Object.defineProperty(event, "cause", { value: error, enumerable: false });
630
+ return event;
631
+ }
632
+ function throwIfAborted(signal) {
633
+ if (!signal?.aborted) return;
634
+ const error = new Error("The operation was aborted");
635
+ error.name = "AbortError";
636
+ throw error;
637
+ }
638
+
639
+ // src/core/tool-validation.ts
640
+ function parseToolArguments(value) {
641
+ let args = value;
642
+ if (typeof value === "string") {
643
+ try {
644
+ args = JSON.parse(value || "{}");
645
+ } catch {
646
+ throw invalidProviderResponse("Tool arguments are not valid JSON");
647
+ }
648
+ }
649
+ if (args === null || typeof args !== "object" || Array.isArray(args))
650
+ throw invalidProviderResponse("Tool arguments must be a JSON object");
651
+ return args;
652
+ }
653
+ function validateToolCalls(calls) {
654
+ const ids = /* @__PURE__ */ new Set();
655
+ for (const call of calls) {
656
+ if (!call || typeof call.id !== "string" || !call.id || typeof call.name !== "string" || !call.name || ids.has(call.id))
657
+ throw invalidProviderResponse(
658
+ "Tool calls have missing or duplicate identities"
659
+ );
660
+ ids.add(call.id);
661
+ if (typeof call.args === "string")
662
+ throw invalidProviderResponse("Parsed tool arguments must be an object");
663
+ parseToolArguments(call.args);
664
+ }
665
+ }
666
+
596
667
  // src/core/openai-responses.ts
597
668
  function resolveOpenAITransport(defaults, overrides) {
598
669
  return {
@@ -640,6 +711,54 @@ function responseMetadata(response) {
640
711
  }
641
712
  };
642
713
  }
714
+ function responseReplayMetadata(metadata) {
715
+ const response = metadata?.openai?.response;
716
+ if (!response) return metadata;
717
+ const output = response.output.map((item) => {
718
+ const fields = ["type", "id", "status"];
719
+ switch (item.type) {
720
+ case "reasoning":
721
+ fields.push("encrypted_content");
722
+ break;
723
+ case "message":
724
+ fields.push("role", "phase");
725
+ break;
726
+ case "function_call":
727
+ fields.push("call_id", "name", "namespace", "arguments");
728
+ break;
729
+ case "tool_search_call":
730
+ fields.push("call_id", "execution", "arguments");
731
+ break;
732
+ case "tool_search_output":
733
+ fields.push("call_id", "tools");
734
+ break;
735
+ case "web_search_call":
736
+ fields.push("action");
737
+ break;
738
+ default:
739
+ return stripItemDiagnostics(item);
740
+ }
741
+ const replay = Object.fromEntries(
742
+ fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
743
+ );
744
+ if (item.type === "reasoning") replay.summary = [];
745
+ if (item.type === "message")
746
+ replay.content = Array.isArray(item.content) ? item.content.flatMap(
747
+ (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 }] : []
748
+ ) : [];
749
+ return stripItemDiagnostics(replay);
750
+ });
751
+ return { openai: { response: { output, refusals: [] } } };
752
+ }
753
+ function stripItemDiagnostics(item) {
754
+ const {
755
+ usage: _usage,
756
+ logprobs: _logprobs,
757
+ metadata: _metadata,
758
+ ...state
759
+ } = item;
760
+ return state;
761
+ }
643
762
  function getResponseReplay(metadata) {
644
763
  const response = metadata?.openai?.response;
645
764
  if (response === void 0) return void 0;
@@ -648,29 +767,7 @@ function getResponseReplay(metadata) {
648
767
  "Invalid OpenAI Responses replay metadata: output must contain typed items"
649
768
  );
650
769
  }
651
- return response.output;
652
- }
653
-
654
- // src/core/provider-error.ts
655
- function providerErrorEvent(error, code) {
656
- const details = error ?? {};
657
- const event = {
658
- type: "error",
659
- message: error instanceof Error ? error.message : String(error),
660
- code,
661
- ...typeof details.status === "number" ? { status: details.status } : {},
662
- ...typeof details.code === "string" ? { providerCode: details.code } : {},
663
- ...typeof details.param === "string" ? { param: details.param } : {},
664
- ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
665
- };
666
- Object.defineProperty(event, "cause", { value: error, enumerable: false });
667
- return event;
668
- }
669
- function throwIfAborted(signal) {
670
- if (!signal?.aborted) return;
671
- const error = new Error("The operation was aborted");
672
- error.name = "AbortError";
673
- throw error;
770
+ return responseReplayMetadata(metadata)?.openai?.response?.output;
674
771
  }
675
772
 
676
773
  // src/core/utils.ts
@@ -680,9 +777,6 @@ function generateId(prefix = "id") {
680
777
  function generateMessageId() {
681
778
  return generateId("msg");
682
779
  }
683
- function generateToolCallId() {
684
- return generateId("call");
685
- }
686
780
 
687
781
  // src/adapters/openai.ts
688
782
  var OpenAIAdapter = class _OpenAIAdapter {
@@ -706,6 +800,8 @@ var OpenAIAdapter = class _OpenAIAdapter {
706
800
  apiKey: this.config.apiKey,
707
801
  baseURL: this.config.baseUrl,
708
802
  organization: this.config.organization,
803
+ project: this.config.project,
804
+ timeout: this.config.timeout,
709
805
  defaultHeaders: this.config.headers
710
806
  });
711
807
  }
@@ -828,7 +924,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
828
924
  formatRawMessages(messages, preserveProviderMetadata = false) {
829
925
  return messages.map((message) => {
830
926
  const { attachments, providerMetadata, modelOutput, ...rest } = message;
831
- let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput, String(message.content ?? "")) : message.content;
927
+ let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
832
928
  if (preserveProviderMetadata && modelOutput)
833
929
  rest.modelOutput = modelOutput;
834
930
  if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
@@ -931,17 +1027,32 @@ var OpenAIAdapter = class _OpenAIAdapter {
931
1027
  const seenCallIds = /* @__PURE__ */ new Set();
932
1028
  const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
933
1029
  if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
934
- throw new Error("Responses contains an incomplete function call");
1030
+ throw invalidProviderResponse(
1031
+ "Responses contains an incomplete function call"
1032
+ );
935
1033
  }
936
1034
  if (seenCallIds.has(item.call_id))
937
- throw new Error("Responses contains duplicate function call IDs");
1035
+ throw invalidProviderResponse(
1036
+ "Responses contains duplicate function call IDs"
1037
+ );
938
1038
  seenCallIds.add(item.call_id);
939
- const args = JSON.parse(item.arguments);
1039
+ let args;
1040
+ try {
1041
+ args = JSON.parse(item.arguments);
1042
+ } catch {
1043
+ throw invalidProviderResponse(
1044
+ "Responses function arguments must be valid JSON"
1045
+ );
1046
+ }
940
1047
  if (!args || typeof args !== "object" || Array.isArray(args))
941
- throw new Error(
1048
+ throw invalidProviderResponse(
942
1049
  "Responses function arguments must be a JSON object"
943
1050
  );
944
- return { id: item.call_id, name: item.name, args };
1051
+ return {
1052
+ id: item.call_id,
1053
+ name: item.name,
1054
+ args
1055
+ };
945
1056
  }) : [];
946
1057
  return {
947
1058
  content,
@@ -972,6 +1083,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
972
1083
  request.config?.responseFormat
973
1084
  );
974
1085
  const modelIdForPayload = request.config?.model || this.model;
1086
+ const include = filterOpenAIResponseInclude(
1087
+ modelIdForPayload,
1088
+ [
1089
+ .../* @__PURE__ */ new Set([
1090
+ ...options?.include ?? [],
1091
+ ...options?.store === false ? ["reasoning.encrypted_content"] : []
1092
+ ])
1093
+ ],
1094
+ this.parameterOptions(request)
1095
+ );
975
1096
  const payload = {
976
1097
  model: modelIdForPayload,
977
1098
  instructions: request.systemPrompt,
@@ -995,14 +1116,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
995
1116
  ...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
996
1117
  ...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
997
1118
  ...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
998
- ...options?.store === false || options?.include ? {
999
- include: [
1000
- .../* @__PURE__ */ new Set([
1001
- ...options?.include ?? [],
1002
- ...options?.store === false ? ["reasoning.encrypted_content"] : []
1003
- ])
1004
- ]
1005
- } : {},
1119
+ ...include ? { include } : {},
1006
1120
  ...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
1007
1121
  stream
1008
1122
  };
@@ -1184,7 +1298,9 @@ var OpenAIAdapter = class _OpenAIAdapter {
1184
1298
  const uniqueCalls = /* @__PURE__ */ new Map();
1185
1299
  for (const call of toolCalls.values()) {
1186
1300
  if (!call.id || !call.name)
1187
- throw new Error("Responses stream contains an incomplete tool call");
1301
+ throw invalidProviderResponse(
1302
+ "Responses stream contains an incomplete tool call"
1303
+ );
1188
1304
  uniqueCalls.set(call.id, call);
1189
1305
  }
1190
1306
  toolCalls.clear();
@@ -1371,15 +1487,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1371
1487
  }
1372
1488
  throwIfAborted(request.signal);
1373
1489
  if (!finishReason)
1374
- throw new Error("OpenAI stream ended without a finish reason");
1490
+ throw invalidProviderResponse(
1491
+ "OpenAI stream ended without a finish reason"
1492
+ );
1375
1493
  if (toolCalls.size && !["tool_calls", "function_call"].includes(finishReason)) {
1376
- throw new Error("OpenAI stream ended with incomplete tool calls");
1377
- }
1378
- for (const call of toolCalls.values()) {
1379
- if (!call.id || !call.name)
1380
- throw new Error("OpenAI stream contains an incomplete tool call");
1381
- JSON.parse(call.arguments || "{}");
1494
+ throw invalidProviderResponse(
1495
+ "OpenAI stream ended with incomplete tool calls"
1496
+ );
1382
1497
  }
1498
+ validateToolCalls(
1499
+ [...toolCalls.values()].map((call) => ({
1500
+ ...call,
1501
+ args: parseToolArguments(call.arguments)
1502
+ }))
1503
+ );
1383
1504
  for (const call of toolCalls.values()) {
1384
1505
  yield {
1385
1506
  type: "action:start",
@@ -1463,20 +1584,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1463
1584
  logProviderPayload("openai", "response payload", response, request.debug);
1464
1585
  const choice = response.choices?.[0];
1465
1586
  const message = choice?.message;
1587
+ const toolCalls = (message?.tool_calls ?? []).map((toolCall) => ({
1588
+ id: toolCall.id,
1589
+ name: toolCall.function?.name,
1590
+ args: parseToolArguments(toolCall.function?.arguments ?? "{}"),
1591
+ ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1592
+ }));
1593
+ validateToolCalls(toolCalls);
1594
+ if (toolCalls.length && choice?.finish_reason && !["tool_calls", "function_call"].includes(choice.finish_reason))
1595
+ throw invalidProviderResponse(
1596
+ "OpenAI response ended with incomplete tool calls"
1597
+ );
1466
1598
  return {
1467
1599
  content: message?.content ?? "",
1468
- toolCalls: message?.tool_calls?.map((toolCall) => ({
1469
- id: toolCall.id ?? generateToolCallId(),
1470
- name: toolCall.function?.name ?? "",
1471
- args: (() => {
1472
- try {
1473
- return JSON.parse(toolCall.function?.arguments ?? "{}");
1474
- } catch {
1475
- return {};
1476
- }
1477
- })(),
1478
- ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1479
- })) ?? [],
1600
+ toolCalls,
1480
1601
  usage: response.usage ? {
1481
1602
  promptTokens: response.usage.prompt_tokens,
1482
1603
  completionTokens: response.usage.completion_tokens,