@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
@@ -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",
@@ -586,6 +600,63 @@ function formatMessages(messages) {
586
600
  });
587
601
  }
588
602
 
603
+ // src/core/provider-error.ts
604
+ function invalidProviderResponse(message) {
605
+ return Object.assign(new Error(message), {
606
+ name: "InvalidProviderResponseError",
607
+ status: 502,
608
+ code: "INVALID_PROVIDER_RESPONSE"
609
+ });
610
+ }
611
+ function providerErrorEvent(error, code) {
612
+ const details = error ?? {};
613
+ const event = {
614
+ type: "error",
615
+ message: error instanceof Error ? error.message : String(error),
616
+ code,
617
+ ...typeof details.status === "number" ? { status: details.status } : {},
618
+ ...typeof details.code === "string" ? { providerCode: details.code } : {},
619
+ ...typeof details.param === "string" ? { param: details.param } : {},
620
+ ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
621
+ };
622
+ Object.defineProperty(event, "cause", { value: error, enumerable: false });
623
+ return event;
624
+ }
625
+ function throwIfAborted(signal) {
626
+ if (!signal?.aborted) return;
627
+ const error = new Error("The operation was aborted");
628
+ error.name = "AbortError";
629
+ throw error;
630
+ }
631
+
632
+ // src/core/tool-validation.ts
633
+ function parseToolArguments(value) {
634
+ let args = value;
635
+ if (typeof value === "string") {
636
+ try {
637
+ args = JSON.parse(value || "{}");
638
+ } catch {
639
+ throw invalidProviderResponse("Tool arguments are not valid JSON");
640
+ }
641
+ }
642
+ if (args === null || typeof args !== "object" || Array.isArray(args))
643
+ throw invalidProviderResponse("Tool arguments must be a JSON object");
644
+ return args;
645
+ }
646
+ function validateToolCalls(calls) {
647
+ const ids = /* @__PURE__ */ new Set();
648
+ for (const call of calls) {
649
+ if (!call || typeof call.id !== "string" || !call.id || typeof call.name !== "string" || !call.name || ids.has(call.id))
650
+ throw invalidProviderResponse(
651
+ "Tool calls have missing or duplicate identities"
652
+ );
653
+ ids.add(call.id);
654
+ if (typeof call.args === "string")
655
+ throw invalidProviderResponse("Parsed tool arguments must be an object");
656
+ parseToolArguments(call.args);
657
+ }
658
+ }
659
+
589
660
  // src/core/openai-responses.ts
590
661
  function resolveOpenAITransport(defaults, overrides) {
591
662
  return {
@@ -633,6 +704,54 @@ function responseMetadata(response) {
633
704
  }
634
705
  };
635
706
  }
707
+ function responseReplayMetadata(metadata) {
708
+ const response = metadata?.openai?.response;
709
+ if (!response) return metadata;
710
+ const output = response.output.map((item) => {
711
+ const fields = ["type", "id", "status"];
712
+ switch (item.type) {
713
+ case "reasoning":
714
+ fields.push("encrypted_content");
715
+ break;
716
+ case "message":
717
+ fields.push("role", "phase");
718
+ break;
719
+ case "function_call":
720
+ fields.push("call_id", "name", "namespace", "arguments");
721
+ break;
722
+ case "tool_search_call":
723
+ fields.push("call_id", "execution", "arguments");
724
+ break;
725
+ case "tool_search_output":
726
+ fields.push("call_id", "tools");
727
+ break;
728
+ case "web_search_call":
729
+ fields.push("action");
730
+ break;
731
+ default:
732
+ return stripItemDiagnostics(item);
733
+ }
734
+ const replay = Object.fromEntries(
735
+ fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
736
+ );
737
+ if (item.type === "reasoning") replay.summary = [];
738
+ if (item.type === "message")
739
+ replay.content = Array.isArray(item.content) ? item.content.flatMap(
740
+ (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 }] : []
741
+ ) : [];
742
+ return stripItemDiagnostics(replay);
743
+ });
744
+ return { openai: { response: { output, refusals: [] } } };
745
+ }
746
+ function stripItemDiagnostics(item) {
747
+ const {
748
+ usage: _usage,
749
+ logprobs: _logprobs,
750
+ metadata: _metadata,
751
+ ...state
752
+ } = item;
753
+ return state;
754
+ }
636
755
  function getResponseReplay(metadata) {
637
756
  const response = metadata?.openai?.response;
638
757
  if (response === void 0) return void 0;
@@ -641,29 +760,7 @@ function getResponseReplay(metadata) {
641
760
  "Invalid OpenAI Responses replay metadata: output must contain typed items"
642
761
  );
643
762
  }
