@absolutejs/ai 0.0.50 → 0.0.51
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/README.md +22 -12
- package/dist/ai/client/index.js +30 -1
- package/dist/ai/client/index.js.map +5 -5
- package/dist/ai/index.js +531 -56
- package/dist/ai/index.js.map +15 -15
- package/dist/ai/providers/anthropic.js +100 -25
- package/dist/ai/providers/anthropic.js.map +5 -5
- package/dist/ai/providers/gemini.js +5 -2
- package/dist/ai/providers/gemini.js.map +4 -4
- package/dist/ai/providers/ollama.js +5 -2
- package/dist/ai/providers/ollama.js.map +4 -4
- package/dist/ai/providers/openai.js +56 -10
- package/dist/ai/providers/openai.js.map +5 -5
- package/dist/ai/providers/openaiCompatible.js +56 -10
- package/dist/ai/providers/openaiCompatible.js.map +5 -5
- package/dist/ai/providers/openaiResponses.js +100 -16
- package/dist/ai/providers/openaiResponses.js.map +5 -5
- package/dist/ai/providers/openrouter.js +888 -38
- package/dist/ai/providers/openrouter.js.map +10 -9
- package/dist/angular/ai/index.js +30 -1
- package/dist/angular/ai/index.js.map +5 -5
- package/dist/react/ai/index.js +30 -1
- package/dist/react/ai/index.js.map +5 -5
- package/dist/src/ai/client/actions.d.ts +53 -0
- package/dist/src/ai/errors/providerError.d.ts +3 -0
- package/dist/src/ai/index.d.ts +2 -2
- package/dist/src/ai/providers/openrouter.d.ts +46 -2
- package/dist/src/ai/providers/openrouterClient.d.ts +132 -3
- package/dist/src/ai/streamAIWithTools.d.ts +6 -0
- package/dist/svelte/ai/index.js +30 -1
- package/dist/svelte/ai/index.js.map +5 -5
- package/dist/types/ai.d.ts +54 -3
- package/dist/types/anthropic.d.ts +13 -5
- package/dist/vue/ai/index.js +30 -1
- package/dist/vue/ai/index.js.map +5 -5
- package/package.json +1 -1
|
@@ -43,6 +43,7 @@ class ProviderError extends Error {
|
|
|
43
43
|
status;
|
|
44
44
|
type;
|
|
45
45
|
retryable;
|
|
46
|
+
metadata;
|
|
46
47
|
statusPageUrl;
|
|
47
48
|
constructor(init) {
|
|
48
49
|
super(init.message, init.cause === undefined ? undefined : { cause: init.cause });
|
|
@@ -51,6 +52,7 @@ class ProviderError extends Error {
|
|
|
51
52
|
this.status = init.status ?? null;
|
|
52
53
|
this.type = init.type ?? null;
|
|
53
54
|
this.retryable = init.retryable;
|
|
55
|
+
this.metadata = init.metadata;
|
|
54
56
|
this.statusPageUrl = providerStatusPage(init.provider);
|
|
55
57
|
}
|
|
56
58
|
static fromResponse(provider, status, body, type) {
|
|
@@ -223,7 +225,8 @@ var withResilience = (provider, providerName = "unknown") => {
|
|
|
223
225
|
yield* attempt(params, attemptNo + 1);
|
|
224
226
|
return;
|
|
225
227
|
}
|
|
226
|
-
|
|
228
|
+
if (providerError.retryable)
|
|
229
|
+
noteFailure(providerName, providerError);
|
|
227
230
|
throw providerError;
|
|
228
231
|
}
|
|
229
232
|
};
|
|
@@ -505,6 +508,9 @@ var buildRequestBody = (params, capabilityModel = params.model) => {
|
|
|
505
508
|
content: mapOpenAIContent(msg),
|
|
506
509
|
role: msg.role
|
|
507
510
|
})), params);
|
|
511
|
+
if (params.systemPrompt) {
|
|
512
|
+
messages.unshift({ content: params.systemPrompt, role: "system" });
|
|
513
|
+
}
|
|
508
514
|
const body = {
|
|
509
515
|
messages,
|
|
510
516
|
model: params.model,
|
|
@@ -648,6 +654,18 @@ var processDelta = function* (delta, pendingToolCalls) {
|
|
|
648
654
|
if (typeof delta.content === "string") {
|
|
649
655
|
yield { content: delta.content, type: "text" };
|
|
650
656
|
}
|
|
657
|
+
if (isRecord(delta.audio)) {
|
|
658
|
+
const audio = delta.audio;
|
|
659
|
+
if (typeof audio.data === "string" || typeof audio.transcript === "string") {
|
|
660
|
+
yield {
|
|
661
|
+
audioId: typeof audio.id === "string" ? audio.id : undefined,
|
|
662
|
+
data: typeof audio.data === "string" ? audio.data : "",
|
|
663
|
+
format: typeof audio.format === "string" ? audio.format : "pcm16",
|
|
664
|
+
transcript: typeof audio.transcript === "string" ? audio.transcript : undefined,
|
|
665
|
+
type: "audio"
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
}
|
|
651
669
|
if (isRecordArray(delta.tool_calls)) {
|
|
652
670
|
processToolCallDeltas(delta.tool_calls, pendingToolCalls);
|
|
653
671
|
}
|
|
@@ -716,7 +734,7 @@ var narrowUsageRecord = (parsed) => {
|
|
|
716
734
|
}
|
|
717
735
|
return normalized;
|
|
718
736
|
};
|
|
719
|
-
var processSSELine = function* (line, pendingToolCalls) {
|
|
737
|
+
var processSSELine = function* (line, pendingToolCalls, providerName) {
|
|
720
738
|
const trimmed = line.trim();
|
|
721
739
|
if (!trimmed || !trimmed.startsWith("data: ")) {
|
|
722
740
|
return;
|
|
@@ -732,6 +750,20 @@ var processSSELine = function* (line, pendingToolCalls) {
|
|
|
732
750
|
} catch {
|
|
733
751
|
return;
|
|
734
752
|
}
|
|
753
|
+
if (isRecord(parsed.error)) {
|
|
754
|
+
const error = parsed.error;
|
|
755
|
+
const metadata2 = isRecord(error.metadata) ? error.metadata : undefined;
|
|
756
|
+
const status = typeof error.code === "number" ? error.code : null;
|
|
757
|
+
const type = metadata2 && typeof metadata2.error_type === "string" ? metadata2.error_type : typeof error.error_type === "string" ? error.error_type : null;
|
|
758
|
+
throw new ProviderError({
|
|
759
|
+
message: typeof error.message === "string" ? error.message : "OpenRouter stream failed",
|
|
760
|
+
metadata: metadata2,
|
|
761
|
+
provider: providerName,
|
|
762
|
+
retryable: status === 408 || status === 409 || status === 425 || status === 429 || status !== null && status >= 500,
|
|
763
|
+
status,
|
|
764
|
+
type
|
|
765
|
+
});
|
|
766
|
+
}
|
|
735
767
|
const usageUpdate = narrowUsageRecord(parsed);
|
|
736
768
|
if (usageUpdate) {
|
|
737
769
|
yield { type: "usage_update", usage: usageUpdate };
|
|
@@ -748,11 +780,24 @@ var processSSELine = function* (line, pendingToolCalls) {
|
|
|
748
780
|
if (!firstChoice) {
|
|
749
781
|
return;
|
|
750
782
|
}
|
|
783
|
+
if (isRecord(firstChoice.error)) {
|
|
784
|
+
const error = firstChoice.error;
|
|
785
|
+
const metadata2 = isRecord(error.metadata) ? error.metadata : undefined;
|
|
786
|
+
const status = typeof error.code === "number" ? error.code : null;
|
|
787
|
+
throw new ProviderError({
|
|
788
|
+
message: typeof error.message === "string" ? error.message : "OpenRouter stream failed",
|
|
789
|
+
metadata: metadata2,
|
|
790
|
+
provider: providerName,
|
|
791
|
+
retryable: status === 429 || status !== null && status >= 500,
|
|
792
|
+
status,
|
|
793
|
+
type: metadata2 && typeof metadata2.error_type === "string" ? metadata2.error_type : null
|
|
794
|
+
});
|
|
795
|
+
}
|
|
751
796
|
yield* processChoice(firstChoice, pendingToolCalls);
|
|
752
797
|
};
|
|
753
798
|
var isUsageUpdate = (chunk) => chunk.type === "usage_update";
|
|
754
|
-
var collectYieldableChunks = (line, pendingToolCalls, usageRef, metadataRef) => {
|
|
755
|
-
const allChunks = Array.from(processSSELine(line, pendingToolCalls));
|
|
799
|
+
var collectYieldableChunks = (line, pendingToolCalls, usageRef, metadataRef, providerName) => {
|
|
800
|
+
const allChunks = Array.from(processSSELine(line, pendingToolCalls, providerName));
|
|
756
801
|
const usageChunks = allChunks.filter(isUsageUpdate);
|
|
757
802
|
const lastUsage = usageChunks.at(NOT_FOUND);
|
|
758
803
|
if (lastUsage) {
|
|
@@ -772,9 +817,9 @@ var collectYieldableChunks = (line, pendingToolCalls, usageRef, metadataRef) =>
|
|
|
772
817
|
}
|
|
773
818
|
return allChunks.filter((chunk) => !isUsageUpdate(chunk) && chunk.type !== "response_metadata");
|
|
774
819
|
};
|
|
775
|
-
var processSSELines = function* (lines, pendingToolCalls, usageRef, metadataRef) {
|
|
820
|
+
var processSSELines = function* (lines, pendingToolCalls, usageRef, metadataRef, providerName) {
|
|
776
821
|
for (const line of lines) {
|
|
777
|
-
yield* collectYieldableChunks(line, pendingToolCalls, usageRef, metadataRef);
|
|
822
|
+
yield* collectYieldableChunks(line, pendingToolCalls, usageRef, metadataRef, providerName);
|
|
778
823
|
}
|
|
779
824
|
};
|
|
780
825
|
var processStreamValue = (value, decoder, state) => {
|
|
@@ -787,16 +832,17 @@ var processStreamValue = (value, decoder, state) => {
|
|
|
787
832
|
var drainReader = async function* (reader, decoder, state, signal) {
|
|
788
833
|
for (let result = await reader.read();!result.done && !signal?.aborted; result = await reader.read()) {
|
|
789
834
|
const lines = processStreamValue(result.value, decoder, state);
|
|
790
|
-
yield* processSSELines(lines, state.pendingToolCalls, state.usageRef, state.metadataRef);
|
|
835
|
+
yield* processSSELines(lines, state.pendingToolCalls, state.usageRef, state.metadataRef, state.providerName);
|
|
791
836
|
}
|
|
792
837
|
};
|
|
793
|
-
var parseSSEStream = async function* (body, initialMetadata, signal) {
|
|
838
|
+
var parseSSEStream = async function* (body, initialMetadata, providerName = "openai", signal) {
|
|
794
839
|
const reader = body.getReader();
|
|
795
840
|
const decoder = new TextDecoder;
|
|
796
841
|
const state = {
|
|
797
842
|
buffer: "",
|
|
798
843
|
metadataRef: { current: initialMetadata },
|
|
799
844
|
pendingToolCalls: new Map,
|
|
845
|
+
providerName,
|
|
800
846
|
usageRef: { current: undefined }
|
|
801
847
|
};
|
|
802
848
|
try {
|
|
@@ -841,7 +887,7 @@ var fetchOpenAIStream = async function* (baseUrl, apiKey, body, fetchImpl, heade
|
|
|
841
887
|
cacheStatus: response.headers.get("X-OpenRouter-Cache-Status") ?? undefined,
|
|
842
888
|
cacheTtl: response.headers.get("X-OpenRouter-Cache-TTL") ?? undefined
|
|
843
889
|
}
|
|
844
|
-
}, signal);
|
|
890
|
+
}, providerName, signal);
|
|
845
891
|
};
|
|
846
892
|
var openai = (config2) => {
|
|
847
893
|
const baseUrl = config2.baseUrl ?? DEFAULT_BASE_URL;
|
|
@@ -923,7 +969,12 @@ var mapContentToResponsesFormat = (content) => {
|
|
|
923
969
|
};
|
|
924
970
|
var hasToolBlocks = (content) => content.some((block) => block.type === "tool_use" || block.type === "tool_result");
|
|
925
971
|
var convertToolBlock = (block) => {
|
|
972
|
+
if (block.type === "provider_data" && block.provider === "openrouter") {
|
|
973
|
+
return { ...block.data };
|
|
974
|
+
}
|
|
926
975
|
if (block.type === "tool_use") {
|
|
976
|
+
if (block.providerData)
|
|
977
|
+
return { ...block.providerData };
|
|
927
978
|
return {
|
|
928
979
|
arguments: typeof block.input === "string" ? block.input : JSON.stringify(block.input),
|
|
929
980
|
call_id: block.id,
|
|
@@ -1059,11 +1110,32 @@ var extractUsage2 = (response) => {
|
|
|
1059
1110
|
const { usage } = response;
|
|
1060
1111
|
const input = typeof usage.input_tokens === "number" ? usage.input_tokens : 0;
|
|
1061
1112
|
const cached = isRecord2(usage.input_tokens_details) && typeof usage.input_tokens_details.cached_tokens === "number" ? usage.input_tokens_details.cached_tokens : 0;
|
|
1062
|
-
|
|
1113
|
+
const outputDetails = isRecord2(usage.output_tokens_details) ? usage.output_tokens_details : undefined;
|
|
1114
|
+
const inputDetails = isRecord2(usage.input_tokens_details) ? usage.input_tokens_details : undefined;
|
|
1115
|
+
const costDetails = isRecord2(usage.cost_details) ? usage.cost_details : undefined;
|
|
1116
|
+
const normalized = {
|
|
1063
1117
|
cacheReadInputTokens: cached,
|
|
1118
|
+
cacheWriteInputTokens: inputDetails && typeof inputDetails.cache_write_tokens === "number" ? inputDetails.cache_write_tokens : undefined,
|
|
1119
|
+
costCredits: typeof usage.cost === "number" ? usage.cost : undefined,
|
|
1064
1120
|
inputTokens: Math.max(0, input - cached),
|
|
1065
|
-
outputTokens: typeof usage.output_tokens === "number" ? usage.output_tokens : 0
|
|
1121
|
+
outputTokens: typeof usage.output_tokens === "number" ? usage.output_tokens : 0,
|
|
1122
|
+
reasoningTokens: outputDetails && typeof outputDetails.reasoning_tokens === "number" ? outputDetails.reasoning_tokens : undefined,
|
|
1123
|
+
upstreamInferenceCostCredits: costDetails && typeof costDetails.upstream_inference_cost === "number" ? costDetails.upstream_inference_cost : undefined
|
|
1066
1124
|
};
|
|
1125
|
+
if (isRecord2(usage.server_tool_use)) {
|
|
1126
|
+
normalized.serverToolUse = Object.fromEntries(Object.entries(usage.server_tool_use).filter((entry) => typeof entry[1] === "number"));
|
|
1127
|
+
}
|
|
1128
|
+
return normalized;
|
|
1129
|
+
};
|
|
1130
|
+
var extractResponseMetadata = (response) => {
|
|
1131
|
+
const providerMetadata = isRecord2(response.openrouter_metadata) ? response.openrouter_metadata : undefined;
|
|
1132
|
+
const generationId = typeof response.id === "string" ? response.id : undefined;
|
|
1133
|
+
const model = typeof response.model === "string" ? response.model : undefined;
|
|
1134
|
+
const provider = typeof response.provider === "string" ? response.provider : undefined;
|
|
1135
|
+
const serviceTier = typeof response.service_tier === "string" ? response.service_tier : undefined;
|
|
1136
|
+
if (!providerMetadata && !generationId && !model && !provider && !serviceTier)
|
|
1137
|
+
return;
|
|
1138
|
+
return { generationId, model, provider, providerMetadata, serviceTier };
|
|
1067
1139
|
};
|
|
1068
1140
|
var extractMimeFormat = (mimeType) => {
|
|
1069
1141
|
if (typeof mimeType !== "string") {
|
|
@@ -1120,6 +1192,7 @@ var processFunctionCallArgumentsDone = function* (parsed, pendingCalls) {
|
|
|
1120
1192
|
id: callId || pending?.callId || itemId,
|
|
1121
1193
|
input: parseToolInput2(args),
|
|
1122
1194
|
name,
|
|
1195
|
+
providerData: pending?.providerData ? { ...pending.providerData, arguments: args } : undefined,
|
|
1123
1196
|
type: "tool_use"
|
|
1124
1197
|
};
|
|
1125
1198
|
};
|
|
@@ -1138,9 +1211,21 @@ var processOutputItemAdded = (parsed, pendingCalls) => {
|
|
|
1138
1211
|
pendingCalls.set(itemId, {
|
|
1139
1212
|
arguments: "",
|
|
1140
1213
|
callId,
|
|
1141
|
-
name
|
|
1214
|
+
name,
|
|
1215
|
+
providerData: { ...item }
|
|
1142
1216
|
});
|
|
1143
1217
|
};
|
|
1218
|
+
var processOutputItemDone = function* (parsed) {
|
|
1219
|
+
if (!isRecord2(parsed.item) || typeof parsed.item.type !== "string")
|
|
1220
|
+
return;
|
|
1221
|
+
if (!parsed.item.type.startsWith("openrouter:"))
|
|
1222
|
+
return;
|
|
1223
|
+
yield {
|
|
1224
|
+
data: { ...parsed.item },
|
|
1225
|
+
provider: "openrouter",
|
|
1226
|
+
type: "provider_event"
|
|
1227
|
+
};
|
|
1228
|
+
};
|
|
1144
1229
|
var isCompletedImageGeneration = (item) => item.type === "image_generation_call" && item.status === "completed" && typeof item.result === "string" && item.result !== "";
|
|
1145
1230
|
var buildImageChunk = (item) => ({
|
|
1146
1231
|
data: typeof item.result === "string" ? item.result : "",
|
|
@@ -1156,6 +1241,30 @@ var extractImageFromOutput = function* (output) {
|
|
|
1156
1241
|
yield buildImageChunk(item);
|
|
1157
1242
|
}
|
|
1158
1243
|
};
|
|
1244
|
+
var extractCitationsFromOutput = function* (output) {
|
|
1245
|
+
for (const item of output) {
|
|
1246
|
+
if (!isRecordArray2(item.content))
|
|
1247
|
+
continue;
|
|
1248
|
+
for (const content of item.content) {
|
|
1249
|
+
if (!Array.isArray(content.annotations))
|
|
1250
|
+
continue;
|
|
1251
|
+
for (const annotation of content.annotations) {
|
|
1252
|
+
if (!isRecord2(annotation) || annotation.type !== "url_citation")
|
|
1253
|
+
continue;
|
|
1254
|
+
if (typeof annotation.url !== "string")
|
|
1255
|
+
continue;
|
|
1256
|
+
yield {
|
|
1257
|
+
content: typeof annotation.content === "string" ? annotation.content : undefined,
|
|
1258
|
+
endIndex: typeof annotation.end_index === "number" ? annotation.end_index : undefined,
|
|
1259
|
+
startIndex: typeof annotation.start_index === "number" ? annotation.start_index : undefined,
|
|
1260
|
+
title: typeof annotation.title === "string" ? annotation.title : undefined,
|
|
1261
|
+
type: "citation",
|
|
1262
|
+
url: annotation.url
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
};
|
|
1159
1268
|
var processCompleted = function* (parsed) {
|
|
1160
1269
|
if (!isRecord2(parsed.response)) {
|
|
1161
1270
|
yield { type: "done", usage: undefined };
|
|
@@ -1163,12 +1272,26 @@ var processCompleted = function* (parsed) {
|
|
|
1163
1272
|
}
|
|
1164
1273
|
const { response } = parsed;
|
|
1165
1274
|
const usage = extractUsage2(response);
|
|
1275
|
+
const metadata = extractResponseMetadata(response);
|
|
1166
1276
|
if (isRecordArray2(response.output)) {
|
|
1277
|
+
yield* extractCitationsFromOutput(response.output);
|
|
1167
1278
|
yield* extractImageFromOutput(response.output);
|
|
1168
1279
|
}
|
|
1169
|
-
yield { type: "done", usage };
|
|
1280
|
+
yield { metadata, type: "done", usage };
|
|
1170
1281
|
};
|
|
1171
|
-
var
|
|
1282
|
+
var responseFailure = (eventType, parsed, providerName) => {
|
|
1283
|
+
const response = isRecord2(parsed.response) ? parsed.response : parsed;
|
|
1284
|
+
const error = isRecord2(response.error) ? response.error : undefined;
|
|
1285
|
+
const type = typeof response.error_type === "string" ? response.error_type : error && typeof error.code === "string" ? error.code : eventType;
|
|
1286
|
+
return new ProviderError({
|
|
1287
|
+
message: error && typeof error.message === "string" ? error.message : `OpenRouter Responses API: ${eventType}`,
|
|
1288
|
+
metadata: response,
|
|
1289
|
+
provider: providerName,
|
|
1290
|
+
retryable: type === "rate_limit_exceeded" || type === "provider_overloaded" || type === "provider_unavailable" || type === "server",
|
|
1291
|
+
type
|
|
1292
|
+
});
|
|
1293
|
+
};
|
|
1294
|
+
var processSSEEvent = function* (eventType, parsed, pendingCalls, providerName) {
|
|
1172
1295
|
switch (eventType) {
|
|
1173
1296
|
case "response.reasoning_summary_text.delta": {
|
|
1174
1297
|
const delta = typeof parsed.delta === "string" ? parsed.delta : "";
|
|
@@ -1189,6 +1312,9 @@ var processSSEEvent = function* (eventType, parsed, pendingCalls) {
|
|
|
1189
1312
|
case "response.output_item.added":
|
|
1190
1313
|
processOutputItemAdded(parsed, pendingCalls);
|
|
1191
1314
|
break;
|
|
1315
|
+
case "response.output_item.done":
|
|
1316
|
+
yield* processOutputItemDone(parsed);
|
|
1317
|
+
break;
|
|
1192
1318
|
case "response.function_call_arguments.delta":
|
|
1193
1319
|
processFunctionCallArgumentsDelta(parsed, pendingCalls);
|
|
1194
1320
|
break;
|
|
@@ -1199,11 +1325,10 @@ var processSSEEvent = function* (eventType, parsed, pendingCalls) {
|
|
|
1199
1325
|
yield* processCompleted(parsed);
|
|
1200
1326
|
break;
|
|
1201
1327
|
case "response.failed":
|
|
1202
|
-
case "response.incomplete":
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
throw
|
|
1206
|
-
}
|
|
1328
|
+
case "response.incomplete":
|
|
1329
|
+
case "response.error":
|
|
1330
|
+
case "error":
|
|
1331
|
+
throw responseFailure(eventType, parsed, providerName);
|
|
1207
1332
|
}
|
|
1208
1333
|
};
|
|
1209
1334
|
var flushSSEBuffer = function* (state) {
|
|
@@ -1212,7 +1337,7 @@ var flushSSEBuffer = function* (state) {
|
|
|
1212
1337
|
}
|
|
1213
1338
|
const parsed = parseJSON(state.buffer);
|
|
1214
1339
|
if (parsed) {
|
|
1215
|
-
yield* processSSEEvent(state.currentEvent, parsed, state.pendingCalls);
|
|
1340
|
+
yield* processSSEEvent(state.currentEvent, parsed, state.pendingCalls, state.providerName);
|
|
1216
1341
|
}
|
|
1217
1342
|
state.currentEvent = "";
|
|
1218
1343
|
state.buffer = "";
|
|
@@ -1250,17 +1375,19 @@ var drainReader2 = async function* (reader, decoder, state, signal) {
|
|
|
1250
1375
|
yield* processSSELines2([textBuffer, ""], state);
|
|
1251
1376
|
}
|
|
1252
1377
|
};
|
|
1253
|
-
var parseSSEStream2 = async function* (body, signal) {
|
|
1378
|
+
var parseSSEStream2 = async function* (body, providerName, signal) {
|
|
1254
1379
|
const reader = body.getReader();
|
|
1255
1380
|
const decoder = new TextDecoder;
|
|
1256
1381
|
const state = {
|
|
1257
1382
|
buffer: "",
|
|
1258
1383
|
currentEvent: "",
|
|
1259
1384
|
pendingCalls: new Map,
|
|
1260
|
-
usage: undefined
|
|
1385
|
+
usage: undefined,
|
|
1386
|
+
providerName
|
|
1261
1387
|
};
|
|
1262
1388
|
try {
|
|
1263
1389
|
yield* drainReader2(reader, decoder, state, signal);
|
|
1390
|
+
yield* flushSSEBuffer(state);
|
|
1264
1391
|
} finally {
|
|
1265
1392
|
reader.releaseLock();
|
|
1266
1393
|
}
|
|
@@ -1288,7 +1415,7 @@ var fetchResponsesStream = async function* (baseUrl, apiKey, body, fetchImpl, he
|
|
|
1288
1415
|
retryable: true
|
|
1289
1416
|
});
|
|
1290
1417
|
}
|
|
1291
|
-
yield* parseSSEStream2(response.body, signal);
|
|
1418
|
+
yield* parseSSEStream2(response.body, providerName, signal);
|
|
1292
1419
|
};
|
|
1293
1420
|
var resolveImageModels = (imageModels) => {
|
|
1294
1421
|
if (!imageModels) {
|
|
@@ -1324,8 +1451,546 @@ var openaiResponses = (config2) => {
|
|
|
1324
1451
|
}, providerName);
|
|
1325
1452
|
};
|
|
1326
1453
|
|
|
1454
|
+
// src/ai/providers/anthropic.ts
|
|
1455
|
+
var h2IfHttps3 = (url) => url.startsWith("https://") ? { protocol: "http2" } : {};
|
|
1456
|
+
var DEFAULT_BASE_URL3 = "https://api.anthropic.com";
|
|
1457
|
+
var API_VERSION = "2023-06-01";
|
|
1458
|
+
var DEFAULT_MAX_TOKENS = 32000;
|
|
1459
|
+
var EVENT_PREFIX_LENGTH2 = 7;
|
|
1460
|
+
var DATA_PREFIX_LENGTH2 = 6;
|
|
1461
|
+
var EMPTY_CHUNKS = [];
|
|
1462
|
+
var isRecord3 = (val) => typeof val === "object" && val !== null;
|
|
1463
|
+
var mapContentBlock = (block) => {
|
|
1464
|
+
if (block.type === "thinking") {
|
|
1465
|
+
return {
|
|
1466
|
+
signature: block.signature,
|
|
1467
|
+
thinking: block.thinking,
|
|
1468
|
+
type: "thinking"
|
|
1469
|
+
};
|
|
1470
|
+
}
|
|
1471
|
+
if (block.type === "image") {
|
|
1472
|
+
return {
|
|
1473
|
+
source: block.source,
|
|
1474
|
+
type: "image"
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
if (block.type === "document") {
|
|
1478
|
+
return {
|
|
1479
|
+
source: block.source,
|
|
1480
|
+
type: "document"
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1483
|
+
if (block.type === "tool_result") {
|
|
1484
|
+
return {
|
|
1485
|
+
content: block.content,
|
|
1486
|
+
tool_use_id: block.tool_use_id,
|
|
1487
|
+
type: "tool_result"
|
|
1488
|
+
};
|
|
1489
|
+
}
|
|
1490
|
+
if (block.type === "tool_use") {
|
|
1491
|
+
if (block.providerData)
|
|
1492
|
+
return { ...block.providerData };
|
|
1493
|
+
return {
|
|
1494
|
+
id: block.id,
|
|
1495
|
+
input: block.input,
|
|
1496
|
+
name: block.name,
|
|
1497
|
+
type: "tool_use"
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1500
|
+
if (block.type === "audio" || block.type === "video") {
|
|
1501
|
+
throw new Error(`Anthropic does not support ${block.type} content blocks`);
|
|
1502
|
+
}
|
|
1503
|
+
if (block.type === "provider_data") {
|
|
1504
|
+
return { ...block.data };
|
|
1505
|
+
}
|
|
1506
|
+
return { text: block.content, type: "text" };
|
|
1507
|
+
};
|
|
1508
|
+
var mapMessage = (msg) => ({
|
|
1509
|
+
content: typeof msg.content === "string" ? msg.content : msg.content.map(mapContentBlock),
|
|
1510
|
+
role: msg.role === "system" ? "user" : msg.role
|
|
1511
|
+
});
|
|
1512
|
+
var mapToolDefinition2 = (tool) => ({
|
|
1513
|
+
description: tool.description,
|
|
1514
|
+
input_schema: tool.input_schema,
|
|
1515
|
+
name: tool.name
|
|
1516
|
+
});
|
|
1517
|
+
var cacheLastContentBlock = (msg) => {
|
|
1518
|
+
const cacheControl = { type: "ephemeral" };
|
|
1519
|
+
if (typeof msg.content === "string") {
|
|
1520
|
+
return {
|
|
1521
|
+
content: [
|
|
1522
|
+
{ cache_control: cacheControl, text: msg.content, type: "text" }
|
|
1523
|
+
],
|
|
1524
|
+
role: msg.role
|
|
1525
|
+
};
|
|
1526
|
+
}
|
|
1527
|
+
if (msg.content.length === 0)
|
|
1528
|
+
return msg;
|
|
1529
|
+
const blocks = [...msg.content];
|
|
1530
|
+
blocks[blocks.length - 1] = {
|
|
1531
|
+
...blocks[blocks.length - 1],
|
|
1532
|
+
cache_control: cacheControl
|
|
1533
|
+
};
|
|
1534
|
+
return { content: blocks, role: msg.role };
|
|
1535
|
+
};
|
|
1536
|
+
var buildRequestBody3 = (params, configuredMax, configCaching) => {
|
|
1537
|
+
const caching = params.promptCaching ?? configCaching;
|
|
1538
|
+
const cacheSystem = params.cacheSystemPrompt ?? caching;
|
|
1539
|
+
const messages = params.messages.filter((msg) => msg.role !== "system").map(mapMessage);
|
|
1540
|
+
if (caching && messages.length > 1) {
|
|
1541
|
+
const last = messages[messages.length - 1];
|
|
1542
|
+
if (last) {
|
|
1543
|
+
messages[messages.length - 1] = cacheLastContentBlock(last);
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
const max = typeof params.maxTokens === "number" ? params.maxTokens : configuredMax;
|
|
1547
|
+
const body = {
|
|
1548
|
+
max_tokens: max,
|
|
1549
|
+
messages,
|
|
1550
|
+
model: params.model,
|
|
1551
|
+
stream: true
|
|
1552
|
+
};
|
|
1553
|
+
if (params.systemPrompt) {
|
|
1554
|
+
body.system = cacheSystem ? [
|
|
1555
|
+
{
|
|
1556
|
+
cache_control: { type: "ephemeral" },
|
|
1557
|
+
text: params.systemPrompt,
|
|
1558
|
+
type: "text"
|
|
1559
|
+
}
|
|
1560
|
+
] : params.systemPrompt;
|
|
1561
|
+
}
|
|
1562
|
+
if (params.tools && params.tools.length > 0) {
|
|
1563
|
+
const tools = params.tools.map(mapToolDefinition2);
|
|
1564
|
+
if (caching) {
|
|
1565
|
+
tools[tools.length - 1] = {
|
|
1566
|
+
...tools[tools.length - 1],
|
|
1567
|
+
cache_control: { type: "ephemeral" }
|
|
1568
|
+
};
|
|
1569
|
+
}
|
|
1570
|
+
body.tools = tools;
|
|
1571
|
+
if (params.toolChoice === "auto" || params.toolChoice === "none") {
|
|
1572
|
+
body.tool_choice = { type: params.toolChoice };
|
|
1573
|
+
} else if (params.toolChoice === "required") {
|
|
1574
|
+
body.tool_choice = { type: "any" };
|
|
1575
|
+
} else if (params.toolChoice && typeof params.toolChoice === "object") {
|
|
1576
|
+
body.tool_choice = { name: params.toolChoice.name, type: "tool" };
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
if (params.stopSequences && params.stopSequences.length > 0) {
|
|
1580
|
+
body.stop_sequences = params.stopSequences;
|
|
1581
|
+
}
|
|
1582
|
+
const mode = params.reasoning ? anthropicReasoningMode(params.model) : "none";
|
|
1583
|
+
const thinkingActive = mode !== "none";
|
|
1584
|
+
if (!thinkingActive && anthropicSupportsSampling(params.model)) {
|
|
1585
|
+
if (typeof params.temperature === "number") {
|
|
1586
|
+
body.temperature = params.temperature;
|
|
1587
|
+
}
|
|
1588
|
+
if (typeof params.topP === "number")
|
|
1589
|
+
body.top_p = params.topP;
|
|
1590
|
+
}
|
|
1591
|
+
if (mode === "effort" || mode === "adaptive") {
|
|
1592
|
+
body.thinking = { type: "adaptive" };
|
|
1593
|
+
if (mode === "effort" && params.reasoning) {
|
|
1594
|
+
const effort = anthropicEffortValue(params.model, params.reasoning);
|
|
1595
|
+
if (effort)
|
|
1596
|
+
body.output_config = { effort };
|
|
1597
|
+
}
|
|
1598
|
+
} else if (mode === "legacy" && params.reasoning) {
|
|
1599
|
+
const budget = resolveBudgetTokens(params.reasoning);
|
|
1600
|
+
if (budget) {
|
|
1601
|
+
body.thinking = { budget_tokens: budget, type: "enabled" };
|
|
1602
|
+
body.max_tokens = Math.max(max, budget + max);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
return body;
|
|
1606
|
+
};
|
|
1607
|
+
var classifyLine = (line) => {
|
|
1608
|
+
if (line.startsWith("event: ")) {
|
|
1609
|
+
return {
|
|
1610
|
+
field: "event",
|
|
1611
|
+
value: line.slice(EVENT_PREFIX_LENGTH2)
|
|
1612
|
+
};
|
|
1613
|
+
}
|
|
1614
|
+
if (line.startsWith("data: ")) {
|
|
1615
|
+
return {
|
|
1616
|
+
field: "data",
|
|
1617
|
+
value: line.slice(DATA_PREFIX_LENGTH2)
|
|
1618
|
+
};
|
|
1619
|
+
}
|
|
1620
|
+
return;
|
|
1621
|
+
};
|
|
1622
|
+
var applyClassified = (acc, classified) => {
|
|
1623
|
+
if (!classified) {
|
|
1624
|
+
return acc;
|
|
1625
|
+
}
|
|
1626
|
+
if (classified.field === "event") {
|
|
1627
|
+
return { eventData: acc.eventData, eventType: classified.value };
|
|
1628
|
+
}
|
|
1629
|
+
return { eventData: classified.value, eventType: acc.eventType };
|
|
1630
|
+
};
|
|
1631
|
+
var parseEventLines = (event) => event.split(`
|
|
1632
|
+
`).reduce((acc, line) => applyClassified(acc, classifyLine(line)), {
|
|
1633
|
+
eventData: "",
|
|
1634
|
+
eventType: ""
|
|
1635
|
+
});
|
|
1636
|
+
var safeParse = (text) => {
|
|
1637
|
+
try {
|
|
1638
|
+
const result = JSON.parse(text);
|
|
1639
|
+
return result;
|
|
1640
|
+
} catch {
|
|
1641
|
+
return;
|
|
1642
|
+
}
|
|
1643
|
+
};
|
|
1644
|
+
var tryParseJson = (text) => {
|
|
1645
|
+
const result = safeParse(text);
|
|
1646
|
+
if (isRecord3(result)) {
|
|
1647
|
+
return result;
|
|
1648
|
+
}
|
|
1649
|
+
return;
|
|
1650
|
+
};
|
|
1651
|
+
var getRecord = (obj, key) => {
|
|
1652
|
+
const val = obj[key];
|
|
1653
|
+
if (isRecord3(val)) {
|
|
1654
|
+
return val;
|
|
1655
|
+
}
|
|
1656
|
+
return;
|
|
1657
|
+
};
|
|
1658
|
+
var getString = (obj, key) => {
|
|
1659
|
+
const val = obj[key];
|
|
1660
|
+
if (typeof val === "string") {
|
|
1661
|
+
return val;
|
|
1662
|
+
}
|
|
1663
|
+
return "";
|
|
1664
|
+
};
|
|
1665
|
+
var getNumber = (obj, key) => {
|
|
1666
|
+
const val = obj[key];
|
|
1667
|
+
if (typeof val === "number") {
|
|
1668
|
+
return val;
|
|
1669
|
+
}
|
|
1670
|
+
return 0;
|
|
1671
|
+
};
|
|
1672
|
+
var handleContentBlockStart = (parsed, state) => {
|
|
1673
|
+
const block = getRecord(parsed, "content_block");
|
|
1674
|
+
if (block && block.type === "tool_use") {
|
|
1675
|
+
state.currentToolId = getString(block, "id");
|
|
1676
|
+
state.currentToolName = getString(block, "name");
|
|
1677
|
+
state.toolInputJson = "";
|
|
1678
|
+
state.isThinkingBlock = false;
|
|
1679
|
+
state.currentProviderBlock = undefined;
|
|
1680
|
+
} else if (block && block.type === "thinking") {
|
|
1681
|
+
state.isThinkingBlock = true;
|
|
1682
|
+
state.thinkingSignature = "";
|
|
1683
|
+
state.currentProviderBlock = undefined;
|
|
1684
|
+
} else {
|
|
1685
|
+
state.isThinkingBlock = false;
|
|
1686
|
+
state.currentProviderBlock = block && block.type !== "text" ? { ...block } : undefined;
|
|
1687
|
+
state.providerBlockInputJson = "";
|
|
1688
|
+
}
|
|
1689
|
+
};
|
|
1690
|
+
var handleContentBlockDelta = (parsed, state) => {
|
|
1691
|
+
const delta = getRecord(parsed, "delta");
|
|
1692
|
+
if (!delta) {
|
|
1693
|
+
return;
|
|
1694
|
+
}
|
|
1695
|
+
if (delta.type === "thinking_delta") {
|
|
1696
|
+
return {
|
|
1697
|
+
content: getString(delta, "thinking"),
|
|
1698
|
+
type: "thinking"
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
if (delta.type === "text_delta") {
|
|
1702
|
+
return {
|
|
1703
|
+
content: getString(delta, "text"),
|
|
1704
|
+
type: "text"
|
|
1705
|
+
};
|
|
1706
|
+
}
|
|
1707
|
+
if (delta.type === "input_json_delta") {
|
|
1708
|
+
if (state.currentProviderBlock) {
|
|
1709
|
+
state.providerBlockInputJson += getString(delta, "partial_json");
|
|
1710
|
+
} else {
|
|
1711
|
+
state.toolInputJson += getString(delta, "partial_json");
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
if (delta.type === "signature_delta") {
|
|
1715
|
+
state.thinkingSignature += getString(delta, "signature");
|
|
1716
|
+
}
|
|
1717
|
+
return;
|
|
1718
|
+
};
|
|
1719
|
+
var handleContentBlockStop = (state) => {
|
|
1720
|
+
if (state.isThinkingBlock && state.thinkingSignature) {
|
|
1721
|
+
state.isThinkingBlock = false;
|
|
1722
|
+
const signature = state.thinkingSignature;
|
|
1723
|
+
state.thinkingSignature = "";
|
|
1724
|
+
return {
|
|
1725
|
+
content: "",
|
|
1726
|
+
signature,
|
|
1727
|
+
type: "thinking"
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1730
|
+
if (state.currentProviderBlock) {
|
|
1731
|
+
const data = { ...state.currentProviderBlock };
|
|
1732
|
+
if (state.providerBlockInputJson) {
|
|
1733
|
+
data.input = tryParseJson(state.providerBlockInputJson) ?? state.providerBlockInputJson;
|
|
1734
|
+
}
|
|
1735
|
+
state.currentProviderBlock = undefined;
|
|
1736
|
+
state.providerBlockInputJson = "";
|
|
1737
|
+
return {
|
|
1738
|
+
data,
|
|
1739
|
+
provider: state.providerName,
|
|
1740
|
+
type: "provider_event"
|
|
1741
|
+
};
|
|
1742
|
+
}
|
|
1743
|
+
if (!state.currentToolId) {
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
|
+
const input = tryParseJson(state.toolInputJson) ?? state.toolInputJson;
|
|
1747
|
+
const chunk = {
|
|
1748
|
+
id: state.currentToolId,
|
|
1749
|
+
input,
|
|
1750
|
+
name: state.currentToolName,
|
|
1751
|
+
type: "tool_use"
|
|
1752
|
+
};
|
|
1753
|
+
state.currentToolId = "";
|
|
1754
|
+
state.currentToolName = "";
|
|
1755
|
+
state.toolInputJson = "";
|
|
1756
|
+
return chunk;
|
|
1757
|
+
};
|
|
1758
|
+
var extractUsage3 = (usageRecord, existingUsage) => {
|
|
1759
|
+
if (!usageRecord) {
|
|
1760
|
+
return existingUsage;
|
|
1761
|
+
}
|
|
1762
|
+
const normalized = {
|
|
1763
|
+
cacheReadInputTokens: getNumber(usageRecord, "cache_read_input_tokens") || existingUsage?.cacheReadInputTokens || 0,
|
|
1764
|
+
cacheWriteInputTokens: getNumber(usageRecord, "cache_creation_input_tokens") || existingUsage?.cacheWriteInputTokens || 0,
|
|
1765
|
+
inputTokens: getNumber(usageRecord, "input_tokens") || existingUsage?.inputTokens || 0,
|
|
1766
|
+
outputTokens: getNumber(usageRecord, "output_tokens") || existingUsage?.outputTokens || 0,
|
|
1767
|
+
costCredits: getNumber(usageRecord, "cost") || existingUsage?.costCredits,
|
|
1768
|
+
reasoningTokens: getNumber(usageRecord, "reasoning_tokens") || existingUsage?.reasoningTokens,
|
|
1769
|
+
upstreamInferenceCostCredits: getNumber(getRecord(usageRecord, "cost_details") ?? {}, "upstream_inference_cost") || existingUsage?.upstreamInferenceCostCredits
|
|
1770
|
+
};
|
|
1771
|
+
const serverToolUse = getRecord(usageRecord, "server_tool_use");
|
|
1772
|
+
if (serverToolUse) {
|
|
1773
|
+
normalized.serverToolUse = Object.fromEntries(Object.entries(serverToolUse).filter((entry) => typeof entry[1] === "number"));
|
|
1774
|
+
}
|
|
1775
|
+
return normalized;
|
|
1776
|
+
};
|
|
1777
|
+
var mergeMetadata = (source, state) => {
|
|
1778
|
+
const providerMetadata = getRecord(source, "openrouter_metadata");
|
|
1779
|
+
const generationId = getString(source, "id") || undefined;
|
|
1780
|
+
const model = getString(source, "model") || undefined;
|
|
1781
|
+
const provider = getString(source, "provider") || undefined;
|
|
1782
|
+
const serviceTier = getString(source, "service_tier") || undefined;
|
|
1783
|
+
if (!providerMetadata && !generationId && !model && !provider && !serviceTier)
|
|
1784
|
+
return;
|
|
1785
|
+
state.metadata = {
|
|
1786
|
+
...state.metadata,
|
|
1787
|
+
generationId: generationId ?? state.metadata?.generationId,
|
|
1788
|
+
model: model ?? state.metadata?.model,
|
|
1789
|
+
provider: provider ?? state.metadata?.provider,
|
|
1790
|
+
providerMetadata: {
|
|
1791
|
+
...state.metadata?.providerMetadata,
|
|
1792
|
+
...providerMetadata
|
|
1793
|
+
},
|
|
1794
|
+
serviceTier: serviceTier ?? state.metadata?.serviceTier
|
|
1795
|
+
};
|
|
1796
|
+
};
|
|
1797
|
+
var handleMessageDelta = (parsed, state) => {
|
|
1798
|
+
const deltaUsage = getRecord(parsed, "usage");
|
|
1799
|
+
state.usage = extractUsage3(deltaUsage, state.usage);
|
|
1800
|
+
const delta = getRecord(parsed, "delta");
|
|
1801
|
+
const stopReason = delta ? getString(delta, "stop_reason") : "";
|
|
1802
|
+
if (stopReason)
|
|
1803
|
+
state.stopReason = stopReason;
|
|
1804
|
+
};
|
|
1805
|
+
var handleMessageStart = (parsed, state) => {
|
|
1806
|
+
const message = getRecord(parsed, "message");
|
|
1807
|
+
if (!message) {
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
const startUsage = getRecord(message, "usage");
|
|
1811
|
+
state.usage = extractUsage3(startUsage, state.usage);
|
|
1812
|
+
mergeMetadata(message, state);
|
|
1813
|
+
};
|
|
1814
|
+
var handleError = (parsed, state) => {
|
|
1815
|
+
const error = getRecord(parsed, "error");
|
|
1816
|
+
const errorMessage = error ? getString(error, "message") : "";
|
|
1817
|
+
const nativeErrorType = error ? getString(error, "type") : "";
|
|
1818
|
+
const errorType = error ? getString(error, "error_type") || nativeErrorType : "";
|
|
1819
|
+
const retryable = errorType === "provider_overloaded" || errorType === "rate_limit_exceeded" || errorType === "provider_unavailable" || errorType === "server" || nativeErrorType === "overloaded_error" || nativeErrorType === "rate_limit_error" || nativeErrorType === "api_error";
|
|
1820
|
+
throw new ProviderError({
|
|
1821
|
+
message: errorMessage || "Anthropic API error",
|
|
1822
|
+
metadata: error,
|
|
1823
|
+
provider: state.providerName,
|
|
1824
|
+
retryable,
|
|
1825
|
+
type: errorType || null
|
|
1826
|
+
});
|
|
1827
|
+
};
|
|
1828
|
+
var processEvent = (eventType, parsed, state) => {
|
|
1829
|
+
switch (eventType) {
|
|
1830
|
+
case "content_block_start": {
|
|
1831
|
+
handleContentBlockStart(parsed, state);
|
|
1832
|
+
return;
|
|
1833
|
+
}
|
|
1834
|
+
case "content_block_delta": {
|
|
1835
|
+
return handleContentBlockDelta(parsed, state);
|
|
1836
|
+
}
|
|
1837
|
+
case "content_block_stop": {
|
|
1838
|
+
return handleContentBlockStop(state);
|
|
1839
|
+
}
|
|
1840
|
+
case "message_delta": {
|
|
1841
|
+
handleMessageDelta(parsed, state);
|
|
1842
|
+
mergeMetadata(parsed, state);
|
|
1843
|
+
return;
|
|
1844
|
+
}
|
|
1845
|
+
case "message_start": {
|
|
1846
|
+
handleMessageStart(parsed, state);
|
|
1847
|
+
return;
|
|
1848
|
+
}
|
|
1849
|
+
case "message_stop": {
|
|
1850
|
+
mergeMetadata(parsed, state);
|
|
1851
|
+
return {
|
|
1852
|
+
stopReason: state.stopReason,
|
|
1853
|
+
metadata: state.metadata,
|
|
1854
|
+
type: "done",
|
|
1855
|
+
usage: state.usage
|
|
1856
|
+
};
|
|
1857
|
+
}
|
|
1858
|
+
case "error": {
|
|
1859
|
+
handleError(parsed, state);
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1862
|
+
default: {
|
|
1863
|
+
return;
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
};
|
|
1867
|
+
var processSingleEvent = (event, state) => {
|
|
1868
|
+
if (!event.trim()) {
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1871
|
+
const { eventData, eventType } = parseEventLines(event);
|
|
1872
|
+
if (!eventData) {
|
|
1873
|
+
return;
|
|
1874
|
+
}
|
|
1875
|
+
const parsed = tryParseJson(eventData);
|
|
1876
|
+
if (!parsed) {
|
|
1877
|
+
return;
|
|
1878
|
+
}
|
|
1879
|
+
return processEvent(eventType, parsed, state);
|
|
1880
|
+
};
|
|
1881
|
+
var collectChunk = (event, state) => {
|
|
1882
|
+
const chunk = processSingleEvent(event, state);
|
|
1883
|
+
return chunk ? [chunk] : [];
|
|
1884
|
+
};
|
|
1885
|
+
var processBufferedEvents = (eventsText, state) => {
|
|
1886
|
+
const events = eventsText.split(`
|
|
1887
|
+
|
|
1888
|
+
`);
|
|
1889
|
+
state.buffer = events.pop() ?? "";
|
|
1890
|
+
return events.flatMap((event) => collectChunk(event, state));
|
|
1891
|
+
};
|
|
1892
|
+
var readNextChunks = async (reader, decoder, state, signal) => {
|
|
1893
|
+
if (signal?.aborted) {
|
|
1894
|
+
return { chunks: EMPTY_CHUNKS, done: true };
|
|
1895
|
+
}
|
|
1896
|
+
const { done, value } = await reader.read();
|
|
1897
|
+
if (done) {
|
|
1898
|
+
return { chunks: EMPTY_CHUNKS, done: true };
|
|
1899
|
+
}
|
|
1900
|
+
const rawText = state.buffer + decoder.decode(value, { stream: true });
|
|
1901
|
+
const chunks = processBufferedEvents(rawText, state);
|
|
1902
|
+
return { chunks, done: false };
|
|
1903
|
+
};
|
|
1904
|
+
var findDoneChunk = (chunks) => chunks.findIndex((c) => c.type === "done");
|
|
1905
|
+
var sseStreamLoop = async (reader, decoder, state, signal) => {
|
|
1906
|
+
const result = await readNextChunks(reader, decoder, state, signal);
|
|
1907
|
+
if (result.done) {
|
|
1908
|
+
return { chunks: result.chunks, finished: true };
|
|
1909
|
+
}
|
|
1910
|
+
const doneIdx = findDoneChunk(result.chunks);
|
|
1911
|
+
if (doneIdx >= 0) {
|
|
1912
|
+
return { chunks: result.chunks.slice(0, doneIdx + 1), finished: true };
|
|
1913
|
+
}
|
|
1914
|
+
return { chunks: result.chunks, finished: false };
|
|
1915
|
+
};
|
|
1916
|
+
async function* streamChunks(reader, decoder, state, signal) {
|
|
1917
|
+
let finished = false;
|
|
1918
|
+
while (!finished) {
|
|
1919
|
+
const result = await sseStreamLoop(reader, decoder, state, signal);
|
|
1920
|
+
({ finished } = result);
|
|
1921
|
+
yield* result.chunks;
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
async function* parseSSEStream3(body, providerName, signal) {
|
|
1925
|
+
const reader = body.getReader();
|
|
1926
|
+
const decoder = new TextDecoder;
|
|
1927
|
+
const state = {
|
|
1928
|
+
buffer: "",
|
|
1929
|
+
currentToolId: "",
|
|
1930
|
+
currentToolName: "",
|
|
1931
|
+
isThinkingBlock: false,
|
|
1932
|
+
stopReason: "",
|
|
1933
|
+
thinkingSignature: "",
|
|
1934
|
+
toolInputJson: "",
|
|
1935
|
+
usage: undefined,
|
|
1936
|
+
providerName,
|
|
1937
|
+
providerBlockInputJson: ""
|
|
1938
|
+
};
|
|
1939
|
+
try {
|
|
1940
|
+
yield* streamChunks(reader, decoder, state, signal);
|
|
1941
|
+
} finally {
|
|
1942
|
+
reader.releaseLock();
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
var fetchAndStream = async function* (baseUrl, config2, params, configuredMax, promptCaching, providerName) {
|
|
1946
|
+
const builtBody = buildRequestBody3(params, configuredMax, promptCaching);
|
|
1947
|
+
const body = config2.transformRequestBody ? config2.transformRequestBody(builtBody, params) : builtBody;
|
|
1948
|
+
const target = `${baseUrl}/v1/messages`;
|
|
1949
|
+
const fetchImpl = config2.fetch ?? fetch;
|
|
1950
|
+
const token = config2.tokenSource ? await Promise.resolve(config2.tokenSource()) : config2.apiKey;
|
|
1951
|
+
const suppliedHeaders = typeof config2.headers === "function" ? await config2.headers(params) : config2.headers ?? {};
|
|
1952
|
+
const requestHeaders = new Headers(suppliedHeaders);
|
|
1953
|
+
requestHeaders.set("Content-Type", "application/json");
|
|
1954
|
+
if (config2.authStyle === "bearer") {
|
|
1955
|
+
requestHeaders.set("Authorization", `Bearer ${token}`);
|
|
1956
|
+
} else {
|
|
1957
|
+
requestHeaders.set("anthropic-version", API_VERSION);
|
|
1958
|
+
requestHeaders.set("x-api-key", token);
|
|
1959
|
+
}
|
|
1960
|
+
const response = await fetchImpl(target, {
|
|
1961
|
+
...h2IfHttps3(target),
|
|
1962
|
+
body: JSON.stringify(body),
|
|
1963
|
+
headers: requestHeaders,
|
|
1964
|
+
method: "POST",
|
|
1965
|
+
signal: params.signal
|
|
1966
|
+
});
|
|
1967
|
+
if (!response.ok) {
|
|
1968
|
+
const errorText = await response.text();
|
|
1969
|
+
throw ProviderError.fromResponse(providerName, response.status, errorText);
|
|
1970
|
+
}
|
|
1971
|
+
if (!response.body) {
|
|
1972
|
+
throw new ProviderError({
|
|
1973
|
+
message: `${providerName} Messages API returned no response body`,
|
|
1974
|
+
provider: providerName,
|
|
1975
|
+
retryable: true
|
|
1976
|
+
});
|
|
1977
|
+
}
|
|
1978
|
+
yield* parseSSEStream3(response.body, providerName, params.signal);
|
|
1979
|
+
};
|
|
1980
|
+
var anthropic = (config2) => {
|
|
1981
|
+
if (!config2.apiKey && !config2.tokenSource)
|
|
1982
|
+
throw new Error("anthropic() requires either apiKey or tokenSource");
|
|
1983
|
+
const baseUrl = config2.baseUrl ?? DEFAULT_BASE_URL3;
|
|
1984
|
+
const configuredMax = config2.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
1985
|
+
const promptCaching = config2.promptCaching ?? true;
|
|
1986
|
+
const providerName = config2.providerName ?? "anthropic";
|
|
1987
|
+
return instrumentAIProvider({
|
|
1988
|
+
stream: (params) => fetchAndStream(baseUrl, config2, params, configuredMax, promptCaching, providerName)
|
|
1989
|
+
}, providerName);
|
|
1990
|
+
};
|
|
1991
|
+
|
|
1327
1992
|
// src/ai/providers/openrouterClient.ts
|
|
1328
|
-
var
|
|
1993
|
+
var DEFAULT_BASE_URL4 = "https://openrouter.ai/api/v1";
|
|
1329
1994
|
var withoutLatestPrefix = (model) => model.startsWith("~") ? model.slice(1) : model;
|
|
1330
1995
|
var openRouterModelMatchesRule = (model, rule) => {
|
|
1331
1996
|
const normalizedModel = withoutLatestPrefix(model);
|
|
@@ -1351,10 +2016,89 @@ var withQuery = (url, query) => {
|
|
|
1351
2016
|
}
|
|
1352
2017
|
return result.toString();
|
|
1353
2018
|
};
|
|
2019
|
+
var parseImageSSE = async function* (response) {
|
|
2020
|
+
if (!response.body)
|
|
2021
|
+
throw new Error("OpenRouter image stream has no body");
|
|
2022
|
+
const reader = response.body.getReader();
|
|
2023
|
+
const decoder = new TextDecoder;
|
|
2024
|
+
let buffer = "";
|
|
2025
|
+
try {
|
|
2026
|
+
for (;; ) {
|
|
2027
|
+
const result = await reader.read();
|
|
2028
|
+
buffer += decoder.decode(result.value, { stream: !result.done });
|
|
2029
|
+
const lines = buffer.split(`
|
|
2030
|
+
`);
|
|
2031
|
+
buffer = lines.pop() ?? "";
|
|
2032
|
+
for (const line of lines) {
|
|
2033
|
+
if (!line.startsWith("data: "))
|
|
2034
|
+
continue;
|
|
2035
|
+
const data = line.slice(6);
|
|
2036
|
+
if (data === "[DONE]")
|
|
2037
|
+
return;
|
|
2038
|
+
try {
|
|
2039
|
+
const parsed = JSON.parse(data);
|
|
2040
|
+
if (parsed && typeof parsed === "object" && "type" in parsed)
|
|
2041
|
+
yield parsed;
|
|
2042
|
+
} catch {}
|
|
2043
|
+
}
|
|
2044
|
+
if (result.done)
|
|
2045
|
+
break;
|
|
2046
|
+
}
|
|
2047
|
+
if (buffer.startsWith("data: ")) {
|
|
2048
|
+
const parsed = JSON.parse(buffer.slice(6));
|
|
2049
|
+
if (parsed && typeof parsed === "object" && "type" in parsed)
|
|
2050
|
+
yield parsed;
|
|
2051
|
+
}
|
|
2052
|
+
} finally {
|
|
2053
|
+
reader.releaseLock();
|
|
2054
|
+
}
|
|
2055
|
+
};
|
|
2056
|
+
var toBytes = (value) => typeof value === "string" ? new TextEncoder().encode(value) : value;
|
|
2057
|
+
var hexToBytes = (hex) => {
|
|
2058
|
+
if (!/^[0-9a-f]+$/iu.test(hex) || hex.length % 2 !== 0)
|
|
2059
|
+
return;
|
|
2060
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
2061
|
+
for (let index = 0;index < bytes.length; index += 1) {
|
|
2062
|
+
bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);
|
|
2063
|
+
}
|
|
2064
|
+
return bytes;
|
|
2065
|
+
};
|
|
2066
|
+
var constantTimeEqual = (left, right) => {
|
|
2067
|
+
if (left.length !== right.length)
|
|
2068
|
+
return false;
|
|
2069
|
+
let mismatch = 0;
|
|
2070
|
+
for (let index = 0;index < left.length; index += 1)
|
|
2071
|
+
mismatch |= (left[index] ?? 0) ^ (right[index] ?? 0);
|
|
2072
|
+
return mismatch === 0;
|
|
2073
|
+
};
|
|
2074
|
+
var verifyOpenRouterWebhookSignature = async (options) => {
|
|
2075
|
+
const fields = new Map(options.header.split(",").map((part) => {
|
|
2076
|
+
const [key2, ...rest] = part.trim().split("=");
|
|
2077
|
+
return [key2, rest.join("=")];
|
|
2078
|
+
}));
|
|
2079
|
+
const timestamp = fields.get("t");
|
|
2080
|
+
const supplied = fields.get("v1");
|
|
2081
|
+
if (!timestamp || !supplied)
|
|
2082
|
+
return false;
|
|
2083
|
+
const timestampNumber = Number(timestamp);
|
|
2084
|
+
const now = options.nowSeconds ?? Math.floor(Date.now() / 1000);
|
|
2085
|
+
const tolerance = options.toleranceSeconds ?? 300;
|
|
2086
|
+
if (!Number.isFinite(timestampNumber) || Math.abs(now - timestampNumber) > tolerance)
|
|
2087
|
+
return false;
|
|
2088
|
+
const key = await crypto.subtle.importKey("raw", Uint8Array.from(toBytes(options.secret)).buffer, { hash: "SHA-256", name: "HMAC" }, false, ["sign"]);
|
|
2089
|
+
const prefix = new TextEncoder().encode(`${timestamp},`);
|
|
2090
|
+
const body = toBytes(options.body);
|
|
2091
|
+
const payload = new Uint8Array(prefix.length + body.length);
|
|
2092
|
+
payload.set(prefix);
|
|
2093
|
+
payload.set(body, prefix.length);
|
|
2094
|
+
const expected = new Uint8Array(await crypto.subtle.sign("HMAC", key, payload.buffer));
|
|
2095
|
+
const suppliedBytes = hexToBytes(supplied);
|
|
2096
|
+
return suppliedBytes ? constantTimeEqual(expected, suppliedBytes) : false;
|
|
2097
|
+
};
|
|
1354
2098
|
var createOpenRouterClient = (config2) => {
|
|
1355
2099
|
if (!config2.apiKey && !config2.tokenSource)
|
|
1356
2100
|
throw new Error("createOpenRouterClient() requires either apiKey or tokenSource");
|
|
1357
|
-
const baseUrl = (config2.baseUrl ??
|
|
2101
|
+
const baseUrl = (config2.baseUrl ?? DEFAULT_BASE_URL4).replace(/\/$/, "");
|
|
1358
2102
|
const fetchImpl = config2.fetch ?? globalThis.fetch;
|
|
1359
2103
|
const allowedModels = config2.allowedModels ? [...config2.allowedModels] : undefined;
|
|
1360
2104
|
const requestRaw = async (path, options = {}) => {
|
|
@@ -1414,6 +2158,13 @@ var createOpenRouterClient = (config2) => {
|
|
|
1414
2158
|
method: "POST"
|
|
1415
2159
|
});
|
|
1416
2160
|
},
|
|
2161
|
+
deleteFile: (id, workspaceId) => request(`/files/${encodeURIComponent(id)}`, { method: "DELETE", query: { workspace_id: workspaceId } }),
|
|
2162
|
+
downloadFile: (id, workspaceId) => requestRaw(`/files/${encodeURIComponent(id)}/content`, {
|
|
2163
|
+
query: { workspace_id: workspaceId }
|
|
2164
|
+
}),
|
|
2165
|
+
downloadVideo: (id, index = 0) => requestRaw(`/videos/${encodeURIComponent(id)}/content`, {
|
|
2166
|
+
query: { index }
|
|
2167
|
+
}),
|
|
1417
2168
|
generateVideo: (body) => {
|
|
1418
2169
|
assertAllowedModel(body.model, allowedModels);
|
|
1419
2170
|
return request("/videos", {
|
|
@@ -1424,6 +2175,9 @@ var createOpenRouterClient = (config2) => {
|
|
|
1424
2175
|
getBatch: (id) => request(`/batches/${encodeURIComponent(id)}`),
|
|
1425
2176
|
getCredits: () => request("/credits"),
|
|
1426
2177
|
getCurrentKey: () => request("/key"),
|
|
2178
|
+
getFile: (id, workspaceId) => request(`/files/${encodeURIComponent(id)}`, {
|
|
2179
|
+
query: { workspace_id: workspaceId }
|
|
2180
|
+
}),
|
|
1427
2181
|
getGeneration: (id) => request("/generation", {
|
|
1428
2182
|
query: { id }
|
|
1429
2183
|
}),
|
|
@@ -1431,15 +2185,47 @@ var createOpenRouterClient = (config2) => {
|
|
|
1431
2185
|
assertAllowedModel(model, allowedModels);
|
|
1432
2186
|
return request(`/models/${encodeModelPath(model)}/endpoints`);
|
|
1433
2187
|
},
|
|
2188
|
+
getModel: (model) => {
|
|
2189
|
+
assertAllowedModel(model, allowedModels);
|
|
2190
|
+
return request(`/model/${encodeModelPath(model)}`);
|
|
2191
|
+
},
|
|
2192
|
+
getImageModelEndpoints: (model) => {
|
|
2193
|
+
assertAllowedModel(model, allowedModels);
|
|
2194
|
+
return request(`/images/models/${encodeModelPath(model)}/endpoints`);
|
|
2195
|
+
},
|
|
1434
2196
|
getVideo: (id) => request(`/videos/${encodeURIComponent(id)}`),
|
|
1435
2197
|
listImageModels: async () => filterModelList(await request("/images/models")),
|
|
2198
|
+
listFiles: (query) => request("/files", { query }),
|
|
1436
2199
|
listModels,
|
|
2200
|
+
listUserModels: async () => filterModelList(await request("/models/user")),
|
|
2201
|
+
listZdrEndpoints: async () => {
|
|
2202
|
+
const result = await request("/endpoints/zdr");
|
|
2203
|
+
if (!allowedModels)
|
|
2204
|
+
return result;
|
|
2205
|
+
return {
|
|
2206
|
+
...result,
|
|
2207
|
+
data: result.data.filter((endpoint) => allowedModels.some((rule) => openRouterModelMatchesRule(endpoint.model_id, rule)))
|
|
2208
|
+
};
|
|
2209
|
+
},
|
|
2210
|
+
countModels: (outputModalities) => request("/models/count", {
|
|
2211
|
+
query: { output_modalities: outputModalities }
|
|
2212
|
+
}),
|
|
1437
2213
|
listPresets: (offset = 0, limit = 100) => request("/presets", { query: { limit, offset } }),
|
|
2214
|
+
listPresetVersions: (slug, offset = 0, limit = 100) => request(`/presets/${encodeURIComponent(slug)}/versions`, { query: { limit, offset } }),
|
|
1438
2215
|
listProviders: () => request("/providers"),
|
|
1439
2216
|
listRerankModels: async () => filterModelList(await request("/rerank/models")),
|
|
1440
2217
|
listVideoModels: async () => filterModelList(await request("/videos/models")),
|
|
1441
2218
|
request,
|
|
1442
2219
|
requestRaw,
|
|
2220
|
+
streamImage: async function* (body, options = {}) {
|
|
2221
|
+
assertAllowedModel(body.model, allowedModels);
|
|
2222
|
+
const response = await requestRaw("/images", {
|
|
2223
|
+
...options,
|
|
2224
|
+
body: { ...body, stream: true },
|
|
2225
|
+
method: "POST"
|
|
2226
|
+
});
|
|
2227
|
+
yield* parseImageSSE(response);
|
|
2228
|
+
},
|
|
1443
2229
|
respond: (body) => {
|
|
1444
2230
|
assertAllowedModel(body.model, allowedModels);
|
|
1445
2231
|
return body.stream ? requestRaw("/responses", { body, method: "POST" }) : request("/responses", {
|
|
@@ -1471,12 +2257,24 @@ var createOpenRouterClient = (config2) => {
|
|
|
1471
2257
|
body,
|
|
1472
2258
|
method: "POST"
|
|
1473
2259
|
});
|
|
2260
|
+
},
|
|
2261
|
+
uploadFile: (file, options = {}) => {
|
|
2262
|
+
const body = new FormData;
|
|
2263
|
+
if (options.filename)
|
|
2264
|
+
body.append("file", file, options.filename);
|
|
2265
|
+
else
|
|
2266
|
+
body.append("file", file);
|
|
2267
|
+
return request("/files", {
|
|
2268
|
+
body,
|
|
2269
|
+
method: "POST",
|
|
2270
|
+
query: { workspace_id: options.workspaceId }
|
|
2271
|
+
});
|
|
1474
2272
|
}
|
|
1475
2273
|
};
|
|
1476
2274
|
};
|
|
1477
2275
|
|
|
1478
2276
|
// src/ai/providers/openrouter.ts
|
|
1479
|
-
var
|
|
2277
|
+
var DEFAULT_BASE_URL5 = "https://openrouter.ai/api";
|
|
1480
2278
|
var MAX_APP_CATEGORIES = 2;
|
|
1481
2279
|
var withoutLatestPrefix2 = (model) => model.startsWith("~") ? model.slice(1) : model;
|
|
1482
2280
|
var modelForOpenAICapabilities = (model) => {
|
|
@@ -1607,7 +2405,7 @@ var assertAllowedPreset = (preset, allowedPresets) => {
|
|
|
1607
2405
|
var assertIndirectModels = (value, allowedModels, key = "") => {
|
|
1608
2406
|
if (key === "model" && typeof value === "string")
|
|
1609
2407
|
assertAllowedModel2(value, allowedModels);
|
|
1610
|
-
if (key === "models" && Array.isArray(value)) {
|
|
2408
|
+
if ((key === "models" || key === "analysis_models") && Array.isArray(value)) {
|
|
1611
2409
|
for (const model of value) {
|
|
1612
2410
|
if (typeof model === "string")
|
|
1613
2411
|
assertAllowedModel2(model, allowedModels);
|
|
@@ -1638,6 +2436,7 @@ var assertRequestOptions = (options, allowedModels, allowedPresets, allowedProvi
|
|
|
1638
2436
|
assertAllowedModel2(model, allowedModels);
|
|
1639
2437
|
}
|
|
1640
2438
|
assertIndirectModels(options.serverTools, allowedModels);
|
|
2439
|
+
assertIndirectModels(options.messagesTools, allowedModels);
|
|
1641
2440
|
assertIndirectModels(options.plugins, allowedModels);
|
|
1642
2441
|
if (options.extraBody) {
|
|
1643
2442
|
const unsafe = Object.keys(options.extraBody).find((key) => SECURITY_SENSITIVE_EXTRA_BODY_FIELDS.has(key));
|
|
@@ -1656,17 +2455,41 @@ var snapshotPolicy = (config2) => ({
|
|
|
1656
2455
|
allowedModels: config2.allowedModels ? [...config2.allowedModels] : undefined,
|
|
1657
2456
|
allowedPresets: config2.allowedPresets ? [...config2.allowedPresets] : undefined
|
|
1658
2457
|
});
|
|
1659
|
-
var transformOpenRouterRequest = (config2, allowedModels, allowedPresets, body, params) => {
|
|
2458
|
+
var transformOpenRouterRequest = (config2, allowedModels, allowedPresets, body, params, skin = "openai") => {
|
|
1660
2459
|
const options = requestOptionsFor(params, config2.requestOptions);
|
|
1661
2460
|
assertRequestOptions(options, allowedModels, allowedPresets, config2.allowedProviders);
|
|
1662
2461
|
const transformed = { ...body, ...options.extraBody };
|
|
1663
|
-
if (
|
|
1664
|
-
transformed.
|
|
1665
|
-
|
|
1666
|
-
}
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
2462
|
+
if (options.audioOutput) {
|
|
2463
|
+
transformed.audio = options.audioOutput;
|
|
2464
|
+
transformed.modalities = ["text", "audio"];
|
|
2465
|
+
}
|
|
2466
|
+
if (skin === "openai") {
|
|
2467
|
+
const requestedReasoning = {};
|
|
2468
|
+
if (params.reasoning?.budgetTokens !== undefined) {
|
|
2469
|
+
requestedReasoning.max_tokens = params.reasoning.budgetTokens;
|
|
2470
|
+
delete transformed.reasoning_effort;
|
|
2471
|
+
} else if (params.reasoning?.effort) {
|
|
2472
|
+
requestedReasoning.effort = params.reasoning.effort;
|
|
2473
|
+
delete transformed.reasoning_effort;
|
|
2474
|
+
}
|
|
2475
|
+
if (options.reasoning) {
|
|
2476
|
+
Object.assign(requestedReasoning, options.reasoning);
|
|
2477
|
+
if (options.reasoning.maxTokens !== undefined) {
|
|
2478
|
+
requestedReasoning.max_tokens = options.reasoning.maxTokens;
|
|
2479
|
+
delete requestedReasoning.maxTokens;
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
if (Object.keys(requestedReasoning).length > 0)
|
|
2483
|
+
transformed.reasoning = requestedReasoning;
|
|
2484
|
+
}
|
|
2485
|
+
const automaticCacheControl = params.promptCaching === true || params.cacheSystemPrompt === true ? { type: "ephemeral" } : undefined;
|
|
2486
|
+
const cacheControl = options.cacheControl ?? automaticCacheControl;
|
|
2487
|
+
if (cacheControl)
|
|
2488
|
+
transformed.cache_control = cacheControl;
|
|
2489
|
+
if (options.promptCacheKey)
|
|
2490
|
+
transformed.prompt_cache_key = options.promptCacheKey;
|
|
2491
|
+
if (options.promptCacheOptions)
|
|
2492
|
+
transformed.prompt_cache_options = options.promptCacheOptions;
|
|
1670
2493
|
const routing = mapRouting({ ...config2.routing, ...options.routing }, config2.allowedProviders);
|
|
1671
2494
|
if (Object.keys(routing).length > 0)
|
|
1672
2495
|
transformed.provider = routing;
|
|
@@ -1686,12 +2509,22 @@ var transformOpenRouterRequest = (config2, allowedModels, allowedPresets, body,
|
|
|
1686
2509
|
...options.serverTools
|
|
1687
2510
|
];
|
|
1688
2511
|
}
|
|
2512
|
+
if (options.messagesTools) {
|
|
2513
|
+
if (skin !== "messages")
|
|
2514
|
+
throw new Error("OpenRouter messagesTools requires openrouterMessages()");
|
|
2515
|
+
transformed.tools = [
|
|
2516
|
+
...Array.isArray(transformed.tools) ? transformed.tools : [],
|
|
2517
|
+
...options.messagesTools
|
|
2518
|
+
];
|
|
2519
|
+
}
|
|
1689
2520
|
if (options.serviceTier)
|
|
1690
2521
|
transformed.service_tier = options.serviceTier;
|
|
1691
2522
|
if (options.sessionId)
|
|
1692
2523
|
transformed.session_id = options.sessionId;
|
|
1693
2524
|
if (options.stopServerToolsWhen)
|
|
1694
2525
|
transformed.stop_server_tools_when = options.stopServerToolsWhen;
|
|
2526
|
+
if (options.trace)
|
|
2527
|
+
transformed.trace = options.trace;
|
|
1695
2528
|
if (options.transforms)
|
|
1696
2529
|
transformed.transforms = [...options.transforms];
|
|
1697
2530
|
if (options.user)
|
|
@@ -1721,7 +2554,7 @@ var openrouter = (config2) => {
|
|
|
1721
2554
|
const { allowedModels, allowedPresets } = snapshotPolicy(config2);
|
|
1722
2555
|
const provider = openai({
|
|
1723
2556
|
apiKey: config2.apiKey,
|
|
1724
|
-
baseUrl: config2.baseUrl ??
|
|
2557
|
+
baseUrl: config2.baseUrl ?? DEFAULT_BASE_URL5,
|
|
1725
2558
|
fetch: config2.fetch,
|
|
1726
2559
|
headers: (params) => resolveAttributionHeaders(config2, params),
|
|
1727
2560
|
modelForCapabilities: modelForOpenAICapabilities,
|
|
@@ -1736,7 +2569,7 @@ var openrouterResponses = (config2) => {
|
|
|
1736
2569
|
const { allowedModels, allowedPresets } = snapshotPolicy(config2);
|
|
1737
2570
|
const provider = openaiResponses({
|
|
1738
2571
|
apiKey: config2.apiKey,
|
|
1739
|
-
baseUrl: config2.baseUrl ??
|
|
2572
|
+
baseUrl: config2.baseUrl ?? DEFAULT_BASE_URL5,
|
|
1740
2573
|
fetch: config2.fetch,
|
|
1741
2574
|
headers: (params) => resolveAttributionHeaders(config2, params),
|
|
1742
2575
|
modelForCapabilities: modelForOpenAICapabilities,
|
|
@@ -1746,12 +2579,29 @@ var openrouterResponses = (config2) => {
|
|
|
1746
2579
|
});
|
|
1747
2580
|
return withOpenRouterPolicy(provider, allowedModels, allowedPresets);
|
|
1748
2581
|
};
|
|
2582
|
+
var openrouterMessages = (config2) => {
|
|
2583
|
+
assertRoutingPolicy(config2);
|
|
2584
|
+
const { allowedModels, allowedPresets } = snapshotPolicy(config2);
|
|
2585
|
+
const provider = anthropic({
|
|
2586
|
+
apiKey: config2.apiKey,
|
|
2587
|
+
authStyle: "bearer",
|
|
2588
|
+
baseUrl: config2.baseUrl ?? DEFAULT_BASE_URL5,
|
|
2589
|
+
fetch: config2.fetch,
|
|
2590
|
+
headers: (params) => resolveAttributionHeaders(config2, params),
|
|
2591
|
+
providerName: "openrouter",
|
|
2592
|
+
tokenSource: config2.tokenSource,
|
|
2593
|
+
transformRequestBody: (body, params) => transformOpenRouterRequest(config2, allowedModels, allowedPresets, body, params, "messages")
|
|
2594
|
+
});
|
|
2595
|
+
return withOpenRouterPolicy(provider, allowedModels, allowedPresets);
|
|
2596
|
+
};
|
|
1749
2597
|
export {
|
|
2598
|
+
verifyOpenRouterWebhookSignature,
|
|
1750
2599
|
openrouterResponses,
|
|
2600
|
+
openrouterMessages,
|
|
1751
2601
|
openrouter,
|
|
1752
2602
|
openRouterModelMatchesRule,
|
|
1753
2603
|
createOpenRouterClient
|
|
1754
2604
|
};
|
|
1755
2605
|
|
|
1756
|
-
//# debugId=
|
|
2606
|
+
//# debugId=29E9DB40EA495C0E64756E2164756E21
|
|
1757
2607
|
//# sourceMappingURL=openrouter.js.map
|