@standardagents/openrouter 0.44.0 → 0.45.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/dist/index.d.ts +8 -2
- package/dist/index.js +284 -378
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -28,6 +28,7 @@ function mapOpenRouterReasoningLevels(model, mandatory, supportedEfforts) {
|
|
|
28
28
|
|
|
29
29
|
// src/responses-transformers.ts
|
|
30
30
|
import { unrecognized } from "@openrouter/sdk/types";
|
|
31
|
+
import { OpenResponsesInput$outboundSchema, OpenResponsesReasoningConfig$outboundSchema } from "@openrouter/sdk/models";
|
|
31
32
|
|
|
32
33
|
// src/chat-completions-transformers.ts
|
|
33
34
|
import { mapReasoningLevel } from "@standardagents/spec";
|
|
@@ -73,12 +74,10 @@ function toOpenRouterServerTool(name, parameters) {
|
|
|
73
74
|
}
|
|
74
75
|
function splitOpenRouterProviderOptions(providerOptions) {
|
|
75
76
|
if (!providerOptions) return void 0;
|
|
76
|
-
const {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
...rest
|
|
81
|
-
} = providerOptions;
|
|
77
|
+
const rest = { ...providerOptions };
|
|
78
|
+
delete rest.serverTools;
|
|
79
|
+
delete rest.server_tools;
|
|
80
|
+
delete rest._metadata;
|
|
82
81
|
return Object.keys(rest).length > 0 ? rest : void 0;
|
|
83
82
|
}
|
|
84
83
|
function serverToolNameFromUsageKey(key) {
|
|
@@ -250,11 +249,10 @@ function transformChatAssistantMessage(msg) {
|
|
|
250
249
|
return typeof detail.data === "string" && detail.data.length > 0;
|
|
251
250
|
}).map((detail) => {
|
|
252
251
|
const type = detail.type;
|
|
253
|
-
const legacy = detail;
|
|
254
252
|
if (type === "text" || type === "reasoning.text") {
|
|
255
253
|
return { type: "reasoning.text", text: detail.text, format: detail.format };
|
|
256
254
|
} else if (type === "summary" || type === "reasoning.summary") {
|
|
257
|
-
return { type: "reasoning.summary", summary: detail.text ??
|
|
255
|
+
return { type: "reasoning.summary", summary: detail.text ?? detail.summary, format: detail.format };
|
|
258
256
|
}
|
|
259
257
|
return { type: "reasoning.encrypted", data: detail.data, id: detail.id, format: detail.format };
|
|
260
258
|
});
|
|
@@ -682,7 +680,11 @@ function processChatStreamChunk(chunk, state) {
|
|
|
682
680
|
chunk.id
|
|
683
681
|
));
|
|
684
682
|
const actualProvider = chunk.provider || chunk.model?.split("/")[0] || void 0;
|
|
685
|
-
const reasoningDetails = state.reasoningDetails.length > 0 ? state.reasoningDetails.map((
|
|
683
|
+
const reasoningDetails = state.reasoningDetails.length > 0 ? state.reasoningDetails.map((detail) => {
|
|
684
|
+
const emittedDetail = { ...detail };
|
|
685
|
+
delete emittedDetail._index;
|
|
686
|
+
return emittedDetail;
|
|
687
|
+
}) : void 0;
|
|
686
688
|
chunks.push({
|
|
687
689
|
type: "finish",
|
|
688
690
|
finishReason: mapChatFinishReason(state.finishReason),
|
|
@@ -804,7 +806,10 @@ function buildChatParams(request, reasoningLevels = getOpenRouterReasoningLevels
|
|
|
804
806
|
);
|
|
805
807
|
if (safeOptions) {
|
|
806
808
|
if (request.reasoning?.level !== void 0) {
|
|
807
|
-
const
|
|
809
|
+
const otherOptions = { ...safeOptions };
|
|
810
|
+
delete otherOptions.effort;
|
|
811
|
+
delete otherOptions.reasoning_effort;
|
|
812
|
+
delete otherOptions.reasoningEffort;
|
|
808
813
|
Object.assign(params, otherOptions);
|
|
809
814
|
} else {
|
|
810
815
|
Object.assign(params, safeOptions);
|
|
@@ -870,6 +875,37 @@ function truncateChatBase64(obj, maxLength = 50) {
|
|
|
870
875
|
function isRecord3(value) {
|
|
871
876
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
872
877
|
}
|
|
878
|
+
function readWireString(record, ...keys) {
|
|
879
|
+
for (const key of keys) {
|
|
880
|
+
const value = record[key];
|
|
881
|
+
if (typeof value === "string" && value) return value;
|
|
882
|
+
}
|
|
883
|
+
return void 0;
|
|
884
|
+
}
|
|
885
|
+
function isResponsesEnvelope(value) {
|
|
886
|
+
return isRecord3(value) && typeof value.id === "string" && Array.isArray(value.output) && (value.model === void 0 || typeof value.model === "string");
|
|
887
|
+
}
|
|
888
|
+
function requireResponsesEnvelope(value) {
|
|
889
|
+
if (!isResponsesEnvelope(value)) throw new Error("Invalid OpenRouter Responses payload.");
|
|
890
|
+
return value;
|
|
891
|
+
}
|
|
892
|
+
function actualProviderOf(response) {
|
|
893
|
+
return typeof response.provider === "string" ? response.provider : response.model?.split("/")[0] || void 0;
|
|
894
|
+
}
|
|
895
|
+
function parseFunctionArguments(value) {
|
|
896
|
+
if (typeof value !== "string" || !value) return {};
|
|
897
|
+
try {
|
|
898
|
+
const parsed = JSON.parse(value);
|
|
899
|
+
return isRecord3(parsed) ? parsed : {};
|
|
900
|
+
} catch {
|
|
901
|
+
return {};
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
function generatedImageFromData(data, fields = {}) {
|
|
905
|
+
let mediaType = fields.mediaType ?? "image/png";
|
|
906
|
+
if (data.startsWith("data:")) mediaType = data.match(/^data:([^;,]+)/)?.[1] ?? mediaType;
|
|
907
|
+
return { ...fields, data, mediaType };
|
|
908
|
+
}
|
|
873
909
|
function transformContentPart(part) {
|
|
874
910
|
if (part.type === "text") {
|
|
875
911
|
return { type: "input_text", text: part.text };
|
|
@@ -879,7 +915,7 @@ function transformContentPart(part) {
|
|
|
879
915
|
const imageUrl = data.startsWith("data:") ? data : `data:${part.mediaType || "image/png"};base64,${data}`;
|
|
880
916
|
return {
|
|
881
917
|
type: "input_image",
|
|
882
|
-
|
|
918
|
+
imageUrl,
|
|
883
919
|
detail: part.detail || "auto"
|
|
884
920
|
};
|
|
885
921
|
}
|
|
@@ -888,7 +924,7 @@ function transformContentPart(part) {
|
|
|
888
924
|
const detail = part.image_url?.detail || "auto";
|
|
889
925
|
return {
|
|
890
926
|
type: "input_image",
|
|
891
|
-
|
|
927
|
+
imageUrl: url,
|
|
892
928
|
detail
|
|
893
929
|
};
|
|
894
930
|
}
|
|
@@ -910,28 +946,39 @@ function transformUserMessage(msg) {
|
|
|
910
946
|
content: typeof content === "string" ? content : content
|
|
911
947
|
};
|
|
912
948
|
}
|
|
949
|
+
function storedReasoningDetail(value) {
|
|
950
|
+
if (!isRecord3(value)) return void 0;
|
|
951
|
+
const type = value.type === "reasoning.text" ? "text" : value.type === "reasoning.encrypted" ? "encrypted" : value.type === "summary" || value.type === "text" || value.type === "encrypted" ? value.type : void 0;
|
|
952
|
+
if (!type) return void 0;
|
|
953
|
+
const data = value.type === "reasoning.encrypted" ? value.text : value.data;
|
|
954
|
+
return {
|
|
955
|
+
type,
|
|
956
|
+
id: typeof value.id === "string" ? value.id : void 0,
|
|
957
|
+
text: typeof value.text === "string" ? value.text : void 0,
|
|
958
|
+
data: typeof data === "string" ? data : void 0
|
|
959
|
+
};
|
|
960
|
+
}
|
|
913
961
|
function transformAssistantMessage(msg) {
|
|
914
962
|
const items = [];
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
}
|
|
926
|
-
if (
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
}
|
|
963
|
+
const reasoningItems = /* @__PURE__ */ new Map();
|
|
964
|
+
const savedDetails = Array.isArray(msg.reasoningDetails) ? msg.reasoningDetails : [];
|
|
965
|
+
for (const saved of savedDetails) {
|
|
966
|
+
const detail = storedReasoningDetail(saved);
|
|
967
|
+
if (!detail) continue;
|
|
968
|
+
const id = detail.id || "";
|
|
969
|
+
let item = reasoningItems.get(id);
|
|
970
|
+
if (!item) {
|
|
971
|
+
item = { type: "reasoning", id, summary: [] };
|
|
972
|
+
reasoningItems.set(id, item);
|
|
973
|
+
}
|
|
974
|
+
if (detail.type === "encrypted" && detail.data) {
|
|
975
|
+
item.encryptedContent = detail.data;
|
|
976
|
+
} else if ((detail.type === "summary" || detail.type === "text") && typeof detail.text === "string") {
|
|
977
|
+
item.summary.push({ type: "summary_text", text: detail.text });
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
for (const item of reasoningItems.values()) {
|
|
981
|
+
if (item.summary.length > 0 || item.encryptedContent && item.id) items.push(item);
|
|
935
982
|
}
|
|
936
983
|
if (msg.content) {
|
|
937
984
|
const outputMessage = {
|
|
@@ -949,7 +996,7 @@ function transformAssistantMessage(msg) {
|
|
|
949
996
|
type: "function_call",
|
|
950
997
|
id: `fc_${tc.id}`,
|
|
951
998
|
// Unique output item ID (prefixed to distinguish from call_id)
|
|
952
|
-
|
|
999
|
+
callId: tc.id,
|
|
953
1000
|
name: tc.name,
|
|
954
1001
|
arguments: JSON.stringify(tc.arguments),
|
|
955
1002
|
status: "completed"
|
|
@@ -979,7 +1026,7 @@ function transformToolMessage(msg) {
|
|
|
979
1026
|
const imageAttachments = Array.isArray(msg.content) ? msg.content.filter((part) => part.type === "image" && Boolean(part.data) || part.type === "image_url") : [];
|
|
980
1027
|
const toolOutput = {
|
|
981
1028
|
type: "function_call_output",
|
|
982
|
-
|
|
1029
|
+
callId: msg.toolCallId,
|
|
983
1030
|
output: output || (imageAttachments.length > 0 ? "Success" : "")
|
|
984
1031
|
};
|
|
985
1032
|
if (imageAttachments.length === 0) {
|
|
@@ -1070,19 +1117,21 @@ function transformToolChoice(choice) {
|
|
|
1070
1117
|
return "auto";
|
|
1071
1118
|
}
|
|
1072
1119
|
function mapFinishReason(response) {
|
|
1120
|
+
const incomplete = response.incompleteDetails ?? response.incomplete_details;
|
|
1121
|
+
const reason = isRecord3(incomplete) ? incomplete.reason : void 0;
|
|
1073
1122
|
if (response.status === "failed") {
|
|
1074
1123
|
return "error";
|
|
1075
1124
|
}
|
|
1076
1125
|
if (response.status === "incomplete") {
|
|
1077
|
-
if (
|
|
1126
|
+
if (reason === "max_output_tokens") {
|
|
1078
1127
|
return "length";
|
|
1079
1128
|
}
|
|
1080
|
-
if (
|
|
1129
|
+
if (reason === "content_filter") {
|
|
1081
1130
|
return "content_filter";
|
|
1082
1131
|
}
|
|
1083
1132
|
}
|
|
1084
|
-
const hasToolCalls = response.output.some(
|
|
1085
|
-
(item) => item.type === "function_call"
|
|
1133
|
+
const hasToolCalls = Array.isArray(response.output) && response.output.some(
|
|
1134
|
+
(item) => isRecord3(item) && item.type === "function_call"
|
|
1086
1135
|
);
|
|
1087
1136
|
if (hasToolCalls) {
|
|
1088
1137
|
return "tool_calls";
|
|
@@ -1092,9 +1141,9 @@ function mapFinishReason(response) {
|
|
|
1092
1141
|
function extractTextContent(output) {
|
|
1093
1142
|
const textParts = [];
|
|
1094
1143
|
for (const item of output) {
|
|
1095
|
-
if (item.type === "message" && item.role === "assistant") {
|
|
1144
|
+
if (isRecord3(item) && item.type === "message" && item.role === "assistant" && Array.isArray(item.content)) {
|
|
1096
1145
|
for (const content of item.content) {
|
|
1097
|
-
if (content.type === "output_text") {
|
|
1146
|
+
if (isRecord3(content) && content.type === "output_text" && typeof content.text === "string") {
|
|
1098
1147
|
textParts.push(content.text);
|
|
1099
1148
|
}
|
|
1100
1149
|
}
|
|
@@ -1105,7 +1154,7 @@ function extractTextContent(output) {
|
|
|
1105
1154
|
function extractResponseWebSearchCitations(output) {
|
|
1106
1155
|
const citations = [];
|
|
1107
1156
|
for (const item of output) {
|
|
1108
|
-
if (item.type !== "message" || !
|
|
1157
|
+
if (!isRecord3(item) || item.type !== "message" || !Array.isArray(item.content)) {
|
|
1109
1158
|
continue;
|
|
1110
1159
|
}
|
|
1111
1160
|
for (const content of item.content) {
|
|
@@ -1119,16 +1168,11 @@ function extractResponseWebSearchCitations(output) {
|
|
|
1119
1168
|
function extractToolCalls(output) {
|
|
1120
1169
|
const toolCalls = [];
|
|
1121
1170
|
for (const item of output) {
|
|
1122
|
-
if (item.type === "function_call") {
|
|
1123
|
-
let parsedArgs = {};
|
|
1124
|
-
try {
|
|
1125
|
-
parsedArgs = item.arguments ? JSON.parse(item.arguments) : {};
|
|
1126
|
-
} catch {
|
|
1127
|
-
}
|
|
1171
|
+
if (isRecord3(item) && item.type === "function_call") {
|
|
1128
1172
|
toolCalls.push({
|
|
1129
|
-
id: item
|
|
1130
|
-
name: item
|
|
1131
|
-
arguments:
|
|
1173
|
+
id: readWireString(item, "callId", "call_id") ?? "",
|
|
1174
|
+
name: readWireString(item, "name") ?? "",
|
|
1175
|
+
arguments: parseFunctionArguments(item.arguments)
|
|
1132
1176
|
});
|
|
1133
1177
|
}
|
|
1134
1178
|
}
|
|
@@ -1137,75 +1181,55 @@ function extractToolCalls(output) {
|
|
|
1137
1181
|
function extractImages(output) {
|
|
1138
1182
|
const images = [];
|
|
1139
1183
|
for (const item of output) {
|
|
1140
|
-
|
|
1141
|
-
if (
|
|
1142
|
-
const
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
// Include revised prompt if available
|
|
1157
|
-
revisedPrompt: itemAny.revised_prompt || itemAny.revisedPrompt || void 0
|
|
1158
|
-
});
|
|
1159
|
-
}
|
|
1160
|
-
if (itemAny.type === "message" && itemAny.content && Array.isArray(itemAny.content)) {
|
|
1161
|
-
for (const content of itemAny.content) {
|
|
1162
|
-
if (content.type === "output_image" || content.type === "image") {
|
|
1163
|
-
const imageData = content.image || content.data || content.url || content.image_url;
|
|
1164
|
-
if (imageData) {
|
|
1165
|
-
let mediaType = content.media_type || content.mediaType || "image/png";
|
|
1166
|
-
if (typeof imageData === "string" && imageData.startsWith("data:")) {
|
|
1167
|
-
const match = imageData.match(/^data:([^;,]+)/);
|
|
1168
|
-
if (match) {
|
|
1169
|
-
mediaType = match[1];
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
images.push({
|
|
1173
|
-
id: content.id || void 0,
|
|
1174
|
-
data: imageData,
|
|
1175
|
-
mediaType
|
|
1176
|
-
});
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1184
|
+
if (!isRecord3(item)) continue;
|
|
1185
|
+
if (item.type === "image_generation_call") {
|
|
1186
|
+
const data = readWireString(item, "result");
|
|
1187
|
+
if (data) images.push(generatedImageFromData(data, {
|
|
1188
|
+
id: readWireString(item, "id"),
|
|
1189
|
+
revisedPrompt: readWireString(item, "revised_prompt", "revisedPrompt")
|
|
1190
|
+
}));
|
|
1191
|
+
}
|
|
1192
|
+
if (item.type === "message" && Array.isArray(item.content)) {
|
|
1193
|
+
for (const content of item.content) {
|
|
1194
|
+
if (!isRecord3(content) || content.type !== "output_image" && content.type !== "image") continue;
|
|
1195
|
+
const data = readWireString(content, "image", "data", "url", "image_url");
|
|
1196
|
+
if (data) images.push(generatedImageFromData(data, {
|
|
1197
|
+
id: readWireString(content, "id"),
|
|
1198
|
+
mediaType: readWireString(content, "media_type", "mediaType")
|
|
1199
|
+
}));
|
|
1179
1200
|
}
|
|
1180
1201
|
}
|
|
1181
1202
|
}
|
|
1182
1203
|
return images.length > 0 ? images : void 0;
|
|
1183
1204
|
}
|
|
1205
|
+
function numberField(record, key) {
|
|
1206
|
+
const value = record[key];
|
|
1207
|
+
return typeof value === "number" ? value : void 0;
|
|
1208
|
+
}
|
|
1209
|
+
function nestedNumber(record, field, key) {
|
|
1210
|
+
const nested = record[field];
|
|
1211
|
+
return isRecord3(nested) ? numberField(nested, key) : void 0;
|
|
1212
|
+
}
|
|
1184
1213
|
function transformUsage(usage, actualProvider) {
|
|
1185
|
-
if (!usage) {
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
totalTokens: 0
|
|
1190
|
-
};
|
|
1191
|
-
}
|
|
1192
|
-
const inputTokens = usage.native_tokens_prompt || usage.nativeTokensPrompt || usage.input_tokens || usage.inputTokens || 0;
|
|
1193
|
-
const outputTokens = usage.native_tokens_completion || usage.nativeTokensCompletion || usage.output_tokens || usage.outputTokens || 0;
|
|
1194
|
-
const totalTokens = usage.total_tokens || usage.totalTokens || 0;
|
|
1195
|
-
const reasoningTokens = usage.output_tokens_details?.reasoning_tokens || usage.outputTokensDetails?.reasoningTokens;
|
|
1196
|
-
const cachedTokens = usage.input_tokens_details?.cached_tokens || usage.inputTokensDetails?.cachedTokens;
|
|
1214
|
+
if (!isRecord3(usage)) return { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
1215
|
+
const inputTokens = numberField(usage, "native_tokens_prompt") || numberField(usage, "nativeTokensPrompt") || numberField(usage, "input_tokens") || numberField(usage, "inputTokens") || 0;
|
|
1216
|
+
const outputTokens = numberField(usage, "native_tokens_completion") || numberField(usage, "nativeTokensCompletion") || numberField(usage, "output_tokens") || numberField(usage, "outputTokens") || 0;
|
|
1217
|
+
const totalTokens = numberField(usage, "total_tokens") || numberField(usage, "totalTokens") || 0;
|
|
1197
1218
|
return {
|
|
1198
1219
|
promptTokens: inputTokens,
|
|
1199
1220
|
completionTokens: outputTokens,
|
|
1200
1221
|
totalTokens: totalTokens || inputTokens + outputTokens,
|
|
1201
|
-
reasoningTokens,
|
|
1202
|
-
cachedTokens,
|
|
1203
|
-
cost: usage
|
|
1222
|
+
reasoningTokens: nestedNumber(usage, "output_tokens_details", "reasoning_tokens") || nestedNumber(usage, "outputTokensDetails", "reasoningTokens"),
|
|
1223
|
+
cachedTokens: nestedNumber(usage, "input_tokens_details", "cached_tokens") || nestedNumber(usage, "inputTokensDetails", "cachedTokens"),
|
|
1224
|
+
cost: numberField(usage, "cost"),
|
|
1204
1225
|
provider: actualProvider
|
|
1205
1226
|
};
|
|
1206
1227
|
}
|
|
1207
|
-
function transformResponse(
|
|
1228
|
+
function transformResponse(value) {
|
|
1229
|
+
const response = requireResponsesEnvelope(value);
|
|
1208
1230
|
const content = extractTextContent(response.output);
|
|
1231
|
+
const reasoningDetails = extractReasoningDetails(response.output, "");
|
|
1232
|
+
const reasoning = reasoningDetails?.flatMap((detail) => detail.type !== "encrypted" && detail.text !== void 0 ? [detail.text] : []).join("\n") || void 0;
|
|
1209
1233
|
const toolCalls = extractToolCalls(response.output);
|
|
1210
1234
|
const images = extractImages(response.output);
|
|
1211
1235
|
const webSearchCitations = extractResponseWebSearchCitations(response.output);
|
|
@@ -1214,9 +1238,11 @@ function transformResponse(response) {
|
|
|
1214
1238
|
webSearchCitations,
|
|
1215
1239
|
response.id
|
|
1216
1240
|
);
|
|
1217
|
-
const actualProvider =
|
|
1241
|
+
const actualProvider = actualProviderOf(response);
|
|
1218
1242
|
return {
|
|
1219
1243
|
content,
|
|
1244
|
+
reasoning,
|
|
1245
|
+
reasoningDetails,
|
|
1220
1246
|
toolCalls,
|
|
1221
1247
|
images,
|
|
1222
1248
|
providerTools,
|
|
@@ -1232,43 +1258,41 @@ function transformResponse(response) {
|
|
|
1232
1258
|
}
|
|
1233
1259
|
function extractReasoningDetails(output, streamedReasoningContent) {
|
|
1234
1260
|
const details = [];
|
|
1235
|
-
if (
|
|
1236
|
-
for (const
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
}
|
|
1261
|
+
if (Array.isArray(output)) {
|
|
1262
|
+
for (const value of output) {
|
|
1263
|
+
if (!isRecord3(value)) continue;
|
|
1264
|
+
const id = typeof value.id === "string" ? value.id : void 0;
|
|
1265
|
+
if (value.type === "reasoning") {
|
|
1266
|
+
if (Array.isArray(value.summary)) {
|
|
1267
|
+
for (const step of value.summary) {
|
|
1268
|
+
const text = typeof step === "string" ? step : isRecord3(step) ? step.text : void 0;
|
|
1269
|
+
if (typeof text === "string") details.push({ type: "summary", id, text });
|
|
1244
1270
|
}
|
|
1245
1271
|
}
|
|
1246
|
-
|
|
1247
|
-
|
|
1272
|
+
const encrypted = value.encrypted_content ?? value.encryptedContent;
|
|
1273
|
+
if (typeof encrypted === "string" && encrypted) {
|
|
1274
|
+
details.push({ type: "encrypted", id, data: encrypted });
|
|
1248
1275
|
}
|
|
1249
|
-
if (
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
details.push({ type: "reasoning.text", text: part.text });
|
|
1256
|
-
}
|
|
1276
|
+
if (typeof value.content === "string") {
|
|
1277
|
+
details.push({ type: "text", id, text: value.content });
|
|
1278
|
+
} else if (Array.isArray(value.content)) {
|
|
1279
|
+
for (const part of value.content) {
|
|
1280
|
+
if (isRecord3(part) && typeof part.text === "string") {
|
|
1281
|
+
details.push({ type: "text", id, text: part.text });
|
|
1257
1282
|
}
|
|
1258
1283
|
}
|
|
1259
1284
|
}
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
details.push({ type: "reasoning.text", text: part.text || "" });
|
|
1285
|
+
} else if (value.type === "message" && Array.isArray(value.content)) {
|
|
1286
|
+
for (const part of value.content) {
|
|
1287
|
+
if (isRecord3(part) && (part.type === "reasoning" || part.type === "reasoning_text")) {
|
|
1288
|
+
details.push({ type: "text", text: typeof part.text === "string" ? part.text : "" });
|
|
1265
1289
|
}
|
|
1266
1290
|
}
|
|
1267
1291
|
}
|
|
1268
1292
|
}
|
|
1269
1293
|
}
|
|
1270
1294
|
if (details.length === 0 && streamedReasoningContent) {
|
|
1271
|
-
details.push({ type: "
|
|
1295
|
+
details.push({ type: "text", text: streamedReasoningContent });
|
|
1272
1296
|
}
|
|
1273
1297
|
return details.length > 0 ? details : void 0;
|
|
1274
1298
|
}
|
|
@@ -1327,7 +1351,10 @@ function buildCreateParams(request, reasoningLevels = getOpenRouterReasoningLeve
|
|
|
1327
1351
|
);
|
|
1328
1352
|
if (providerOptions) {
|
|
1329
1353
|
if (request.reasoning?.level !== void 0) {
|
|
1330
|
-
const
|
|
1354
|
+
const otherOptions = { ...providerOptions };
|
|
1355
|
+
delete otherOptions.effort;
|
|
1356
|
+
delete otherOptions.reasoning_effort;
|
|
1357
|
+
delete otherOptions.reasoningEffort;
|
|
1331
1358
|
Object.assign(params, otherOptions);
|
|
1332
1359
|
} else {
|
|
1333
1360
|
Object.assign(params, providerOptions);
|
|
@@ -1350,264 +1377,165 @@ function buildCreateParams(request, reasoningLevels = getOpenRouterReasoningLeve
|
|
|
1350
1377
|
}
|
|
1351
1378
|
return params;
|
|
1352
1379
|
}
|
|
1380
|
+
function serializeResponsesRequest(params, providerOptions) {
|
|
1381
|
+
const { input, toolChoice, parallelToolCalls, maxOutputTokens, topP, reasoning, ...rest } = params;
|
|
1382
|
+
let reasoningWire = reasoning;
|
|
1383
|
+
if (isRecord3(reasoning)) {
|
|
1384
|
+
const parsed = OpenResponsesReasoningConfig$outboundSchema.safeParse(reasoning);
|
|
1385
|
+
if (parsed.success) {
|
|
1386
|
+
const { effort: _effort, maxTokens: _maxTokens, ...reasoningOptions } = reasoning;
|
|
1387
|
+
reasoningWire = { ...parsed.data, ...reasoningOptions };
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
return {
|
|
1391
|
+
input: providerOptions && Object.prototype.propertyIsEnumerable.call(providerOptions, "input") ? providerOptions.input : input === void 0 ? void 0 : OpenResponsesInput$outboundSchema.parse(input),
|
|
1392
|
+
tool_choice: toolChoice,
|
|
1393
|
+
parallel_tool_calls: parallelToolCalls,
|
|
1394
|
+
max_output_tokens: maxOutputTokens,
|
|
1395
|
+
top_p: topP,
|
|
1396
|
+
reasoning: reasoningWire,
|
|
1397
|
+
// Preserve opaque provider options, including explicit wire-field overrides.
|
|
1398
|
+
...rest
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1353
1401
|
function createStreamState() {
|
|
1354
1402
|
return {
|
|
1355
1403
|
toolCalls: /* @__PURE__ */ new Map(),
|
|
1356
1404
|
reasoningContent: "",
|
|
1357
1405
|
hasContent: false,
|
|
1358
1406
|
hasReasoning: false,
|
|
1359
|
-
currentItemId: null,
|
|
1360
1407
|
imageGenerations: /* @__PURE__ */ new Map()
|
|
1361
1408
|
};
|
|
1362
1409
|
}
|
|
1363
1410
|
function processStreamEvent(event, state) {
|
|
1364
1411
|
const chunks = [];
|
|
1412
|
+
if (!isRecord3(event)) return chunks;
|
|
1365
1413
|
switch (event.type) {
|
|
1366
|
-
// Text content streaming
|
|
1367
1414
|
case "response.output_text.delta":
|
|
1415
|
+
if (typeof event.delta !== "string") break;
|
|
1368
1416
|
state.hasContent = true;
|
|
1369
1417
|
chunks.push({ type: "content-delta", delta: event.delta });
|
|
1370
1418
|
break;
|
|
1371
1419
|
case "response.output_text.done":
|
|
1420
|
+
case "response.reasoning_text.done":
|
|
1372
1421
|
break;
|
|
1373
|
-
// Reasoning streaming - OpenRouter uses 'response.reasoning.delta'
|
|
1374
|
-
// Note: SDK types may not include reasoning events, so we check dynamically
|
|
1375
1422
|
case "response.reasoning_text.delta":
|
|
1423
|
+
case "response.reasoning.delta": {
|
|
1424
|
+
const delta = readWireString(event, "delta") ?? "";
|
|
1376
1425
|
state.hasReasoning = true;
|
|
1377
|
-
state.reasoningContent +=
|
|
1378
|
-
chunks.push({ type: "reasoning-delta", delta
|
|
1379
|
-
break;
|
|
1380
|
-
case "response.reasoning_text.done":
|
|
1426
|
+
state.reasoningContent += delta;
|
|
1427
|
+
chunks.push({ type: "reasoning-delta", delta });
|
|
1381
1428
|
break;
|
|
1382
|
-
|
|
1383
|
-
case "response.output_item.added":
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
});
|
|
1392
|
-
chunks.push({
|
|
1393
|
-
type: "tool-call-start",
|
|
1394
|
-
id: callId,
|
|
1395
|
-
name
|
|
1396
|
-
});
|
|
1429
|
+
}
|
|
1430
|
+
case "response.output_item.added": {
|
|
1431
|
+
const item = event.item;
|
|
1432
|
+
if (!isRecord3(item)) break;
|
|
1433
|
+
if (item.type === "function_call") {
|
|
1434
|
+
const callId = readWireString(item, "callId", "call_id") ?? "";
|
|
1435
|
+
const name = readWireString(item, "name") ?? "";
|
|
1436
|
+
state.toolCalls.set(callId, { id: callId, name, arguments: "" });
|
|
1437
|
+
chunks.push({ type: "tool-call-start", id: callId, name });
|
|
1397
1438
|
}
|
|
1398
|
-
if (
|
|
1399
|
-
const
|
|
1400
|
-
|
|
1401
|
-
state.imageGenerations.set(imageId, {
|
|
1402
|
-
id: imageId,
|
|
1403
|
-
data: "",
|
|
1404
|
-
status: "in_progress"
|
|
1405
|
-
});
|
|
1439
|
+
if (item.type === "image_generation_call") {
|
|
1440
|
+
const id = readWireString(item, "id", "call_id", "callId") ?? `img-${state.imageGenerations.size}`;
|
|
1441
|
+
state.imageGenerations.set(id, { id, data: "", status: "in_progress" });
|
|
1406
1442
|
}
|
|
1407
1443
|
break;
|
|
1444
|
+
}
|
|
1408
1445
|
case "response.output_item.done": {
|
|
1409
|
-
const
|
|
1410
|
-
if (
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
const existing = state.imageGenerations.get(imageId);
|
|
1419
|
-
if (existing) {
|
|
1420
|
-
existing.data = imageData;
|
|
1421
|
-
existing.status = "completed";
|
|
1422
|
-
}
|
|
1423
|
-
const imageIndex = Array.from(state.imageGenerations.keys()).indexOf(imageId);
|
|
1424
|
-
chunks.push({
|
|
1425
|
-
type: "image-done",
|
|
1426
|
-
index: imageIndex >= 0 ? imageIndex : state.imageGenerations.size - 1,
|
|
1427
|
-
image: {
|
|
1428
|
-
id: imageId || void 0,
|
|
1429
|
-
data: imageData,
|
|
1430
|
-
mediaType,
|
|
1431
|
-
revisedPrompt: itemAny.revised_prompt || itemAny.revisedPrompt || void 0
|
|
1432
|
-
}
|
|
1433
|
-
});
|
|
1446
|
+
const item = event.item;
|
|
1447
|
+
if (!isRecord3(item) || item.type !== "image_generation_call") break;
|
|
1448
|
+
const data = readWireString(item, "result");
|
|
1449
|
+
if (!data) break;
|
|
1450
|
+
const id = readWireString(item, "id", "call_id", "callId") ?? "";
|
|
1451
|
+
const existing = state.imageGenerations.get(id);
|
|
1452
|
+
if (existing) {
|
|
1453
|
+
existing.data = data;
|
|
1454
|
+
existing.status = "completed";
|
|
1434
1455
|
}
|
|
1456
|
+
const index = Array.from(state.imageGenerations.keys()).indexOf(id);
|
|
1457
|
+
chunks.push({
|
|
1458
|
+
type: "image-done",
|
|
1459
|
+
index: index >= 0 ? index : state.imageGenerations.size - 1,
|
|
1460
|
+
image: generatedImageFromData(data, { id: id || void 0, revisedPrompt: readWireString(item, "revised_prompt", "revisedPrompt") })
|
|
1461
|
+
});
|
|
1435
1462
|
break;
|
|
1436
1463
|
}
|
|
1437
1464
|
case "response.function_call_arguments.delta": {
|
|
1438
|
-
const itemId = event
|
|
1439
|
-
const
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
deltaToolCall.arguments += event.delta;
|
|
1444
|
-
chunks.push({
|
|
1445
|
-
type: "tool-call-delta",
|
|
1446
|
-
id: deltaToolCall.id,
|
|
1447
|
-
argumentsDelta: event.delta
|
|
1448
|
-
});
|
|
1465
|
+
const itemId = readWireString(event, "itemId", "item_id") ?? "";
|
|
1466
|
+
const call = Array.from(state.toolCalls.values()).find((tool) => tool.id === itemId);
|
|
1467
|
+
if (call && typeof event.delta === "string") {
|
|
1468
|
+
call.arguments += event.delta;
|
|
1469
|
+
chunks.push({ type: "tool-call-delta", id: call.id, argumentsDelta: event.delta });
|
|
1449
1470
|
}
|
|
1450
1471
|
break;
|
|
1451
1472
|
}
|
|
1452
1473
|
case "response.function_call_arguments.done": {
|
|
1453
|
-
const itemId = event
|
|
1454
|
-
const
|
|
1455
|
-
|
|
1456
|
-
);
|
|
1457
|
-
if (doneToolCall) {
|
|
1458
|
-
let parsedArgs = {};
|
|
1459
|
-
try {
|
|
1460
|
-
parsedArgs = doneToolCall.arguments ? JSON.parse(doneToolCall.arguments) : {};
|
|
1461
|
-
} catch {
|
|
1462
|
-
}
|
|
1463
|
-
chunks.push({
|
|
1464
|
-
type: "tool-call-done",
|
|
1465
|
-
id: doneToolCall.id,
|
|
1466
|
-
arguments: parsedArgs
|
|
1467
|
-
});
|
|
1468
|
-
}
|
|
1474
|
+
const itemId = readWireString(event, "itemId", "item_id") ?? "";
|
|
1475
|
+
const call = Array.from(state.toolCalls.values()).find((tool) => tool.id === itemId);
|
|
1476
|
+
if (call) chunks.push({ type: "tool-call-done", id: call.id, arguments: parseFunctionArguments(call.arguments) });
|
|
1469
1477
|
break;
|
|
1470
1478
|
}
|
|
1471
|
-
|
|
1472
|
-
case "response.
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
}
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
const generatedImages = extractImages(event.response.output);
|
|
1482
|
-
if (generatedImages && generatedImages.length > 0) {
|
|
1483
|
-
for (let i = 0; i < generatedImages.length; i++) {
|
|
1484
|
-
const img = generatedImages[i];
|
|
1485
|
-
const alreadyEmitted = img.id && state.imageGenerations.get(img.id)?.status === "completed";
|
|
1486
|
-
if (!alreadyEmitted) {
|
|
1487
|
-
chunks.push({
|
|
1488
|
-
type: "image-done",
|
|
1489
|
-
index: i,
|
|
1490
|
-
image: img
|
|
1491
|
-
});
|
|
1479
|
+
case "response.completed":
|
|
1480
|
+
case "response.incomplete": {
|
|
1481
|
+
const response = requireResponsesEnvelope(event.response);
|
|
1482
|
+
if (state.hasContent) chunks.push({ type: "content-done" });
|
|
1483
|
+
if (state.hasReasoning) chunks.push({ type: "reasoning-done" });
|
|
1484
|
+
const images = extractImages(response.output);
|
|
1485
|
+
if (images) {
|
|
1486
|
+
for (const [index, image] of images.entries()) {
|
|
1487
|
+
if (!image.id || state.imageGenerations.get(image.id)?.status !== "completed") {
|
|
1488
|
+
chunks.push({ type: "image-done", index, image });
|
|
1492
1489
|
}
|
|
1493
1490
|
}
|
|
1494
1491
|
}
|
|
1495
1492
|
chunks.push(...providerToolDoneChunksFromServerToolUseOrCitations(
|
|
1496
|
-
|
|
1497
|
-
extractResponseWebSearchCitations(
|
|
1498
|
-
|
|
1493
|
+
response.usage,
|
|
1494
|
+
extractResponseWebSearchCitations(response.output),
|
|
1495
|
+
response.id
|
|
1499
1496
|
));
|
|
1500
|
-
|
|
1497
|
+
const finish = {
|
|
1501
1498
|
type: "finish",
|
|
1502
|
-
finishReason: mapFinishReason(
|
|
1503
|
-
usage: transformUsage(
|
|
1504
|
-
responseId:
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1499
|
+
finishReason: mapFinishReason(response),
|
|
1500
|
+
usage: transformUsage(response.usage, actualProviderOf(response)),
|
|
1501
|
+
responseId: response.id,
|
|
1502
|
+
reasoningDetails: extractReasoningDetails(response.output, state.reasoningContent)
|
|
1503
|
+
};
|
|
1504
|
+
chunks.push(finish);
|
|
1508
1505
|
break;
|
|
1509
1506
|
}
|
|
1510
|
-
case "response.failed":
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
code: event.response.error?.code
|
|
1515
|
-
});
|
|
1516
|
-
break;
|
|
1517
|
-
case "response.incomplete": {
|
|
1518
|
-
if (state.hasContent) {
|
|
1519
|
-
chunks.push({ type: "content-done" });
|
|
1520
|
-
}
|
|
1521
|
-
if (state.hasReasoning) {
|
|
1522
|
-
chunks.push({ type: "reasoning-done" });
|
|
1523
|
-
}
|
|
1524
|
-
const incompleteProvider = typeof event.response.provider === "string" ? event.response.provider : event.response.model?.split("/")[0] || void 0;
|
|
1525
|
-
const incompleteReasoningDetails = extractReasoningDetails(event.response.output, state.reasoningContent);
|
|
1526
|
-
const incompleteImages = extractImages(event.response.output);
|
|
1527
|
-
if (incompleteImages && incompleteImages.length > 0) {
|
|
1528
|
-
for (let i = 0; i < incompleteImages.length; i++) {
|
|
1529
|
-
const img = incompleteImages[i];
|
|
1530
|
-
const alreadyEmitted = img.id && state.imageGenerations.get(img.id)?.status === "completed";
|
|
1531
|
-
if (!alreadyEmitted) {
|
|
1532
|
-
chunks.push({
|
|
1533
|
-
type: "image-done",
|
|
1534
|
-
index: i,
|
|
1535
|
-
image: img
|
|
1536
|
-
});
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1539
|
-
}
|
|
1540
|
-
chunks.push(...providerToolDoneChunksFromServerToolUseOrCitations(
|
|
1541
|
-
event.response.usage,
|
|
1542
|
-
extractResponseWebSearchCitations(event.response.output),
|
|
1543
|
-
event.response.id
|
|
1544
|
-
));
|
|
1545
|
-
chunks.push({
|
|
1546
|
-
type: "finish",
|
|
1547
|
-
finishReason: mapFinishReason(event.response),
|
|
1548
|
-
usage: transformUsage(event.response.usage, incompleteProvider),
|
|
1549
|
-
responseId: event.response.id,
|
|
1550
|
-
// Used to fetch generation metadata after stream
|
|
1551
|
-
reasoningDetails: incompleteReasoningDetails
|
|
1552
|
-
});
|
|
1507
|
+
case "response.failed": {
|
|
1508
|
+
const response = isRecord3(event.response) ? event.response : {};
|
|
1509
|
+
const error = isRecord3(response.error) ? response.error : {};
|
|
1510
|
+
chunks.push({ type: "error", error: readWireString(error, "message") ?? "Response generation failed", code: readWireString(error, "code") });
|
|
1553
1511
|
break;
|
|
1554
1512
|
}
|
|
1555
|
-
// Handle reasoning and image events dynamically (SDK types may not include them)
|
|
1556
1513
|
default: {
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1514
|
+
if (event.type === "response.image_generation_call.partial_image" || event.type === "response.image_generation.partial") {
|
|
1515
|
+
const id = readWireString(event, "item_id", "itemId", "id") ?? "";
|
|
1516
|
+
const data = readWireString(event, "partial_image_b64", "partial_image", "delta", "data") ?? "";
|
|
1517
|
+
const existing = state.imageGenerations.get(id);
|
|
1518
|
+
if (existing) existing.data += data;
|
|
1519
|
+
else state.imageGenerations.set(id, { id, data, status: "generating" });
|
|
1520
|
+
const index = Array.from(state.imageGenerations.keys()).indexOf(id);
|
|
1521
|
+
chunks.push({ type: "image-delta", index: index >= 0 ? index : state.imageGenerations.size - 1, data });
|
|
1563
1522
|
}
|
|
1564
|
-
if (
|
|
1565
|
-
const
|
|
1566
|
-
const
|
|
1567
|
-
|
|
1523
|
+
if (event.type === "response.image_generation_call.completed" || event.type === "response.image_generation.done") {
|
|
1524
|
+
const id = readWireString(event, "item_id", "itemId", "id") ?? "";
|
|
1525
|
+
const data = readWireString(event, "result", "image", "data");
|
|
1526
|
+
if (!data) break;
|
|
1527
|
+
const existing = state.imageGenerations.get(id);
|
|
1568
1528
|
if (existing) {
|
|
1569
|
-
existing.data
|
|
1570
|
-
|
|
1571
|
-
state.imageGenerations.set(imageId, {
|
|
1572
|
-
id: imageId,
|
|
1573
|
-
data: partialData,
|
|
1574
|
-
status: "generating"
|
|
1575
|
-
});
|
|
1529
|
+
existing.data = data;
|
|
1530
|
+
existing.status = "completed";
|
|
1576
1531
|
}
|
|
1577
|
-
const
|
|
1532
|
+
const index = Array.from(state.imageGenerations.keys()).indexOf(id);
|
|
1578
1533
|
chunks.push({
|
|
1579
|
-
type: "image-
|
|
1580
|
-
index:
|
|
1581
|
-
data:
|
|
1534
|
+
type: "image-done",
|
|
1535
|
+
index: index >= 0 ? index : state.imageGenerations.size - 1,
|
|
1536
|
+
image: generatedImageFromData(data, { id: id || void 0, revisedPrompt: readWireString(event, "revised_prompt", "revisedPrompt") })
|
|
1582
1537
|
});
|
|
1583
1538
|
}
|
|
1584
|
-
if (eventType === "response.image_generation_call.completed" || eventType === "response.image_generation.done") {
|
|
1585
|
-
const imageId = eventAny.item_id || eventAny.itemId || eventAny.id || "";
|
|
1586
|
-
const imageData = eventAny.result || eventAny.image || eventAny.data || "";
|
|
1587
|
-
if (imageData) {
|
|
1588
|
-
let mediaType = "image/png";
|
|
1589
|
-
if (imageData.startsWith("data:")) {
|
|
1590
|
-
const match = imageData.match(/^data:([^;,]+)/);
|
|
1591
|
-
if (match) mediaType = match[1];
|
|
1592
|
-
}
|
|
1593
|
-
const existing = state.imageGenerations.get(imageId);
|
|
1594
|
-
if (existing) {
|
|
1595
|
-
existing.data = imageData;
|
|
1596
|
-
existing.status = "completed";
|
|
1597
|
-
}
|
|
1598
|
-
const imageIndex = Array.from(state.imageGenerations.keys()).indexOf(imageId);
|
|
1599
|
-
chunks.push({
|
|
1600
|
-
type: "image-done",
|
|
1601
|
-
index: imageIndex >= 0 ? imageIndex : state.imageGenerations.size - 1,
|
|
1602
|
-
image: {
|
|
1603
|
-
id: imageId || void 0,
|
|
1604
|
-
data: imageData,
|
|
1605
|
-
mediaType,
|
|
1606
|
-
revisedPrompt: eventAny.revised_prompt || eventAny.revisedPrompt || void 0
|
|
1607
|
-
}
|
|
1608
|
-
});
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
1539
|
break;
|
|
1612
1540
|
}
|
|
1613
1541
|
}
|
|
@@ -1654,7 +1582,7 @@ function truncateBase64(obj, maxLength = 50) {
|
|
|
1654
1582
|
function parseRawStreamEvent(jsonStr) {
|
|
1655
1583
|
try {
|
|
1656
1584
|
const event = JSON.parse(jsonStr);
|
|
1657
|
-
return event;
|
|
1585
|
+
return isRecord3(event) && typeof event.type === "string" ? event : null;
|
|
1658
1586
|
} catch {
|
|
1659
1587
|
return null;
|
|
1660
1588
|
}
|
|
@@ -1780,7 +1708,7 @@ var moonshotai_default = 'data:image/svg+xml,<svg fill="currentColor" fill-rule=
|
|
|
1780
1708
|
var nvidia_default = 'data:image/svg+xml,<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M10.212 8.976V7.62c.127-.01.256-.017.388-.021 3.596-.117 5.957 3.184 5.957 3.184s-2.548 3.647-5.282 3.647a3.227 3.227 0 01-1.063-.175v-4.109c1.4.174 1.681.812 2.523 2.258l1.873-1.627a4.905 4.905 0 00-3.67-1.846 6.594 6.594 0 00-.729.044m0-4.476v2.025c.13-.01.259-.019.388-.024 5.002-.174 8.261 4.226 8.261 4.226s-3.743 4.69-7.643 4.69c-.338 0-.675-.031-1.007-.092v1.25c.278.038.558.057.838.057 3.629 0 6.253-1.91 8.794-4.169.421.347 2.146 1.193 2.501 1.564-2.416 2.083-8.048 3.763-11.24 3.763-.308 0-.603-.02-.894-.048V19.5H24v-15H10.21zm0 9.756v1.068c-3.356-.616-4.287-4.21-4.287-4.21a7.173 7.173 0 014.287-2.138v1.172h-.005a3.182 3.182 0 00-2.502 1.178s.615 2.276 2.507 2.931m-5.961-3.3c1.436-1.935 3.604-3.148 5.961-3.336V6.523C5.81 6.887 2 10.723 2 10.723s2.158 6.427 8.21 7.015v-1.166C5.77 16 4.25 10.958 4.25 10.958h-.002z" fill="%2374B71B" fill-rule="nonzero"/></svg>%0A';
|
|
1781
1709
|
|
|
1782
1710
|
// src/vendor-icons/openai.svg
|
|
1783
|
-
var openai_default = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" fill="none" viewBox="0 0 128 128"><
|
|
1711
|
+
var openai_default = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" fill="none" viewBox="0 0 128 128"><rect width="128" height="128" rx="28" fill="%23000"/><path fill="%23fff" transform="translate(18 18) scale(0.71875)" d="M118.824 52.388a31.9 31.9 0 0 0-2.74-26.192 32.25 32.25 0 0 0-34.736-15.472A31.9 31.9 0 0 0 57.296 0C43.28-.032 30.844 8.992 26.532 22.328A31.9 31.9 0 0 0 5.208 37.796C-1.828 49.924-.224 65.212 9.176 75.612a31.9 31.9 0 0 0 2.74 26.192 32.25 32.25 0 0 0 34.736 15.472 31.88 31.88 0 0 0 24.052 10.72c14.024.036 26.464-8.996 30.776-22.344a31.9 31.9 0 0 0 21.324-15.468 32.26 32.26 0 0 0-3.976-37.804zm-48.112 67.244a23.9 23.9 0 0 1-15.356-5.552c.196-.104.536-.292.756-.428L81.6 98.932a4.14 4.14 0 0 0 2.096-3.628V59.372l10.772 6.22a.38.38 0 0 1 .208.296v29.756c-.016 13.232-10.732 23.96-23.964 23.988M19.176 97.62a23.88 23.88 0 0 1-2.86-16.072c.188.112.52.316.756.452L42.56 96.72a4.15 4.15 0 0 0 4.188 0l31.116-17.968v12.44a.4.4 0 0 1-.152.332L51.948 106.4c-11.476 6.608-26.132 2.68-32.768-8.78zm-6.708-55.636a23.9 23.9 0 0 1 12.484-10.516c0 .22-.012.608-.012.88v29.444a4.15 4.15 0 0 0 2.092 3.624L58.148 83.38 47.376 89.6a.38.38 0 0 1-.364.032L21.244 74.744c-11.452-6.632-15.38-21.284-8.78-32.756zm88.504 20.596L69.856 44.612l10.772-6.216a.38.38 0 0 1 .364-.032L106.76 53.24c11.472 6.628 15.404 21.304 8.776 32.776a23.98 23.98 0 0 1-12.48 10.512V66.204a4.14 4.14 0 0 0-2.08-3.624zm10.72-16.136c-.188-.116-.52-.316-.756-.452l-25.488-14.72a4.15 4.15 0 0 0-4.188 0L50.144 49.24V36.8a.4.4 0 0 1 .152-.332L76.06 21.604c11.476-6.62 26.148-2.68 32.764 8.8a23.98 23.98 0 0 1 2.86 16.04zM44.288 68.616l-10.776-6.22a.38.38 0 0 1-.208-.296V32.344C33.312 19.096 44.06 8.36 57.308 8.368a23.98 23.98 0 0 1 15.336 5.552c-.196.104-.532.292-.756.428L46.4 29.068a4.14 4.14 0 0 0-2.096 3.624l-.016 35.916zM50.14 56 64 47.996l13.86 8V72L64 80l-13.86-8z"/></svg>%0A';
|
|
1784
1712
|
|
|
1785
1713
|
// src/vendor-icons/qwen.svg
|
|
1786
1714
|
var qwen_default = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24"><title>Qwen</title><defs><linearGradient id="lobe-icons-qwen-fill" x1="0%" x2="100%" y1="0%" y2="0%"><stop offset="0%" stop-color="%2300055f" stop-opacity=".84"/><stop offset="100%" stop-color="%236f69f7" stop-opacity=".84"/></linearGradient></defs><path fill="url(%23lobe-icons-qwen-fill)" d="M12.604 1.34q.59 1.035 1.174 2.075a.18.18 0 0 0 .157.091h5.552q.26 0 .446.327l1.454 2.57c.19.337.24.478.024.837q-.39.646-.76 1.3l-.367.658c-.106.196-.223.28-.04.512l2.652 4.637c.172.301.111.494-.043.77q-.656 1.177-1.335 2.34c-.159.272-.352.375-.68.37a43 43 0 0 0-2.327.016.1.1 0 0 0-.081.05 575 575 0 0 1-2.705 4.74c-.169.293-.38.363-.725.364q-1.495.005-3.017.002a.54.54 0 0 1-.465-.271l-1.335-2.323a.09.09 0 0 0-.083-.049H4.982a1.8 1.8 0 0 1-.805-.092l-1.603-2.77a.54.54 0 0 1-.002-.54l1.207-2.12a.2.2 0 0 0 0-.197 551 551 0 0 1-1.875-3.272l-.79-1.395c-.16-.31-.173-.496.095-.965q.697-1.22 1.387-2.436c.132-.234.304-.334.584-.335a338 338 0 0 1 2.589-.001.12.12 0 0 0 .107-.063l2.806-4.895a.49.49 0 0 1 .422-.246c.524-.001 1.053 0 1.583-.006L11.704 1c.341-.003.724.032.9.34m-3.432.403a.06.06 0 0 0-.052.03L6.254 6.788a.16.16 0 0 1-.135.078H3.253q-.084 0-.041.074l5.81 10.156q.037.062-.034.063l-2.795.015a.22.22 0 0 0-.2.116l-1.32 2.31q-.066.117.068.118l5.716.008q.068 0 .104.061l1.403 2.454q.069.122.139 0l5.006-8.76.783-1.382a.055.055 0 0 1 .096 0l1.424 2.53a.12.12 0 0 0 .107.062l2.763-.02a.04.04 0 0 0 .035-.02.04.04 0 0 0 0-.04l-2.9-5.086a.11.11 0 0 1 0-.113l.293-.507 1.12-1.977q.036-.062-.035-.062H9.2q-.088 0-.043-.077l1.434-2.505a.11.11 0 0 0 0-.114L9.225 1.774a.06.06 0 0 0-.053-.031m6.29 8.02q.07 0 .034.06l-.832 1.465-2.613 4.585a.06.06 0 0 1-.05.029.06.06 0 0 1-.05-.029L8.498 9.841q-.03-.051.028-.054l.216-.012 6.722-.012z"/></svg>';
|
|
@@ -2390,7 +2318,7 @@ var OpenRouterProvider = class _OpenRouterProvider {
|
|
|
2390
2318
|
"Authorization": `Bearer ${apiKey}`
|
|
2391
2319
|
},
|
|
2392
2320
|
body: JSON.stringify({
|
|
2393
|
-
...params,
|
|
2321
|
+
...serializeResponsesRequest(params, request.providerOptions),
|
|
2394
2322
|
stream: false
|
|
2395
2323
|
}),
|
|
2396
2324
|
signal: request.signal
|
|
@@ -2422,7 +2350,7 @@ var OpenRouterProvider = class _OpenRouterProvider {
|
|
|
2422
2350
|
* Stream using the Chat Completions API (default).
|
|
2423
2351
|
*/
|
|
2424
2352
|
async streamWithChat(request) {
|
|
2425
|
-
const
|
|
2353
|
+
const toProviderError = this.toProviderError.bind(this);
|
|
2426
2354
|
const apiKey = this.config.apiKey;
|
|
2427
2355
|
const baseUrl = this.config.baseUrl || "https://openrouter.ai/api/v1";
|
|
2428
2356
|
try {
|
|
@@ -2459,12 +2387,10 @@ var OpenRouterProvider = class _OpenRouterProvider {
|
|
|
2459
2387
|
async *[Symbol.asyncIterator]() {
|
|
2460
2388
|
const state = createChatStreamState();
|
|
2461
2389
|
let finishChunk = null;
|
|
2462
|
-
let responseId = null;
|
|
2463
2390
|
try {
|
|
2464
2391
|
for await (const chunk of parseChatSSEStream(response, state)) {
|
|
2465
2392
|
if (chunk.type === "finish") {
|
|
2466
2393
|
finishChunk = chunk;
|
|
2467
|
-
responseId = chunk.responseId || null;
|
|
2468
2394
|
} else {
|
|
2469
2395
|
yield chunk;
|
|
2470
2396
|
}
|
|
@@ -2474,18 +2400,10 @@ var OpenRouterProvider = class _OpenRouterProvider {
|
|
|
2474
2400
|
const pricing = await _OpenRouterProvider.settleUsagePricing(pricingPromise);
|
|
2475
2401
|
if (pricing) finishChunk.usage.pricing = pricing;
|
|
2476
2402
|
}
|
|
2477
|
-
|
|
2478
|
-
...finishChunk,
|
|
2479
|
-
_asyncMetadata: responseId ? {
|
|
2480
|
-
generationId: responseId,
|
|
2481
|
-
apiKey,
|
|
2482
|
-
baseUrl
|
|
2483
|
-
} : void 0
|
|
2484
|
-
};
|
|
2485
|
-
yield finishWithMeta;
|
|
2403
|
+
yield finishChunk;
|
|
2486
2404
|
}
|
|
2487
2405
|
} catch (error) {
|
|
2488
|
-
const providerError =
|
|
2406
|
+
const providerError = toProviderError(error);
|
|
2489
2407
|
yield createChatErrorChunk(providerError.message, providerError.code);
|
|
2490
2408
|
}
|
|
2491
2409
|
}
|
|
@@ -2498,7 +2416,7 @@ var OpenRouterProvider = class _OpenRouterProvider {
|
|
|
2498
2416
|
* Stream using the Responses API (beta).
|
|
2499
2417
|
*/
|
|
2500
2418
|
async streamWithResponses(request) {
|
|
2501
|
-
const
|
|
2419
|
+
const toProviderError = this.toProviderError.bind(this);
|
|
2502
2420
|
const apiKey = this.config.apiKey;
|
|
2503
2421
|
const baseUrl = this.config.baseUrl || "https://openrouter.ai/api/v1";
|
|
2504
2422
|
try {
|
|
@@ -2512,7 +2430,7 @@ var OpenRouterProvider = class _OpenRouterProvider {
|
|
|
2512
2430
|
"Authorization": `Bearer ${apiKey}`
|
|
2513
2431
|
},
|
|
2514
2432
|
body: JSON.stringify({
|
|
2515
|
-
...params,
|
|
2433
|
+
...serializeResponsesRequest(params, request.providerOptions),
|
|
2516
2434
|
stream: true
|
|
2517
2435
|
}),
|
|
2518
2436
|
signal: request.signal
|
|
@@ -2532,12 +2450,10 @@ var OpenRouterProvider = class _OpenRouterProvider {
|
|
|
2532
2450
|
async *[Symbol.asyncIterator]() {
|
|
2533
2451
|
const state = createStreamState();
|
|
2534
2452
|
let finishChunk = null;
|
|
2535
|
-
let responseId = null;
|
|
2536
2453
|
try {
|
|
2537
2454
|
for await (const chunk of parseSSEStream(response, state)) {
|
|
2538
2455
|
if (chunk.type === "finish") {
|
|
2539
2456
|
finishChunk = chunk;
|
|
2540
|
-
responseId = chunk.responseId || null;
|
|
2541
2457
|
} else {
|
|
2542
2458
|
yield chunk;
|
|
2543
2459
|
}
|
|
@@ -2547,19 +2463,10 @@ var OpenRouterProvider = class _OpenRouterProvider {
|
|
|
2547
2463
|
const pricing = await _OpenRouterProvider.settleUsagePricing(pricingPromise);
|
|
2548
2464
|
if (pricing) finishChunk.usage.pricing = pricing;
|
|
2549
2465
|
}
|
|
2550
|
-
|
|
2551
|
-
...finishChunk,
|
|
2552
|
-
// Include what's needed to fetch metadata later
|
|
2553
|
-
_asyncMetadata: responseId ? {
|
|
2554
|
-
generationId: responseId,
|
|
2555
|
-
apiKey,
|
|
2556
|
-
baseUrl
|
|
2557
|
-
} : void 0
|
|
2558
|
-
};
|
|
2559
|
-
yield finishWithMeta;
|
|
2466
|
+
yield finishChunk;
|
|
2560
2467
|
}
|
|
2561
2468
|
} catch (error) {
|
|
2562
|
-
const providerError =
|
|
2469
|
+
const providerError = toProviderError(error);
|
|
2563
2470
|
yield createErrorChunk(providerError.message, providerError.code);
|
|
2564
2471
|
}
|
|
2565
2472
|
}
|
|
@@ -2607,9 +2514,10 @@ var OpenRouterProvider = class _OpenRouterProvider {
|
|
|
2607
2514
|
return error;
|
|
2608
2515
|
}
|
|
2609
2516
|
if (error instanceof Error) {
|
|
2610
|
-
const
|
|
2611
|
-
const
|
|
2612
|
-
const
|
|
2517
|
+
const status = "status" in error && typeof error.status === "number" && error.status ? error.status : "statusCode" in error && typeof error.statusCode === "number" ? error.statusCode : void 0;
|
|
2518
|
+
const headers = "headers" in error ? error.headers : void 0;
|
|
2519
|
+
const retryHeader = headers instanceof Headers ? headers.get("retry-after") : headers !== null && typeof headers === "object" && "retry-after" in headers ? headers["retry-after"] : void 0;
|
|
2520
|
+
const retryAfter = typeof retryHeader === "string" ? parseInt(retryHeader, 10) : void 0;
|
|
2613
2521
|
if (status === 429) {
|
|
2614
2522
|
return new ProviderError(error.message, "rate_limit", status, retryAfter);
|
|
2615
2523
|
}
|
|
@@ -2619,10 +2527,10 @@ var OpenRouterProvider = class _OpenRouterProvider {
|
|
|
2619
2527
|
if (status === 400) {
|
|
2620
2528
|
return new ProviderError(error.message, "invalid_request", status);
|
|
2621
2529
|
}
|
|
2622
|
-
if (status >= 500) {
|
|
2530
|
+
if (status !== void 0 && status >= 500) {
|
|
2623
2531
|
return new ProviderError(error.message, "server_error", status);
|
|
2624
2532
|
}
|
|
2625
|
-
if (error.name === "AbortError" ||
|
|
2533
|
+
if (error.name === "AbortError" || error.name === "RequestTimeoutError" || "code" in error && error.code === "ETIMEDOUT") {
|
|
2626
2534
|
return new ProviderError(error.message, "timeout");
|
|
2627
2535
|
}
|
|
2628
2536
|
return new ProviderError(error.message, "unknown", status);
|
|
@@ -2640,11 +2548,9 @@ var OpenRouterProvider = class _OpenRouterProvider {
|
|
|
2640
2548
|
const apiMode = this.getApiMode(request);
|
|
2641
2549
|
if (apiMode === "responses") {
|
|
2642
2550
|
const params2 = buildCreateParams(request, await resolveRequestReasoningLevels(request, (model) => this.getModelCapabilities(model)));
|
|
2643
|
-
|
|
2644
|
-
params2.provider = { only: this.config.providers };
|
|
2645
|
-
}
|
|
2551
|
+
this.applyConfiguredProvidersToResponses(params2);
|
|
2646
2552
|
return {
|
|
2647
|
-
body: truncateBase64(params2),
|
|
2553
|
+
body: truncateBase64(serializeResponsesRequest(params2, request.providerOptions)),
|
|
2648
2554
|
messagesPath: "input",
|
|
2649
2555
|
metadata: {
|
|
2650
2556
|
endpoint: "https://openrouter.ai/api/v1/responses"
|