644
- return response.output;
645
- }
646
-
647
- // src/core/provider-error.ts
648
- function providerErrorEvent(error, code) {
649
- const details = error ?? {};
650
- const event = {
651
- type: "error",
652
- message: error instanceof Error ? error.message : String(error),
653
- code,
654
- ...typeof details.status === "number" ? { status: details.status } : {},
655
- ...typeof details.code === "string" ? { providerCode: details.code } : {},
656
- ...typeof details.param === "string" ? { param: details.param } : {},
657
- ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
658
- };
659
- Object.defineProperty(event, "cause", { value: error, enumerable: false });
660
- return event;
661
- }
662
- function throwIfAborted(signal) {
663
- if (!signal?.aborted) return;
664
- const error = new Error("The operation was aborted");
665
- error.name = "AbortError";
666
- throw error;
763
+ return responseReplayMetadata(metadata)?.openai?.response?.output;
667
764
  }
668
765
 
669
766
  // src/core/utils.ts
@@ -673,9 +770,6 @@ function generateId(prefix = "id") {
673
770
  function generateMessageId() {
674
771
  return generateId("msg");
675
772
  }
676
- function generateToolCallId() {
677
- return generateId("call");
678
- }
679
773
 
680
774
  // src/adapters/openai.ts
681
775
  var OpenAIAdapter = class _OpenAIAdapter {
@@ -699,6 +793,8 @@ var OpenAIAdapter = class _OpenAIAdapter {
699
793
  apiKey: this.config.apiKey,
700
794
  baseURL: this.config.baseUrl,
701
795
  organization: this.config.organization,
796
+ project: this.config.project,
797
+ timeout: this.config.timeout,
702
798
  defaultHeaders: this.config.headers
703
799
  });
704
800
  }
