190proof 1.0.112 → 1.0.114
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 +4 -0
- package/dist/index.d.mts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +119 -152
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +117 -151
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -279,6 +279,7 @@ Optional per-request knobs live on `payload` (`GenericPayload`):
|
|
|
279
279
|
- `payload.streaming`: `boolean` - OpenRouter-only (default: true). Streams the completion over SSE. A streaming attempt is bounded by two independent timers instead of `requestTimeoutMs`: `streamTimeoutMs` (total wall clock, default 600000) and the per-useful-chunk stall timeout (`chunkTimeoutMs` argument, default 15000). A chunk is "useful" only if it advances content, reasoning, tool-call fragments, finish_reason, or usage — SSE comment keep-alives (`: OPENROUTER PROCESSING`) and role-only deltas don't reset the stall timer, so a hung provider dies within one stall window while a healthy long generation can run to the total budget. Set `streaming: false` for the old single-JSON-body transport.
|
|
280
280
|
- `payload.streamTimeoutMs`: `number` - OpenRouter-only: total wall-clock budget per streaming attempt (default: 600000).
|
|
281
281
|
- `payload.streamDeadlineAt`: `number` - OpenRouter-only: absolute deadline (epoch ms) for the whole call **including retries** — the caller's turn budget. Each attempt gets `min(streamTimeoutMs, deadline - now)`, and once under 10s remain the call fails fast instead of starting a generation that cannot be delivered. Use it whenever the caller has its own timeout: a per-attempt budget alone is re-granted on every retry and can outlive that timeout.
|
|
282
|
+
- `payload.thinkingConfig`: `Record<string, unknown>` - Google-only: forwarded verbatim as `generationConfig.thinkingConfig` on the Gemini request — e.g. `{ thinkingBudget: 0 }` to disable thinking, `{ thinkingLevel: "HIGH" }` on models that take a level. Ignored by all other adapters; shapes are model-specific and validated by Google, not the SDK.
|
|
282
283
|
|
|
283
284
|
When a streaming attempt is cut at its **total deadline** and prose has already arrived, the partial answer is returned with `truncated: true` on the response rather than discarded — those tokens were generated and billed, so throwing them away costs money and gives the user nothing. Surface such a reply as incomplete. Salvage never applies to tool-call turns (half-streamed arguments are unparseable JSON), to stalls (the provider died mid-thought), or to caller aborts. When nothing is salvageable, the discard is logged with an approximate token count — aborted attempts never receive OpenRouter's `usage` chunk, so that log line is the only record of the wasted spend.
|
|
284
285
|
|
|
@@ -304,6 +305,9 @@ interface ParsedResponseMessage {
|
|
|
304
305
|
prompt_tokens: number;
|
|
305
306
|
completion_tokens: number;
|
|
306
307
|
total_tokens: number;
|
|
308
|
+
// Reasoning/thinking tokens spent before the visible answer; currently
|
|
309
|
+
// populated from Google's usageMetadata.thoughtsTokenCount.
|
|
310
|
+
thoughts_tokens?: number;
|
|
307
311
|
} | null; // null when streaming
|
|
308
312
|
}
|
|
309
313
|
```
|
package/dist/index.d.mts
CHANGED
|
@@ -199,6 +199,13 @@ interface ParsedResponseMessage {
|
|
|
199
199
|
total_tokens: number;
|
|
200
200
|
/** Prompt tokens served from the provider's cache (subset of prompt_tokens). */
|
|
201
201
|
cached_tokens?: number;
|
|
202
|
+
/**
|
|
203
|
+
* Reasoning/thinking tokens spent before the visible answer (subset of
|
|
204
|
+
* completion_tokens on some providers, separate on others). Currently
|
|
205
|
+
* populated from Google's `usageMetadata.thoughtsTokenCount`; undefined
|
|
206
|
+
* when the provider reports none.
|
|
207
|
+
*/
|
|
208
|
+
thoughts_tokens?: number;
|
|
202
209
|
} | null;
|
|
203
210
|
}
|
|
204
211
|
interface FunctionCall {
|
|
@@ -275,6 +282,14 @@ interface GenericPayload {
|
|
|
275
282
|
};
|
|
276
283
|
temperature?: number;
|
|
277
284
|
fallbackModel?: AnyModel;
|
|
285
|
+
/**
|
|
286
|
+
* Google-only: forwarded verbatim as `generationConfig.thinkingConfig` on
|
|
287
|
+
* the Gemini request — e.g. `{ thinkingBudget: 0 }` to disable thinking or
|
|
288
|
+
* `{ thinkingLevel: "HIGH" }` on models that take a level. Ignored by all
|
|
289
|
+
* other adapters. Shapes are model-specific and validated by Google, not
|
|
290
|
+
* the SDK.
|
|
291
|
+
*/
|
|
292
|
+
thinkingConfig?: Record<string, unknown>;
|
|
278
293
|
/**
|
|
279
294
|
* OpenRouter-only: provider-routing preferences. Ignored by non-OpenRouter
|
|
280
295
|
* adapters. Forwarded as the request body's `provider` field.
|
package/dist/index.d.ts
CHANGED
|
@@ -199,6 +199,13 @@ interface ParsedResponseMessage {
|
|
|
199
199
|
total_tokens: number;
|
|
200
200
|
/** Prompt tokens served from the provider's cache (subset of prompt_tokens). */
|
|
201
201
|
cached_tokens?: number;
|
|
202
|
+
/**
|
|
203
|
+
* Reasoning/thinking tokens spent before the visible answer (subset of
|
|
204
|
+
* completion_tokens on some providers, separate on others). Currently
|
|
205
|
+
* populated from Google's `usageMetadata.thoughtsTokenCount`; undefined
|
|
206
|
+
* when the provider reports none.
|
|
207
|
+
*/
|
|
208
|
+
thoughts_tokens?: number;
|
|
202
209
|
} | null;
|
|
203
210
|
}
|
|
204
211
|
interface FunctionCall {
|
|
@@ -275,6 +282,14 @@ interface GenericPayload {
|
|
|
275
282
|
};
|
|
276
283
|
temperature?: number;
|
|
277
284
|
fallbackModel?: AnyModel;
|
|
285
|
+
/**
|
|
286
|
+
* Google-only: forwarded verbatim as `generationConfig.thinkingConfig` on
|
|
287
|
+
* the Gemini request — e.g. `{ thinkingBudget: 0 }` to disable thinking or
|
|
288
|
+
* `{ thinkingLevel: "HIGH" }` on models that take a level. Ignored by all
|
|
289
|
+
* other adapters. Shapes are model-specific and validated by Google, not
|
|
290
|
+
* the SDK.
|
|
291
|
+
*/
|
|
292
|
+
thinkingConfig?: Record<string, unknown>;
|
|
278
293
|
/**
|
|
279
294
|
* OpenRouter-only: provider-routing preferences. Ignored by non-OpenRouter
|
|
280
295
|
* adapters. Forwarded as the request body's `provider` field.
|
package/dist/index.js
CHANGED
|
@@ -28,8 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
30
|
// index.ts
|
|
31
|
-
var
|
|
32
|
-
__export(
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
33
|
ClaudeModel: () => ClaudeModel,
|
|
34
34
|
GPTModel: () => GPTModel,
|
|
35
35
|
GeminiModel: () => GeminiModel,
|
|
@@ -41,7 +41,7 @@ __export(proof_exports, {
|
|
|
41
41
|
callWithRetries: () => callWithRetries,
|
|
42
42
|
parseModelString: () => parseModelString
|
|
43
43
|
});
|
|
44
|
-
module.exports = __toCommonJS(
|
|
44
|
+
module.exports = __toCommonJS(index_exports);
|
|
45
45
|
|
|
46
46
|
// interfaces.ts
|
|
47
47
|
var ClaudeModel = /* @__PURE__ */ ((ClaudeModel2) => {
|
|
@@ -172,8 +172,7 @@ async function withRetries(identifier, apiName, fn, options = {}) {
|
|
|
172
172
|
return await fn();
|
|
173
173
|
} catch (error3) {
|
|
174
174
|
lastError = error3;
|
|
175
|
-
if ((_a = options.signal) == null ? void 0 : _a.aborted)
|
|
176
|
-
throw error3;
|
|
175
|
+
if ((_a = options.signal) == null ? void 0 : _a.aborted) throw error3;
|
|
177
176
|
if (onError) {
|
|
178
177
|
onError(error3, attempt);
|
|
179
178
|
} else {
|
|
@@ -197,8 +196,7 @@ function parseStreamedResponse(identifier, paragraph, toolCallAccumulators, allo
|
|
|
197
196
|
const functionCalls = [];
|
|
198
197
|
for (let i = 0; i < toolCallAccumulators.length; i++) {
|
|
199
198
|
const acc = toolCallAccumulators[i];
|
|
200
|
-
if (!acc.name || !acc.arguments)
|
|
201
|
-
continue;
|
|
199
|
+
if (!acc.name || !acc.arguments) continue;
|
|
202
200
|
if (allowedFunctionNames && !allowedFunctionNames.has(acc.name)) {
|
|
203
201
|
throw new Error(
|
|
204
202
|
`Stream error: received function call with unknown name: ${acc.name}`
|
|
@@ -337,8 +335,7 @@ function buildOpenAIRequestConfig(identifier, model, config) {
|
|
|
337
335
|
};
|
|
338
336
|
}
|
|
339
337
|
function filterOpenAICompatReasoningDetails(details) {
|
|
340
|
-
if (!Array.isArray(details))
|
|
341
|
-
return details || void 0;
|
|
338
|
+
if (!Array.isArray(details)) return details || void 0;
|
|
342
339
|
const blocks = details.filter(
|
|
343
340
|
(block) => typeof (block == null ? void 0 : block.type) === "string" && block.type.startsWith("reasoning.")
|
|
344
341
|
);
|
|
@@ -409,13 +406,11 @@ async function prepareOpenAIPayload(identifier, payload) {
|
|
|
409
406
|
};
|
|
410
407
|
});
|
|
411
408
|
}
|
|
412
|
-
if (message.reasoning)
|
|
413
|
-
outMessage.reasoning = message.reasoning;
|
|
409
|
+
if (message.reasoning) outMessage.reasoning = message.reasoning;
|
|
414
410
|
const reasoningDetails = filterOpenAICompatReasoningDetails(
|
|
415
411
|
message.reasoningDetails
|
|
416
412
|
);
|
|
417
|
-
if (reasoningDetails)
|
|
418
|
-
outMessage.reasoning_details = reasoningDetails;
|
|
413
|
+
if (reasoningDetails) outMessage.reasoning_details = reasoningDetails;
|
|
419
414
|
preparedPayload.messages.push(outMessage);
|
|
420
415
|
}
|
|
421
416
|
return preparedPayload;
|
|
@@ -477,8 +472,7 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
|
|
|
477
472
|
}
|
|
478
473
|
const jsonStrings = chunk.split(/^data: /gm);
|
|
479
474
|
for (const jsonString of jsonStrings) {
|
|
480
|
-
if (!jsonString)
|
|
481
|
-
continue;
|
|
475
|
+
if (!jsonString) continue;
|
|
482
476
|
if (jsonString.includes("[DONE]")) {
|
|
483
477
|
clearTimeout(overallTimeout);
|
|
484
478
|
return parseStreamedResponse(
|
|
@@ -516,8 +510,7 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
|
|
|
516
510
|
while (toolCallAccumulators.length <= idx) {
|
|
517
511
|
toolCallAccumulators.push({ name: "", arguments: "" });
|
|
518
512
|
}
|
|
519
|
-
if (toolCall.id)
|
|
520
|
-
toolCallAccumulators[idx].id = toolCall.id;
|
|
513
|
+
if (toolCall.id) toolCallAccumulators[idx].id = toolCall.id;
|
|
521
514
|
if ((_e = toolCall.function) == null ? void 0 : _e.name)
|
|
522
515
|
toolCallAccumulators[idx].name += toolCall.function.name;
|
|
523
516
|
if ((_f = toolCall.function) == null ? void 0 : _f.arguments)
|
|
@@ -525,11 +518,9 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
|
|
|
525
518
|
}
|
|
526
519
|
}
|
|
527
520
|
const text = (_h = (_g = json.choices[0]) == null ? void 0 : _g.delta) == null ? void 0 : _h.content;
|
|
528
|
-
if (text)
|
|
529
|
-
paragraph += text;
|
|
521
|
+
if (text) paragraph += text;
|
|
530
522
|
const reasoningDelta = (_j = (_i = json.choices[0]) == null ? void 0 : _i.delta) == null ? void 0 : _j.reasoning;
|
|
531
|
-
if (reasoningDelta)
|
|
532
|
-
reasoning += reasoningDelta;
|
|
523
|
+
if (reasoningDelta) reasoning += reasoningDelta;
|
|
533
524
|
}
|
|
534
525
|
}
|
|
535
526
|
}
|
|
@@ -674,8 +665,7 @@ function jigAnthropicMessages(messages) {
|
|
|
674
665
|
];
|
|
675
666
|
}
|
|
676
667
|
jiggedMessages = jiggedMessages.reduce((acc, message) => {
|
|
677
|
-
if (acc.length === 0)
|
|
678
|
-
return [message];
|
|
668
|
+
if (acc.length === 0) return [message];
|
|
679
669
|
const lastMessage = acc[acc.length - 1];
|
|
680
670
|
if (lastMessage.role === message.role) {
|
|
681
671
|
const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
|
|
@@ -929,8 +919,7 @@ function jigGoogleMessages(messages) {
|
|
|
929
919
|
];
|
|
930
920
|
}
|
|
931
921
|
jiggedMessages = jiggedMessages.reduce((acc, message) => {
|
|
932
|
-
if (acc.length === 0)
|
|
933
|
-
return [message];
|
|
922
|
+
if (acc.length === 0) return [message];
|
|
934
923
|
const lastMessage = acc[acc.length - 1];
|
|
935
924
|
if (lastMessage.role === message.role) {
|
|
936
925
|
lastMessage.parts = [...lastMessage.parts, ...message.parts];
|
|
@@ -948,6 +937,7 @@ async function prepareGoogleAIPayload(_identifier, payload) {
|
|
|
948
937
|
const preparedPayload = {
|
|
949
938
|
model: payload.model,
|
|
950
939
|
messages: [],
|
|
940
|
+
thinkingConfig: payload.thinkingConfig,
|
|
951
941
|
tools: payload.functions ? {
|
|
952
942
|
functionDeclarations: payload.functions.map((fn) => ({
|
|
953
943
|
name: fn.name,
|
|
@@ -968,8 +958,7 @@ async function prepareGoogleAIPayload(_identifier, payload) {
|
|
|
968
958
|
const toolNameById = /* @__PURE__ */ new Map();
|
|
969
959
|
for (const m of payload.messages) {
|
|
970
960
|
for (const fc of m.functionCalls || []) {
|
|
971
|
-
if (fc.id)
|
|
972
|
-
toolNameById.set(fc.id, fc.name);
|
|
961
|
+
if (fc.id) toolNameById.set(fc.id, fc.name);
|
|
973
962
|
}
|
|
974
963
|
}
|
|
975
964
|
for (const message of payload.messages) {
|
|
@@ -1044,10 +1033,12 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
|
|
|
1044
1033
|
const contents = jigGoogleMessages(payload.messages);
|
|
1045
1034
|
const requestBody = {
|
|
1046
1035
|
contents,
|
|
1047
|
-
generationConfig: {
|
|
1036
|
+
generationConfig: {
|
|
1037
|
+
responseModalities: ["TEXT"],
|
|
1038
|
+
...payload.thinkingConfig ? { thinkingConfig: payload.thinkingConfig } : {}
|
|
1039
|
+
}
|
|
1048
1040
|
};
|
|
1049
|
-
if (payload.tools)
|
|
1050
|
-
requestBody.tools = [payload.tools];
|
|
1041
|
+
if (payload.tools) requestBody.tools = [payload.tools];
|
|
1051
1042
|
if (payload.tools && payload.toolConfig) {
|
|
1052
1043
|
requestBody.toolConfig = payload.toolConfig;
|
|
1053
1044
|
}
|
|
@@ -1105,8 +1096,7 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
|
|
|
1105
1096
|
});
|
|
1106
1097
|
continue;
|
|
1107
1098
|
}
|
|
1108
|
-
if (part.text)
|
|
1109
|
-
text += part.text;
|
|
1099
|
+
if (part.text) text += part.text;
|
|
1110
1100
|
if ((_m = part.inlineData) == null ? void 0 : _m.data) {
|
|
1111
1101
|
files.push({ mimeType: "image/png", data: part.inlineData.data });
|
|
1112
1102
|
}
|
|
@@ -1150,7 +1140,8 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
|
|
|
1150
1140
|
prompt_tokens: (_o = response.usageMetadata.promptTokenCount) != null ? _o : 0,
|
|
1151
1141
|
completion_tokens: (_p = response.usageMetadata.candidatesTokenCount) != null ? _p : 0,
|
|
1152
1142
|
total_tokens: (_q = response.usageMetadata.totalTokenCount) != null ? _q : 0,
|
|
1153
|
-
cached_tokens: (_r = response.usageMetadata.cachedContentTokenCount) != null ? _r : 0
|
|
1143
|
+
cached_tokens: (_r = response.usageMetadata.cachedContentTokenCount) != null ? _r : 0,
|
|
1144
|
+
thoughts_tokens: response.usageMetadata.thoughtsTokenCount
|
|
1154
1145
|
} : null
|
|
1155
1146
|
};
|
|
1156
1147
|
}
|
|
@@ -1183,21 +1174,15 @@ async function callGoogleAIWithRetries(id, payload, retries = 5, requestTimeoutM
|
|
|
1183
1174
|
finishReason: error2.finishReason,
|
|
1184
1175
|
modelVersion: error2.modelVersion
|
|
1185
1176
|
};
|
|
1186
|
-
if (error2.safetyRatings)
|
|
1187
|
-
|
|
1188
|
-
if (error2.usageMetadata)
|
|
1189
|
-
errorDetails.usageMetadata = error2.usageMetadata;
|
|
1177
|
+
if (error2.safetyRatings) errorDetails.safetyRatings = error2.safetyRatings;
|
|
1178
|
+
if (error2.usageMetadata) errorDetails.usageMetadata = error2.usageMetadata;
|
|
1190
1179
|
if (error2.promptFeedback)
|
|
1191
1180
|
errorDetails.promptFeedback = error2.promptFeedback;
|
|
1192
|
-
if (error2.status)
|
|
1193
|
-
|
|
1194
|
-
if (error2.
|
|
1195
|
-
errorDetails.errorCode = error2.code;
|
|
1196
|
-
if (error2.details)
|
|
1197
|
-
errorDetails.errorDetails = error2.details;
|
|
1181
|
+
if (error2.status) errorDetails.httpStatus = error2.status;
|
|
1182
|
+
if (error2.code) errorDetails.errorCode = error2.code;
|
|
1183
|
+
if (error2.details) errorDetails.errorDetails = error2.details;
|
|
1198
1184
|
const fileUris = payload.messages.flatMap((m) => m.parts).filter((p) => "fileData" in p).map((p) => p.fileData.fileUri);
|
|
1199
|
-
if (fileUris.length)
|
|
1200
|
-
errorDetails.fileUris = fileUris;
|
|
1185
|
+
if (fileUris.length) errorDetails.fileUris = fileUris;
|
|
1201
1186
|
logger_default.error(
|
|
1202
1187
|
id,
|
|
1203
1188
|
`Retry #${attempt} error: ${error2.message}`,
|
|
@@ -1261,9 +1246,13 @@ function prepareOpenAICompatMessages(messages) {
|
|
|
1261
1246
|
}
|
|
1262
1247
|
continue;
|
|
1263
1248
|
}
|
|
1249
|
+
const fileRefs = (message.files || []).filter((file) => file.url).map(
|
|
1250
|
+
(file) => ALLOWED_IMAGE_MIME_TYPES.includes(file.mimeType) ? `Image (${file.url})` : `File (${file.url})`
|
|
1251
|
+
);
|
|
1252
|
+
const content = [normalizeMessageContent(message.content), ...fileRefs].filter(Boolean).join("\n");
|
|
1264
1253
|
const outMessage = {
|
|
1265
1254
|
role: message.role,
|
|
1266
|
-
content
|
|
1255
|
+
content
|
|
1267
1256
|
};
|
|
1268
1257
|
if ((_a = message.functionCalls) == null ? void 0 : _a.length) {
|
|
1269
1258
|
outMessage.tool_calls = message.functionCalls.map((fc, i) => {
|
|
@@ -1277,16 +1266,13 @@ function prepareOpenAICompatMessages(messages) {
|
|
|
1277
1266
|
}
|
|
1278
1267
|
};
|
|
1279
1268
|
});
|
|
1280
|
-
if (!
|
|
1281
|
-
outMessage.content = null;
|
|
1269
|
+
if (!content) outMessage.content = null;
|
|
1282
1270
|
}
|
|
1283
|
-
if (message.reasoning)
|
|
1284
|
-
outMessage.reasoning = message.reasoning;
|
|
1271
|
+
if (message.reasoning) outMessage.reasoning = message.reasoning;
|
|
1285
1272
|
const reasoningDetails = filterOpenAICompatReasoningDetails(
|
|
1286
1273
|
message.reasoningDetails
|
|
1287
1274
|
);
|
|
1288
|
-
if (reasoningDetails)
|
|
1289
|
-
outMessage.reasoning_details = reasoningDetails;
|
|
1275
|
+
if (reasoningDetails) outMessage.reasoning_details = reasoningDetails;
|
|
1290
1276
|
out.push(outMessage);
|
|
1291
1277
|
}
|
|
1292
1278
|
return out;
|
|
@@ -1429,8 +1415,7 @@ function parseDsmlToolCalls(content) {
|
|
|
1429
1415
|
let last = -1;
|
|
1430
1416
|
let tag;
|
|
1431
1417
|
while ((tag = DSML_ANY_TAG_RE.exec(content)) !== null) {
|
|
1432
|
-
if (first === -1)
|
|
1433
|
-
first = tag.index;
|
|
1418
|
+
if (first === -1) first = tag.index;
|
|
1434
1419
|
last = tag.index + tag[0].length;
|
|
1435
1420
|
}
|
|
1436
1421
|
const remaining = first === -1 ? content : (content.slice(0, first) + content.slice(last)).trim();
|
|
@@ -1446,8 +1431,7 @@ function finalizeOpenRouterMessage(id, raw) {
|
|
|
1446
1431
|
const functionCalls = [];
|
|
1447
1432
|
for (let i = 0; i < raw.toolCalls.length; i++) {
|
|
1448
1433
|
const tc = raw.toolCalls[i];
|
|
1449
|
-
if (!tc.name)
|
|
1450
|
-
continue;
|
|
1434
|
+
if (!tc.name) continue;
|
|
1451
1435
|
functionCalls.push({
|
|
1452
1436
|
id: (_a = tc.id) != null ? _a : `call_${i}`,
|
|
1453
1437
|
name: tc.name,
|
|
@@ -1500,8 +1484,7 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
|
|
|
1500
1484
|
controller.abort();
|
|
1501
1485
|
};
|
|
1502
1486
|
const unref = (t) => {
|
|
1503
|
-
if (typeof t === "object" && "unref" in t)
|
|
1504
|
-
t.unref();
|
|
1487
|
+
if (typeof t === "object" && "unref" in t) t.unref();
|
|
1505
1488
|
return t;
|
|
1506
1489
|
};
|
|
1507
1490
|
const totalTimer = unref(
|
|
@@ -1569,98 +1552,88 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
|
|
|
1569
1552
|
const reader = response.body.getReader();
|
|
1570
1553
|
const decoder = new TextDecoder();
|
|
1571
1554
|
let lineBuffer = "";
|
|
1572
|
-
outer:
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
let newlineIdx;
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1555
|
+
outer: while (true) {
|
|
1556
|
+
const { done, value } = await reader.read();
|
|
1557
|
+
if (done) break;
|
|
1558
|
+
lineBuffer += decoder.decode(value, { stream: true });
|
|
1559
|
+
let newlineIdx;
|
|
1560
|
+
while ((newlineIdx = lineBuffer.indexOf("\n")) !== -1) {
|
|
1561
|
+
let line = lineBuffer.slice(0, newlineIdx);
|
|
1562
|
+
lineBuffer = lineBuffer.slice(newlineIdx + 1);
|
|
1563
|
+
if (line.endsWith("\r")) line = line.slice(0, -1);
|
|
1564
|
+
if (!line) continue;
|
|
1565
|
+
if (line.startsWith(":")) continue;
|
|
1566
|
+
if (!line.startsWith("data:")) continue;
|
|
1567
|
+
const dataStr = line.slice(5).trimStart();
|
|
1568
|
+
if (dataStr === "[DONE]") {
|
|
1569
|
+
sawDone = true;
|
|
1570
|
+
break outer;
|
|
1571
|
+
}
|
|
1572
|
+
let json;
|
|
1573
|
+
try {
|
|
1574
|
+
json = JSON.parse(dataStr);
|
|
1575
|
+
} catch (e) {
|
|
1576
|
+
logger_default.error(
|
|
1577
|
+
id,
|
|
1578
|
+
"OpenRouter stream: unparseable data line:",
|
|
1579
|
+
dataStr.slice(0, 200)
|
|
1580
|
+
);
|
|
1581
|
+
continue;
|
|
1582
|
+
}
|
|
1583
|
+
dataChunks++;
|
|
1584
|
+
if (json.error) {
|
|
1585
|
+
logger_default.error(id, "OpenRouter stream error event:", json.error);
|
|
1586
|
+
const error2 = new Error(
|
|
1587
|
+
`OpenRouter error: ${json.error.message}`
|
|
1588
|
+
);
|
|
1589
|
+
error2.data = json.error;
|
|
1590
|
+
throw error2;
|
|
1591
|
+
}
|
|
1592
|
+
if (json.provider) provider = json.provider;
|
|
1593
|
+
let useful = false;
|
|
1594
|
+
if (json.usage) {
|
|
1595
|
+
usage = json.usage;
|
|
1596
|
+
useful = true;
|
|
1597
|
+
}
|
|
1598
|
+
const choice = (_c = json.choices) == null ? void 0 : _c[0];
|
|
1599
|
+
if (choice) {
|
|
1600
|
+
const delta = (_d = choice.delta) != null ? _d : {};
|
|
1601
|
+
if (delta.content) {
|
|
1602
|
+
paragraph += delta.content;
|
|
1603
|
+
useful = true;
|
|
1605
1604
|
}
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
const error2 = new Error(
|
|
1610
|
-
`OpenRouter error: ${json.error.message}`
|
|
1611
|
-
);
|
|
1612
|
-
error2.data = json.error;
|
|
1613
|
-
throw error2;
|
|
1605
|
+
if (delta.reasoning) {
|
|
1606
|
+
reasoning += delta.reasoning;
|
|
1607
|
+
useful = true;
|
|
1614
1608
|
}
|
|
1615
|
-
if (
|
|
1616
|
-
|
|
1617
|
-
let useful = false;
|
|
1618
|
-
if (json.usage) {
|
|
1619
|
-
usage = json.usage;
|
|
1609
|
+
if (Array.isArray(delta.reasoning_details) && delta.reasoning_details.length) {
|
|
1610
|
+
reasoningDetails.push(...delta.reasoning_details);
|
|
1620
1611
|
useful = true;
|
|
1621
1612
|
}
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
useful = true;
|
|
1628
|
-
}
|
|
1629
|
-
if (delta.reasoning) {
|
|
1630
|
-
reasoning += delta.reasoning;
|
|
1631
|
-
useful = true;
|
|
1632
|
-
}
|
|
1633
|
-
if (Array.isArray(delta.reasoning_details) && delta.reasoning_details.length) {
|
|
1634
|
-
reasoningDetails.push(...delta.reasoning_details);
|
|
1635
|
-
useful = true;
|
|
1636
|
-
}
|
|
1637
|
-
if (Array.isArray(delta.tool_calls)) {
|
|
1638
|
-
for (const toolCall of delta.tool_calls) {
|
|
1639
|
-
const idx = (_e = toolCall.index) != null ? _e : 0;
|
|
1640
|
-
while (toolCalls.length <= idx) {
|
|
1641
|
-
toolCalls.push({ name: "", argumentsJson: "" });
|
|
1642
|
-
}
|
|
1643
|
-
if (toolCall.id)
|
|
1644
|
-
toolCalls[idx].id = toolCall.id;
|
|
1645
|
-
if ((_f = toolCall.function) == null ? void 0 : _f.name)
|
|
1646
|
-
toolCalls[idx].name += toolCall.function.name;
|
|
1647
|
-
if ((_g = toolCall.function) == null ? void 0 : _g.arguments)
|
|
1648
|
-
toolCalls[idx].argumentsJson += toolCall.function.arguments;
|
|
1649
|
-
useful = true;
|
|
1613
|
+
if (Array.isArray(delta.tool_calls)) {
|
|
1614
|
+
for (const toolCall of delta.tool_calls) {
|
|
1615
|
+
const idx = (_e = toolCall.index) != null ? _e : 0;
|
|
1616
|
+
while (toolCalls.length <= idx) {
|
|
1617
|
+
toolCalls.push({ name: "", argumentsJson: "" });
|
|
1650
1618
|
}
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1619
|
+
if (toolCall.id) toolCalls[idx].id = toolCall.id;
|
|
1620
|
+
if ((_f = toolCall.function) == null ? void 0 : _f.name)
|
|
1621
|
+
toolCalls[idx].name += toolCall.function.name;
|
|
1622
|
+
if ((_g = toolCall.function) == null ? void 0 : _g.arguments)
|
|
1623
|
+
toolCalls[idx].argumentsJson += toolCall.function.arguments;
|
|
1654
1624
|
useful = true;
|
|
1655
1625
|
}
|
|
1656
1626
|
}
|
|
1657
|
-
if (
|
|
1658
|
-
|
|
1627
|
+
if (choice.finish_reason) {
|
|
1628
|
+
finishReason = choice.finish_reason;
|
|
1629
|
+
useful = true;
|
|
1630
|
+
}
|
|
1659
1631
|
}
|
|
1632
|
+
if (useful) armStallTimer();
|
|
1660
1633
|
}
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1634
|
+
}
|
|
1635
|
+
if (sawDone) reader.cancel().catch(() => {
|
|
1636
|
+
});
|
|
1664
1637
|
if (!sawDone && !finishReason) {
|
|
1665
1638
|
logger_default.error(
|
|
1666
1639
|
id,
|
|
@@ -1767,15 +1740,12 @@ var MODERATION_RE = /moderat|inappropriate content|content polic|content managem
|
|
|
1767
1740
|
function moderationEvictionSlug(error2, payload) {
|
|
1768
1741
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1769
1742
|
const body = (_c = error2 == null ? void 0 : error2.data) != null ? _c : (_b = (_a = error2 == null ? void 0 : error2.response) == null ? void 0 : _a.data) == null ? void 0 : _b.error;
|
|
1770
|
-
if (!body)
|
|
1771
|
-
return null;
|
|
1743
|
+
if (!body) return null;
|
|
1772
1744
|
const message = String((_d = body.message) != null ? _d : "");
|
|
1773
1745
|
const isModeration = body.code === 403 || Array.isArray((_e = body.metadata) == null ? void 0 : _e.reasons) || MODERATION_RE.test(message);
|
|
1774
|
-
if (!isModeration)
|
|
1775
|
-
return null;
|
|
1746
|
+
if (!isModeration) return null;
|
|
1776
1747
|
const display = (_h = (_f = body.metadata) == null ? void 0 : _f.provider_name) != null ? _h : (_g = /Upstream error from ([^:]+):/.exec(message)) == null ? void 0 : _g[1];
|
|
1777
|
-
if (!display)
|
|
1778
|
-
return null;
|
|
1748
|
+
if (!display) return null;
|
|
1779
1749
|
const key = normalizeProviderKey(display);
|
|
1780
1750
|
const fromOrder = (_j = (_i = payload.provider) == null ? void 0 : _i.order) == null ? void 0 : _j.find(
|
|
1781
1751
|
(entry) => normalizeProviderKey(entry) === key
|
|
@@ -1785,11 +1755,9 @@ function moderationEvictionSlug(error2, payload) {
|
|
|
1785
1755
|
var MIN_STREAM_ATTEMPT_MS = 1e4;
|
|
1786
1756
|
var estimateTokens = (text) => Math.round(text.length / 4);
|
|
1787
1757
|
function streamAttemptBudgetMs(options) {
|
|
1788
|
-
if (options.streamDeadlineAt === void 0)
|
|
1789
|
-
return options.streamTimeoutMs;
|
|
1758
|
+
if (options.streamDeadlineAt === void 0) return options.streamTimeoutMs;
|
|
1790
1759
|
const remaining = options.streamDeadlineAt - Date.now();
|
|
1791
|
-
if (remaining < MIN_STREAM_ATTEMPT_MS)
|
|
1792
|
-
return null;
|
|
1760
|
+
if (remaining < MIN_STREAM_ATTEMPT_MS) return null;
|
|
1793
1761
|
return Math.min(options.streamTimeoutMs, remaining);
|
|
1794
1762
|
}
|
|
1795
1763
|
async function callOpenRouterWithRetries(id, payload, retries = 5, options, signal) {
|
|
@@ -1945,8 +1913,7 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
|
|
|
1945
1913
|
(_e = result.provider) != null ? _e : result.provider = provider;
|
|
1946
1914
|
return result;
|
|
1947
1915
|
} catch (error2) {
|
|
1948
|
-
if ((_f = aiPayload.signal) == null ? void 0 : _f.aborted)
|
|
1949
|
-
throw error2;
|
|
1916
|
+
if ((_f = aiPayload.signal) == null ? void 0 : _f.aborted) throw error2;
|
|
1950
1917
|
if (aiPayload.fallbackModel) {
|
|
1951
1918
|
logger_default.error(
|
|
1952
1919
|
id,
|