@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.
- package/LICENSE +21 -0
- package/README.md +87 -17
- package/dist/adapters/index.d.mts +11 -13
- package/dist/adapters/index.d.ts +11 -13
- package/dist/adapters/index.js +406 -114
- package/dist/adapters/index.mjs +406 -114
- package/dist/audio-K-Z3-Bce.d.mts +191 -0
- package/dist/audio-K-Z3-Bce.d.ts +191 -0
- package/dist/{base-BICaQaRS.d.mts → base-6LzczuCg.d.ts} +8 -1
- package/dist/{base-CpRPB8u8.d.ts → base-DySbTP8C.d.mts} +8 -1
- package/dist/decisions-CJzOt87t.d.mts +137 -0
- package/dist/decisions-CJzOt87t.d.ts +137 -0
- package/dist/fallback/index.d.mts +4 -4
- package/dist/fallback/index.d.ts +4 -4
- package/dist/http-BQxUT5A9.d.mts +9 -0
- package/dist/http-BQxUT5A9.d.ts +9 -0
- package/dist/index.d.mts +17 -9
- package/dist/index.d.ts +17 -9
- package/dist/index.js +698 -205
- package/dist/index.mjs +695 -206
- package/dist/providers/anthropic/index.d.mts +7 -4
- package/dist/providers/anthropic/index.d.ts +7 -4
- package/dist/providers/anthropic/index.js +389 -115
- package/dist/providers/anthropic/index.mjs +389 -115
- package/dist/providers/azure/index.d.mts +3 -3
- package/dist/providers/azure/index.d.ts +3 -3
- package/dist/providers/cloudflare/index.d.mts +11 -0
- package/dist/providers/cloudflare/index.d.ts +11 -0
- package/dist/providers/cloudflare/index.js +743 -0
- package/dist/providers/cloudflare/index.mjs +741 -0
- package/dist/providers/fireworks/index.d.mts +3 -3
- package/dist/providers/fireworks/index.d.ts +3 -3
- package/dist/providers/fireworks/index.js +181 -60
- package/dist/providers/fireworks/index.mjs +181 -60
- package/dist/providers/google/index.d.mts +3 -3
- package/dist/providers/google/index.d.ts +3 -3
- package/dist/providers/google/index.js +181 -60
- package/dist/providers/google/index.mjs +181 -60
- package/dist/providers/ollama/index.d.mts +4 -4
- package/dist/providers/ollama/index.d.ts +4 -4
- package/dist/providers/openai/index.d.mts +38 -6
- package/dist/providers/openai/index.d.ts +38 -6
- package/dist/providers/openai/index.js +1451 -85
- package/dist/providers/openai/index.mjs +1449 -86
- package/dist/providers/openrouter/index.d.mts +21 -4
- package/dist/providers/openrouter/index.d.ts +21 -4
- package/dist/providers/openrouter/index.js +1040 -131
- package/dist/providers/openrouter/index.mjs +1040 -132
- package/dist/providers/togetherai/index.d.mts +3 -3
- package/dist/providers/togetherai/index.d.ts +3 -3
- package/dist/providers/togetherai/index.js +181 -60
- package/dist/providers/togetherai/index.mjs +181 -60
- package/dist/providers/typesafe/index.d.mts +8 -0
- package/dist/providers/typesafe/index.d.ts +8 -0
- package/dist/providers/typesafe/index.js +735 -0
- package/dist/providers/typesafe/index.mjs +733 -0
- package/dist/providers/xai/index.d.mts +3 -3
- package/dist/providers/xai/index.d.ts +3 -3
- package/dist/providers/xai/index.js +181 -60
- package/dist/providers/xai/index.mjs +181 -60
- package/dist/{types-DCFqkJAy.d.ts → types-B0y6VZSQ.d.ts} +1 -1
- package/dist/{types-DHQEMFHA.d.mts → types-BXQMtaCX.d.ts} +17 -3
- package/dist/{types-C3RgRbEC.d.mts → types-BY6BVhFg.d.mts} +1 -1
- package/dist/{types-Dikj3En4.d.ts → types-C7_qVSSd.d.mts} +17 -3
- package/dist/{types-Dg1Bcg1k.d.mts → types-D7lzMMLu.d.mts} +13 -1
- package/dist/{types-Dg1Bcg1k.d.ts → types-D7lzMMLu.d.ts} +13 -1
- package/dist/yourgpt/index.d.mts +1 -1
- package/dist/yourgpt/index.d.ts +1 -1
- package/docs/decisions.md +174 -0
- package/docs/media.md +201 -0
- package/docs/multimodal-and-audio.md +9 -2
- package/package.json +34 -12
- package/dist/audio-BBSwnjo8.d.mts +0 -92
- package/dist/audio-BBSwnjo8.d.ts +0 -92
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as LanguageModel } from '../../types-
|
|
2
|
-
import { X as XAIProviderConfig, A as AIProvider } from '../../types-
|
|
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-
|
|
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-
|
|
2
|
-
import { X as XAIProviderConfig, A as AIProvider } from '../../types-
|
|
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-
|
|
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
|
|
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,
|
|
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
|
|
1054
|
+
throw invalidProviderResponse(
|
|
1055
|
+
"Responses contains an incomplete function call"
|
|
1056
|
+
);
|
|
959
1057
|
}
|
|
960
1058
|
if (seenCallIds.has(item.call_id))
|
|
961
|
-
throw
|
|
1059
|
+
throw invalidProviderResponse(
|
|
1060
|
+
"Responses contains duplicate function call IDs"
|
|
1061
|
+
);
|
|
962
1062
|
seenCallIds.add(item.call_id);
|
|
963
|
-
|
|
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
|
|
1072
|
+
throw invalidProviderResponse(
|
|
966
1073
|
"Responses function arguments must be a JSON object"
|
|
967
1074
|
);
|
|
968
|
-
return {
|
|
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
|
-
...
|
|
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
|
|
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
|
|
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
|
|
1401
|
-
|
|
1402
|
-
|
|
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
|
|
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,
|