@@ -821,7 +917,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
821
917
  formatRawMessages(messages, preserveProviderMetadata = false) {
822
918
  return messages.map((message) => {
823
919
  const { attachments, providerMetadata, modelOutput, ...rest } = message;
824
- let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput, String(message.content ?? "")) : message.content;
920
+ let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
825
921
  if (preserveProviderMetadata && modelOutput)
826
922
  rest.modelOutput = modelOutput;
827
923
  if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
@@ -924,17 +1020,32 @@ var OpenAIAdapter = class _OpenAIAdapter {
924
1020
  const seenCallIds = /* @__PURE__ */ new Set();
925
1021
  const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
926
1022
  if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
927
- throw new Error("Responses contains an incomplete function call");
1023
+ throw invalidProviderResponse(
1024
+ "Responses contains an incomplete function call"
1025
+ );
928
1026
  }
929
1027
  if (seenCallIds.has(item.call_id))
930
- throw new Error("Responses contains duplicate function call IDs");
1028
+ throw invalidProviderResponse(
1029
+ "Responses contains duplicate function call IDs"
1030
+ );
931
1031
  seenCallIds.add(item.call_id);
932
- const args = JSON.parse(item.arguments);
1032
+ let args;
1033
+ try {
1034
+ args = JSON.parse(item.arguments);
1035
+ } catch {
1036
+ throw invalidProviderResponse(
1037
+ "Responses function arguments must be valid JSON"
1038
+ );
1039
+ }
933
1040
  if (!args || typeof args !== "object" || Array.isArray(args))
934
- throw new Error(
1041
+ throw invalidProviderResponse(
935
1042
  "Responses function arguments must be a JSON object"
936
1043
  );
937
- return { id: item.call_id, name: item.name, args };
1044
+ return {
1045
+ id: item.call_id,
1046
+ name: item.name,
1047
+ args
1048
+ };
938
1049
  }) : [];
939
1050
  return {
940
1051
  content,
@@ -965,6 +1076,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
965
1076
  request.config?.responseFormat
966
1077
  );
967
1078
  const modelIdForPayload = request.config?.model || this.model;
1079
+ const include = filterOpenAIResponseInclude(
1080
+ modelIdForPayload,
1081
+ [
1082
+ .../* @__PURE__ */ new Set([
1083
+ ...options?.include ?? [],
1084
+ ...options?.store === false ? ["reasoning.encrypted_content"] : []
1085
+ ])
1086
+ ],
1087
+ this.parameterOptions(request)
1088
+ );
968
1089
  const payload = {
969
1090
  model: modelIdForPayload,
970
1091
  instructions: request.systemPrompt,
@@ -988,14 +1109,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
988
1109
  ...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
989
1110
  ...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
990
1111
  ...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
991
- ...options?.store === false || options?.include ? {
992
- include: [
993
- .../* @__PURE__ */ new Set([
994
- ...options?.include ?? [],
995
- ...options?.store === false ? ["reasoning.encrypted_content"] : []
996
- ])
997
- ]
998
- } : {},
1112
+ ...include ? { include } : {},
999
1113
  ...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
1000
1114
  stream
1001
1115
  };
@@ -1177,7 +1291,9 @@ var OpenAIAdapter = class _OpenAIAdapter {
1177
1291
  const uniqueCalls = /* @__PURE__ */ new Map();
1178
1292
  for (const call of toolCalls.values()) {
1179
1293
  if (!call.id || !call.name)
1180
- throw new Error("Responses stream contains an incomplete tool call");
1294
+ throw invalidProviderResponse(
1295
+ "Responses stream contains an incomplete tool call"
1296
+ );
1181
1297
  uniqueCalls.set(call.id, call);
1182
1298
  }
1183
1299
  toolCalls.clear();
@@ -1364,15 +1480,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1364
1480
  }
1365
1481
  throwIfAborted(request.signal);
1366
1482
  if (!finishReason)
1367
- throw new Error("OpenAI stream ended without a finish reason");
1483
+ throw invalidProviderResponse(
1484
+ "OpenAI stream ended without a finish reason"
1485
+ );
1368
1486
  if (toolCalls.size && !["tool_calls", "function_call"].includes(finishReason)) {
1369
- throw new Error("OpenAI stream ended with incomplete tool calls");
1370
- }
1371
- for (const call of toolCalls.values()) {
1372
- if (!call.id || !call.name)
1373
- throw new Error("OpenAI stream contains an incomplete tool call");
1374
- JSON.parse(call.arguments || "{}");
1487
+ throw invalidProviderResponse(
1488
+ "OpenAI stream ended with incomplete tool calls"
1489
+ );
1375
1490
  }
1491
+ validateToolCalls(
1492
+ [...toolCalls.values()].map((call) => ({
1493
+ ...call,
1494
+ args: parseToolArguments(call.arguments)
1495
+ }))
1496
+ );
1376
1497
  for (const call of toolCalls.values()) {
1377
1498
  yield {
1378
1499
  type: "action:start",
@@ -1456,20 +1577,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1456
1577
  logProviderPayload("openai", "response payload", response, request.debug);
1457
1578
  const choice = response.choices?.[0];
1458
1579
  const message = choice?.message;
1580
+ const toolCalls = (message?.tool_calls ?? []).map((toolCall) => ({
1581
+ id: toolCall.id,
1582
+ name: toolCall.function?.name,
1583
+ args: parseToolArguments(toolCall.function?.arguments ?? "{}"),
1584
+ ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1585
+ }));
1586
+ validateToolCalls(toolCalls);
1587
+ if (toolCalls.length && choice?.finish_reason && !["tool_calls", "function_call"].includes(choice.finish_reason))
1588
+ throw invalidProviderResponse(
1589
+ "OpenAI response ended with incomplete tool calls"
1590
+ );
1459
1591
  return {
1460
1592
  content: message?.content ?? "",
1461
- toolCalls: message?.tool_calls?.map((toolCall) => ({
1462
- id: toolCall.id ?? generateToolCallId(),
1463
- name: toolCall.function?.name ?? "",
1464
- args: (() => {
1465
- try {
1466
- return JSON.parse(toolCall.function?.arguments ?? "{}");
1467
- } catch {
1468
- return {};
1469
- }
1470
- })(),
1471
- ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1472
- })) ?? [],
1593
+ toolCalls,
1473
1594
  usage: response.usage ? {
1474
1595
  promptTokens: response.usage.prompt_tokens,
1475
1596
  completionTokens: response.usage.completion_tokens,
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-Dg1Bcg1k.mjs';
2
- import { G as GoogleProviderConfig, A as AIProvider } from '../../types-DHQEMFHA.mjs';
1
+ import { L as LanguageModel } from '../../types-D7lzMMLu.mjs';
2
+ import { G as GoogleProviderConfig, 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
  * Google Provider - OpenAI-Compatible
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-Dg1Bcg1k.js';
2
- import { G as GoogleProviderConfig, A as AIProvider } from '../../types-Dikj3En4.js';
1
+ import { L as LanguageModel } from '../../types-D7lzMMLu.js';
2
+ import { G as GoogleProviderConfig, 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
  * Google Provider - OpenAI-Compatible