@yourgpt/llm-sdk 2.6.0-beta.2 → 2.6.0-beta.3

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.
@@ -640,6 +640,54 @@ function responseMetadata(response) {
640
640
  }
641
641
  };
642
642
  }
643
+ function responseReplayMetadata(metadata) {
644
+ const response = metadata?.openai?.response;
645
+ if (!response) return metadata;
646
+ const output = response.output.map((item) => {
647
+ const fields = ["type", "id", "status"];
648
+ switch (item.type) {
649
+ case "reasoning":
650
+ fields.push("encrypted_content");
651
+ break;
652
+ case "message":
653
+ fields.push("role", "phase");
654
+ break;
655
+ case "function_call":
656
+ fields.push("call_id", "name", "namespace", "arguments");
657
+ break;
658
+ case "tool_search_call":
659
+ fields.push("call_id", "execution", "arguments");
660
+ break;
661
+ case "tool_search_output":
662
+ fields.push("call_id", "tools");
663
+ break;
664
+ case "web_search_call":
665
+ fields.push("action");
666
+ break;
667
+ default:
668
+ return stripItemDiagnostics(item);
669
+ }
670
+ const replay = Object.fromEntries(
671
+ fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
672
+ );
673
+ if (item.type === "reasoning") replay.summary = [];
674
+ if (item.type === "message")
675
+ replay.content = Array.isArray(item.content) ? item.content.flatMap(
676
+ (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 }] : []
677
+ ) : [];
678
+ return stripItemDiagnostics(replay);
679
+ });
680
+ return { openai: { response: { output, refusals: [] } } };
681
+ }
682
+ function stripItemDiagnostics(item) {
683
+ const {
684
+ usage: _usage,
685
+ logprobs: _logprobs,
686
+ metadata: _metadata,
687
+ ...state
688
+ } = item;
689
+ return state;
690
+ }
643
691
  function getResponseReplay(metadata) {
644
692
  const response = metadata?.openai?.response;
645
693
  if (response === void 0) return void 0;
@@ -648,10 +696,17 @@ function getResponseReplay(metadata) {
648
696
  "Invalid OpenAI Responses replay metadata: output must contain typed items"
649
697
  );
650
698
  }
651
- return response.output;
699
+ return responseReplayMetadata(metadata)?.openai?.response?.output;
652
700
  }
653
701
 
654
702
  // src/core/provider-error.ts
