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