703
+ function invalidProviderResponse(message) {
704
+ return Object.assign(new Error(message), {
705
+ name: "InvalidProviderResponseError",
706
+ status: 502,
707
+ code: "INVALID_PROVIDER_RESPONSE"
708
+ });
709
+ }
655
710
  function providerErrorEvent(error, code) {
656
711
  const details = error ?? {};
657
712
  const event = {
@@ -828,7 +883,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
828
883
  formatRawMessages(messages, preserveProviderMetadata = false) {
829
884
  return messages.map((message) => {
830
885
  const { attachments, providerMetadata, modelOutput, ...rest } = message;
831
- let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput, String(message.content ?? "")) : message.content;
886
+ let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
832
887
  if (preserveProviderMetadata && modelOutput)
833
888
  rest.modelOutput = modelOutput;
834
889
  if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
@@ -931,17 +986,32 @@ var OpenAIAdapter = class _OpenAIAdapter {
931
986
  const seenCallIds = /* @__PURE__ */ new Set();
932
987
  const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
933
988
  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");
989
+ throw invalidProviderResponse(
990
+ "Responses contains an incomplete function call"
991
+ );
935
992
  }
936
993
  if (seenCallIds.has(item.call_id))
937
- throw new Error("Responses contains duplicate function call IDs");
994
+ throw invalidProviderResponse(
995
+ "Responses contains duplicate function call IDs"
996
+ );
938
997
  seenCallIds.add(item.call_id);
939
- const args = JSON.parse(item.arguments);
998
+ let args;
999
+ try {
1000
+ args = JSON.parse(item.arguments);
1001
+ } catch {
1002
+ throw invalidProviderResponse(
1003
+ "Responses function arguments must be valid JSON"
1004
+ );
1005
+ }
940
1006
  if (!args || typeof args !== "object" || Array.isArray(args))
941
- throw new Error(
1007
+ throw invalidProviderResponse(
942
1008
  "Responses function arguments must be a JSON object"
943
1009
  );
944
- return { id: item.call_id, name: item.name, args };
1010
+ return {
1011
+ id: item.call_id,
1012
+ name: item.name,
1013
+ args
1014
+ };
945
1015
  }) : [];
946
1016
  return {
947
1017
  content,
@@ -1184,7 +1254,9 @@ var OpenAIAdapter = class _OpenAIAdapter {
1184
1254
  const uniqueCalls = /* @__PURE__ */ new Map();
1185
1255
  for (const call of toolCalls.values()) {
1186
1256
  if (!call.id || !call.name)
1187
- throw new Error("Responses stream contains an incomplete tool call");
1257
+ throw invalidProviderResponse(
1258
+ "Responses stream contains an incomplete tool call"
1259
+ );
1188
1260
  uniqueCalls.set(call.id, call);
1189
1261
  }
1190
1262
  toolCalls.clear();
@@ -638,6 +638,54 @@ function responseMetadata(response) {
638
638
  }
639
639
  };
640
640
  }
641
+ function responseReplayMetadata(metadata) {
642
+ const response = metadata?.openai?.response;
643
+ if (!response) return metadata;
644
+ const output = response.output.map((item) => {
645
+ const fields = ["type", "id", "status"];
646
+ switch (item.type) {
647
+ case "reasoning":
648
+ fields.push("encrypted_content");
649
+ break;
650
+ case "message":
651
+ fields.push("role", "phase");
652
+ break;
653
+ case "function_call":
654
+ fields.push("call_id", "name", "namespace", "arguments");
655
+ break;
656
+ case "tool_search_call":
657
+ fields.push("call_id", "execution", "arguments");
658
+ break;
659
+ case "tool_search_output":
660
+ fields.push("call_id", "tools");
661
+ break;
662
+ case "web_search_call":
663
+ fields.push("action");
664
+ break;
665
+ default:
666
+ return stripItemDiagnostics(item);
667
+ }
668
+ const replay = Object.fromEntries(
669
+ fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
670
+ );
671
+ if (item.type === "reasoning") replay.summary = [];
672
+ if (item.type === "message")
673
+ replay.content = Array.isArray(item.content) ? item.content.flatMap(
674
+ (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 }] : []
675
+ ) : [];
676
+ return stripItemDiagnostics(replay);
677
+ });
678
+ return { openai: { response: { output, refusals: [] } } };
679
+ }
680
+ function stripItemDiagnostics(item) {
681
+ const {
682
+ usage: _usage,
683
+ logprobs: _logprobs,
684
+ metadata: _metadata,
685
+ ...state
686
+ } = item;
687
+ return state;
688
+ }
641
689
  function getResponseReplay(metadata) {
642
690
  const response = metadata?.openai?.response;
643
691
  if (response === void 0) return void 0;
@@ -646,10 +694,17 @@ function getResponseReplay(metadata) {
646
694
  "Invalid OpenAI Responses replay metadata: output must contain typed items"
647
695
  );
648
696
  }
649
- return response.output;
697
+ return responseReplayMetadata(metadata)?.openai?.response?.output;
650
698
  }
651
699
 
652
700
  // src/core/provider-error.ts
701
+ function invalidProviderResponse(message) {
702
+ return Object.assign(new Error(message), {
703
+ name: "InvalidProviderResponseError",
704
+ status: 502,
705
+ code: "INVALID_PROVIDER_RESPONSE"
706
+ });
707
+ }
653
708
  function providerErrorEvent(error, code) {
654
709
  const details = error ?? {};
655
710
  const event = {
@@ -826,7 +881,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
826
881
  formatRawMessages(messages, preserveProviderMetadata = false) {
827
882
  return messages.map((message) => {
828
883
  const { attachments, providerMetadata, modelOutput, ...rest } = message;
829
- let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput, String(message.content ?? "")) : message.content;
884
+ let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
830
885
  if (preserveProviderMetadata && modelOutput)
831
886
  rest.modelOutput = modelOutput;
832
887
  if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
@@ -929,17 +984,32 @@ var OpenAIAdapter = class _OpenAIAdapter {
929
984
  const seenCallIds = /* @__PURE__ */ new Set();
930
985
  const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
931
986
  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");
987
+ throw invalidProviderResponse(
988
+ "Responses contains an incomplete function call"
989
+ );
933
990
  }
934
991
  if (seenCallIds.has(item.call_id))
935
- throw new Error("Responses contains duplicate function call IDs");
992
+ throw invalidProviderResponse(
993
+ "Responses contains duplicate function call IDs"
994
+ );
936
995
  seenCallIds.add(item.call_id);
937
- const args = JSON.parse(item.arguments);
996
+ let args;
997
+ try {
998
+ args = JSON.parse(item.arguments);
999
+ } catch {
1000
+ throw invalidProviderResponse(
1001
+ "Responses function arguments must be valid JSON"
1002
+ );
1003
+ }
938
1004
  if (!args || typeof args !== "object" || Array.isArray(args))
939
- throw new Error(
1005
+ throw invalidProviderResponse(
940
1006
  "Responses function arguments must be a JSON object"
941
1007
  );
942
- return { id: item.call_id, name: item.name, args };
1008
+ return {
1009
+ id: item.call_id,
1010
+ name: item.name,
1011
+ args
1012
+ };
943
1013
  }) : [];
944
1014
  return {
945
1015
  content,
@@ -1182,7 +1252,9 @@ var OpenAIAdapter = class _OpenAIAdapter {
1182
1252
  const uniqueCalls = /* @__PURE__ */ new Map();
1183
1253
  for (const call of toolCalls.values()) {
1184
1254
  if (!call.id || !call.name)
1185
- throw new Error("Responses stream contains an incomplete tool call");
1255
+ throw invalidProviderResponse(
1256
+ "Responses stream contains an incomplete tool call"
1257
+ );
1186
1258
  uniqueCalls.set(call.id, call);
1187
1259
  }
1188
1260
  toolCalls.clear();
@@ -664,6 +664,54 @@ function responseMetadata(response) {
664
664
  }
665
665
  };
666
666
  }
667
+ function responseReplayMetadata(metadata) {
668
+ const response = metadata?.openai?.response;
669
+ if (!response) return metadata;
670
+ const output = response.output.map((item) => {
671
+ const fields = ["type", "id", "status"];
672
+ switch (item.type) {
673
+ case "reasoning":
674
+ fields.push("encrypted_content");
675
+ break;
676
+ case "message":
677
+ fields.push("role", "phase");
678
+ break;
679
+ case "function_call":
680
+ fields.push("call_id", "name", "namespace", "arguments");
681
+ break;
682
+ case "tool_search_call":
683
+ fields.push("call_id", "execution", "arguments");
684
+ break;
685
+ case "tool_search_output":
686
+ fields.push("call_id", "tools");
687
+ break;
688
+ case "web_search_call":
689
+ fields.push("action");
690
+ break;
691
+ default:
692
+ return stripItemDiagnostics(item);
693
+ }
694
+ const replay = Object.fromEntries(
695
+ fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
696
+ );
697
+ if (item.type === "reasoning") replay.summary = [];
698
+ if (item.type === "message")
699
+ replay.content = Array.isArray(item.content) ? item.content.flatMap(
700
+ (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 }] : []
701
+ ) : [];
702
+ return stripItemDiagnostics(replay);
703
+ });
704
+ return { openai: { response: { output, refusals: [] } } };
705
+ }
706
+ function stripItemDiagnostics(item) {
707
+ const {
708
+ usage: _usage,
709
+ logprobs: _logprobs,
710
+ metadata: _metadata,
711
+ ...state
712
+ } = item;
713
+ return state;
714
+ }
667
715
  function getResponseReplay(metadata) {
668
716
  const response = metadata?.openai?.response;
669
717
  if (response === void 0) return void 0;
@@ -672,10 +720,17 @@ function getResponseReplay(metadata) {
672
720
  "Invalid OpenAI Responses replay metadata: output must contain typed items"
673
721
  );
674
722
  }
675
- return response.output;
723
+ return responseReplayMetadata(metadata)?.openai?.response?.output;
676
724
  }
677
725
 
678
726
  // src/core/provider-error.ts
727
+ function invalidProviderResponse(message) {
728
+ return Object.assign(new Error(message), {
729
+ name: "InvalidProviderResponseError",
730
+ status: 502,
731
+ code: "INVALID_PROVIDER_RESPONSE"
732
+ });
733
+ }
679
734
  function providerErrorEvent(error, code) {
680
735
  const details = error ?? {};
681
736
  const event = {
@@ -852,7 +907,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
852
907
  formatRawMessages(messages, preserveProviderMetadata = false) {
853
908
  return messages.map((message) => {
854
909
  const { attachments, providerMetadata, modelOutput, ...rest } = message;
855
- let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput, String(message.content ?? "")) : message.content;
910
+ let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
856
911
  if (preserveProviderMetadata && modelOutput)
857
912
  rest.modelOutput = modelOutput;
858
913
  if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
@@ -955,17 +1010,32 @@ var OpenAIAdapter = class _OpenAIAdapter {
955
1010
  const seenCallIds = /* @__PURE__ */ new Set();
956
1011
  const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
957
1012
  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");
1013
+ throw invalidProviderResponse(
1014
+ "Responses contains an incomplete function call"
1015
+ );
959
1016
  }
960
1017
  if (seenCallIds.has(item.call_id))
961
- throw new Error("Responses contains duplicate function call IDs");
1018
+ throw invalidProviderResponse(
1019
+ "Responses contains duplicate function call IDs"
1020
+ );
962
1021
  seenCallIds.add(item.call_id);
963
- const args = JSON.parse(item.arguments);
1022
+ let args;
1023
+ try {
1024
+ args = JSON.parse(item.arguments);
1025
+ } catch {
1026
+ throw invalidProviderResponse(
1027
+ "Responses function arguments must be valid JSON"
1028
+ );
1029
+ }
964
1030
  if (!args || typeof args !== "object" || Array.isArray(args))
965
- throw new Error(
1031
+ throw invalidProviderResponse(
966
1032
  "Responses function arguments must be a JSON object"
967
1033
  );
968
- return { id: item.call_id, name: item.name, args };
1034
+ return {
1035
+ id: item.call_id,
1036
+ name: item.name,
1037
+ args
1038
+ };
969
1039
  }) : [];
970
1040
  return {
971
1041
  content,
@@ -1208,7 +1278,9 @@ var OpenAIAdapter = class _OpenAIAdapter {
1208
1278
  const uniqueCalls = /* @__PURE__ */ new Map();
1209
1279
  for (const call of toolCalls.values()) {
1210
1280
  if (!call.id || !call.name)
1211
- throw new Error("Responses stream contains an incomplete tool call");
1281
+ throw invalidProviderResponse(
1282
+ "Responses stream contains an incomplete tool call"
1283
+ );
1212
1284
  uniqueCalls.set(call.id, call);
1213
1285
  }
1214
1286
  toolCalls.clear();
@@ -662,6 +662,54 @@ function responseMetadata(response) {
662
662
  }
663
663
  };
664
664
  }
665
+ function responseReplayMetadata(metadata) {
666
+ const response = metadata?.openai?.response;
667
+ if (!response) return metadata;
668
+ const output = response.output.map((item) => {
669
+ const fields = ["type", "id", "status"];
670
+ switch (item.type) {
671
+ case "reasoning":
672
+ fields.push("encrypted_content");
673
+ break;
674
+ case "message":
675
+ fields.push("role", "phase");
676
+ break;
677
+ case "function_call":
678
+ fields.push("call_id", "name", "namespace", "arguments");
679
+ break;
680
+ case "tool_search_call":
681
+ fields.push("call_id", "execution", "arguments");
682
+ break;
683
+ case "tool_search_output":
684
+ fields.push("call_id", "tools");
685
+ break;
686
+ case "web_search_call":
687
+ fields.push("action");
688
+ break;
689
+ default:
690
+ return stripItemDiagnostics(item);
691
+ }
692
+ const replay = Object.fromEntries(
693
+ fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
694
+ );
695
+ if (item.type === "reasoning") replay.summary = [];
696
+ if (item.type === "message")
697
+ replay.content = Array.isArray(item.content) ? item.content.flatMap(
698
+ (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 }] : []
699
+ ) : [];
700
+ return stripItemDiagnostics(replay);
701
+ });
702
+ return { openai: { response: { output, refusals: [] } } };
703
+ }
704
+ function stripItemDiagnostics(item) {
705
+ const {
706
+ usage: _usage,
707
+ logprobs: _logprobs,
708
+ metadata: _metadata,
709
+ ...state
710
+ } = item;
711
+ return state;
712
+ }
665
713
  function getResponseReplay(metadata) {
666
714
  const response = metadata?.openai?.response;
667
715
  if (response === void 0) return void 0;
@@ -670,10 +718,17 @@ function getResponseReplay(metadata) {
670
718
  "Invalid OpenAI Responses replay metadata: output must contain typed items"
671
719
  );
672
720
  }
673
- return response.output;
721
+ return responseReplayMetadata(metadata)?.openai?.response?.output;
674
722
  }
675
723
 
676
724
  // src/core/provider-error.ts
725
+ function invalidProviderResponse(message) {
726
+ return Object.assign(new Error(message), {
727
+ name: "InvalidProviderResponseError",
728
+ status: 502,
729
+ code: "INVALID_PROVIDER_RESPONSE"
730
+ });
731
+ }
677
732
  function providerErrorEvent(error, code) {
678
733
  const details = error ?? {};
679
734
  const event = {
@@ -850,7 +905,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
850
905
  formatRawMessages(messages, preserveProviderMetadata = false) {
851
906
  return messages.map((message) => {
852
907
  const { attachments, providerMetadata, modelOutput, ...rest } = message;
853
- let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput, String(message.content ?? "")) : message.content;
908
+ let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
854
909
  if (preserveProviderMetadata && modelOutput)
855
910
  rest.modelOutput = modelOutput;
856
911
  if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
@@ -953,17 +1008,32 @@ var OpenAIAdapter = class _OpenAIAdapter {
953
1008
  const seenCallIds = /* @__PURE__ */ new Set();
954
1009
  const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
955
1010
  if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
956
- throw new Error("Responses contains an incomplete function call");
1011
+ throw invalidProviderResponse(
1012
+ "Responses contains an incomplete function call"
1013
+ );
957
1014
  }
958
1015
  if (seenCallIds.has(item.call_id))
959
- throw new Error("Responses contains duplicate function call IDs");
1016
+ throw invalidProviderResponse(
1017
+ "Responses contains duplicate function call IDs"
1018
+ );
960
1019
  seenCallIds.add(item.call_id);
961
- const args = JSON.parse(item.arguments);
1020
+ let args;
1021
+ try {
1022
+ args = JSON.parse(item.arguments);
1023
+ } catch {
1024
+ throw invalidProviderResponse(
1025
+ "Responses function arguments must be valid JSON"
1026
+ );
1027
+ }
962
1028
  if (!args || typeof args !== "object" || Array.isArray(args))
963
- throw new Error(
1029
+ throw invalidProviderResponse(
964
1030
  "Responses function arguments must be a JSON object"
965
1031
  );
966
- return { id: item.call_id, name: item.name, args };
1032
+ return {
1033
+ id: item.call_id,
1034
+ name: item.name,
1035
+ args
1036
+ };
967
1037
  }) : [];
968
1038
  return {
969
1039
  content,
@@ -1206,7 +1276,9 @@ var OpenAIAdapter = class _OpenAIAdapter {
1206
1276
  const uniqueCalls = /* @__PURE__ */ new Map();
1207
1277
  for (const call of toolCalls.values()) {
1208
1278
  if (!call.id || !call.name)
1209
- throw new Error("Responses stream contains an incomplete tool call");
1279
+ throw invalidProviderResponse(
1280
+ "Responses stream contains an incomplete tool call"
1281
+ );
1210
1282
  uniqueCalls.set(call.id, call);
1211
1283
  }
1212
1284
  toolCalls.clear();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yourgpt/llm-sdk",
3
- "version": "2.6.0-beta.2",
3
+ "version": "2.6.0-beta.3",
4
4
  "description": "AI SDK for building AI Agents with any LLM",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",