190proof 1.0.109 → 1.0.110
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 +2 -0
- package/dist/index.js +183 -105
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +182 -103
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -278,6 +278,8 @@ Optional per-request knobs live on `payload` (`GenericPayload`):
|
|
|
278
278
|
- `payload.requestTimeoutMs`: `number` - Per-attempt HTTP timeout in ms (default: 120000), honored by every adapter — except streaming OpenRouter attempts, which it deliberately does NOT bound (see below). For OpenRouter's non-streaming transport the default is 180000.
|
|
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
|
+
|
|
282
|
+
OpenRouter retries also perform **moderation eviction**: a provider content-moderation rejection (e.g. "Upstream error from Alibaba: Output data may contain inappropriate content.") is deterministic for a given payload, so on the first one the refusing provider is removed from the request's provider preferences (`ignore` += slug, `order` -= slug) and every remaining attempt reroutes to the next provider. Non-moderation errors retry with unchanged preferences, and `fallbackModel` still applies if the whole pool refuses.
|
|
281
283
|
- `payload.signal`: `AbortSignal` - Caller-supplied cancellation. When it aborts, the in-flight provider request is cancelled and `callWithRetries` **rejects immediately — it does not retry or fall back** (both the retry loop and the fallback branch bail on `signal.aborted`). Threaded to the underlying fetch/axios/SDK call of each provider.
|
|
282
284
|
|
|
283
285
|
#### Returns
|
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 proof_exports = {};
|
|
32
|
+
__export(proof_exports, {
|
|
33
33
|
ClaudeModel: () => ClaudeModel,
|
|
34
34
|
GPTModel: () => GPTModel,
|
|
35
35
|
GeminiModel: () => GeminiModel,
|
|
@@ -40,7 +40,7 @@ __export(index_exports, {
|
|
|
40
40
|
callWithRetries: () => callWithRetries,
|
|
41
41
|
parseModelString: () => parseModelString
|
|
42
42
|
});
|
|
43
|
-
module.exports = __toCommonJS(
|
|
43
|
+
module.exports = __toCommonJS(proof_exports);
|
|
44
44
|
|
|
45
45
|
// interfaces.ts
|
|
46
46
|
var ClaudeModel = /* @__PURE__ */ ((ClaudeModel2) => {
|
|
@@ -171,7 +171,8 @@ async function withRetries(identifier, apiName, fn, options = {}) {
|
|
|
171
171
|
return await fn();
|
|
172
172
|
} catch (error3) {
|
|
173
173
|
lastError = error3;
|
|
174
|
-
if ((_a = options.signal) == null ? void 0 : _a.aborted)
|
|
174
|
+
if ((_a = options.signal) == null ? void 0 : _a.aborted)
|
|
175
|
+
throw error3;
|
|
175
176
|
if (onError) {
|
|
176
177
|
onError(error3, attempt);
|
|
177
178
|
} else {
|
|
@@ -195,7 +196,8 @@ function parseStreamedResponse(identifier, paragraph, toolCallAccumulators, allo
|
|
|
195
196
|
const functionCalls = [];
|
|
196
197
|
for (let i = 0; i < toolCallAccumulators.length; i++) {
|
|
197
198
|
const acc = toolCallAccumulators[i];
|
|
198
|
-
if (!acc.name || !acc.arguments)
|
|
199
|
+
if (!acc.name || !acc.arguments)
|
|
200
|
+
continue;
|
|
199
201
|
if (allowedFunctionNames && !allowedFunctionNames.has(acc.name)) {
|
|
200
202
|
throw new Error(
|
|
201
203
|
`Stream error: received function call with unknown name: ${acc.name}`
|
|
@@ -334,7 +336,8 @@ function buildOpenAIRequestConfig(identifier, model, config) {
|
|
|
334
336
|
};
|
|
335
337
|
}
|
|
336
338
|
function filterOpenAICompatReasoningDetails(details) {
|
|
337
|
-
if (!Array.isArray(details))
|
|
339
|
+
if (!Array.isArray(details))
|
|
340
|
+
return details || void 0;
|
|
338
341
|
const blocks = details.filter(
|
|
339
342
|
(block) => typeof (block == null ? void 0 : block.type) === "string" && block.type.startsWith("reasoning.")
|
|
340
343
|
);
|
|
@@ -405,11 +408,13 @@ async function prepareOpenAIPayload(identifier, payload) {
|
|
|
405
408
|
};
|
|
406
409
|
});
|
|
407
410
|
}
|
|
408
|
-
if (message.reasoning)
|
|
411
|
+
if (message.reasoning)
|
|
412
|
+
outMessage.reasoning = message.reasoning;
|
|
409
413
|
const reasoningDetails = filterOpenAICompatReasoningDetails(
|
|
410
414
|
message.reasoningDetails
|
|
411
415
|
);
|
|
412
|
-
if (reasoningDetails)
|
|
416
|
+
if (reasoningDetails)
|
|
417
|
+
outMessage.reasoning_details = reasoningDetails;
|
|
413
418
|
preparedPayload.messages.push(outMessage);
|
|
414
419
|
}
|
|
415
420
|
return preparedPayload;
|
|
@@ -471,7 +476,8 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
|
|
|
471
476
|
}
|
|
472
477
|
const jsonStrings = chunk.split(/^data: /gm);
|
|
473
478
|
for (const jsonString of jsonStrings) {
|
|
474
|
-
if (!jsonString)
|
|
479
|
+
if (!jsonString)
|
|
480
|
+
continue;
|
|
475
481
|
if (jsonString.includes("[DONE]")) {
|
|
476
482
|
clearTimeout(overallTimeout);
|
|
477
483
|
return parseStreamedResponse(
|
|
@@ -509,7 +515,8 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
|
|
|
509
515
|
while (toolCallAccumulators.length <= idx) {
|
|
510
516
|
toolCallAccumulators.push({ name: "", arguments: "" });
|
|
511
517
|
}
|
|
512
|
-
if (toolCall.id)
|
|
518
|
+
if (toolCall.id)
|
|
519
|
+
toolCallAccumulators[idx].id = toolCall.id;
|
|
513
520
|
if ((_e = toolCall.function) == null ? void 0 : _e.name)
|
|
514
521
|
toolCallAccumulators[idx].name += toolCall.function.name;
|
|
515
522
|
if ((_f = toolCall.function) == null ? void 0 : _f.arguments)
|
|
@@ -517,9 +524,11 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
|
|
|
517
524
|
}
|
|
518
525
|
}
|
|
519
526
|
const text = (_h = (_g = json.choices[0]) == null ? void 0 : _g.delta) == null ? void 0 : _h.content;
|
|
520
|
-
if (text)
|
|
527
|
+
if (text)
|
|
528
|
+
paragraph += text;
|
|
521
529
|
const reasoningDelta = (_j = (_i = json.choices[0]) == null ? void 0 : _i.delta) == null ? void 0 : _j.reasoning;
|
|
522
|
-
if (reasoningDelta)
|
|
530
|
+
if (reasoningDelta)
|
|
531
|
+
reasoning += reasoningDelta;
|
|
523
532
|
}
|
|
524
533
|
}
|
|
525
534
|
}
|
|
@@ -664,7 +673,8 @@ function jigAnthropicMessages(messages) {
|
|
|
664
673
|
];
|
|
665
674
|
}
|
|
666
675
|
jiggedMessages = jiggedMessages.reduce((acc, message) => {
|
|
667
|
-
if (acc.length === 0)
|
|
676
|
+
if (acc.length === 0)
|
|
677
|
+
return [message];
|
|
668
678
|
const lastMessage = acc[acc.length - 1];
|
|
669
679
|
if (lastMessage.role === message.role) {
|
|
670
680
|
const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
|
|
@@ -918,7 +928,8 @@ function jigGoogleMessages(messages) {
|
|
|
918
928
|
];
|
|
919
929
|
}
|
|
920
930
|
jiggedMessages = jiggedMessages.reduce((acc, message) => {
|
|
921
|
-
if (acc.length === 0)
|
|
931
|
+
if (acc.length === 0)
|
|
932
|
+
return [message];
|
|
922
933
|
const lastMessage = acc[acc.length - 1];
|
|
923
934
|
if (lastMessage.role === message.role) {
|
|
924
935
|
lastMessage.parts = [...lastMessage.parts, ...message.parts];
|
|
@@ -956,7 +967,8 @@ async function prepareGoogleAIPayload(_identifier, payload) {
|
|
|
956
967
|
const toolNameById = /* @__PURE__ */ new Map();
|
|
957
968
|
for (const m of payload.messages) {
|
|
958
969
|
for (const fc of m.functionCalls || []) {
|
|
959
|
-
if (fc.id)
|
|
970
|
+
if (fc.id)
|
|
971
|
+
toolNameById.set(fc.id, fc.name);
|
|
960
972
|
}
|
|
961
973
|
}
|
|
962
974
|
for (const message of payload.messages) {
|
|
@@ -1033,7 +1045,8 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
|
|
|
1033
1045
|
contents,
|
|
1034
1046
|
generationConfig: { responseModalities: ["TEXT"] }
|
|
1035
1047
|
};
|
|
1036
|
-
if (payload.tools)
|
|
1048
|
+
if (payload.tools)
|
|
1049
|
+
requestBody.tools = [payload.tools];
|
|
1037
1050
|
if (payload.tools && payload.toolConfig) {
|
|
1038
1051
|
requestBody.toolConfig = payload.toolConfig;
|
|
1039
1052
|
}
|
|
@@ -1091,7 +1104,8 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
|
|
|
1091
1104
|
});
|
|
1092
1105
|
continue;
|
|
1093
1106
|
}
|
|
1094
|
-
if (part.text)
|
|
1107
|
+
if (part.text)
|
|
1108
|
+
text += part.text;
|
|
1095
1109
|
if ((_m = part.inlineData) == null ? void 0 : _m.data) {
|
|
1096
1110
|
files.push({ mimeType: "image/png", data: part.inlineData.data });
|
|
1097
1111
|
}
|
|
@@ -1168,15 +1182,21 @@ async function callGoogleAIWithRetries(id, payload, retries = 5, requestTimeoutM
|
|
|
1168
1182
|
finishReason: error2.finishReason,
|
|
1169
1183
|
modelVersion: error2.modelVersion
|
|
1170
1184
|
};
|
|
1171
|
-
if (error2.safetyRatings)
|
|
1172
|
-
|
|
1185
|
+
if (error2.safetyRatings)
|
|
1186
|
+
errorDetails.safetyRatings = error2.safetyRatings;
|
|
1187
|
+
if (error2.usageMetadata)
|
|
1188
|
+
errorDetails.usageMetadata = error2.usageMetadata;
|
|
1173
1189
|
if (error2.promptFeedback)
|
|
1174
1190
|
errorDetails.promptFeedback = error2.promptFeedback;
|
|
1175
|
-
if (error2.status)
|
|
1176
|
-
|
|
1177
|
-
if (error2.
|
|
1191
|
+
if (error2.status)
|
|
1192
|
+
errorDetails.httpStatus = error2.status;
|
|
1193
|
+
if (error2.code)
|
|
1194
|
+
errorDetails.errorCode = error2.code;
|
|
1195
|
+
if (error2.details)
|
|
1196
|
+
errorDetails.errorDetails = error2.details;
|
|
1178
1197
|
const fileUris = payload.messages.flatMap((m) => m.parts).filter((p) => "fileData" in p).map((p) => p.fileData.fileUri);
|
|
1179
|
-
if (fileUris.length)
|
|
1198
|
+
if (fileUris.length)
|
|
1199
|
+
errorDetails.fileUris = fileUris;
|
|
1180
1200
|
logger_default.error(
|
|
1181
1201
|
id,
|
|
1182
1202
|
`Retry #${attempt} error: ${error2.message}`,
|
|
@@ -1256,13 +1276,16 @@ function prepareOpenAICompatMessages(messages) {
|
|
|
1256
1276
|
}
|
|
1257
1277
|
};
|
|
1258
1278
|
});
|
|
1259
|
-
if (!message.content)
|
|
1279
|
+
if (!message.content)
|
|
1280
|
+
outMessage.content = null;
|
|
1260
1281
|
}
|
|
1261
|
-
if (message.reasoning)
|
|
1282
|
+
if (message.reasoning)
|
|
1283
|
+
outMessage.reasoning = message.reasoning;
|
|
1262
1284
|
const reasoningDetails = filterOpenAICompatReasoningDetails(
|
|
1263
1285
|
message.reasoningDetails
|
|
1264
1286
|
);
|
|
1265
|
-
if (reasoningDetails)
|
|
1287
|
+
if (reasoningDetails)
|
|
1288
|
+
outMessage.reasoning_details = reasoningDetails;
|
|
1266
1289
|
out.push(outMessage);
|
|
1267
1290
|
}
|
|
1268
1291
|
return out;
|
|
@@ -1405,7 +1428,8 @@ function parseDsmlToolCalls(content) {
|
|
|
1405
1428
|
let last = -1;
|
|
1406
1429
|
let tag;
|
|
1407
1430
|
while ((tag = DSML_ANY_TAG_RE.exec(content)) !== null) {
|
|
1408
|
-
if (first === -1)
|
|
1431
|
+
if (first === -1)
|
|
1432
|
+
first = tag.index;
|
|
1409
1433
|
last = tag.index + tag[0].length;
|
|
1410
1434
|
}
|
|
1411
1435
|
const remaining = first === -1 ? content : (content.slice(0, first) + content.slice(last)).trim();
|
|
@@ -1421,7 +1445,8 @@ function finalizeOpenRouterMessage(id, raw) {
|
|
|
1421
1445
|
const functionCalls = [];
|
|
1422
1446
|
for (let i = 0; i < raw.toolCalls.length; i++) {
|
|
1423
1447
|
const tc = raw.toolCalls[i];
|
|
1424
|
-
if (!tc.name)
|
|
1448
|
+
if (!tc.name)
|
|
1449
|
+
continue;
|
|
1425
1450
|
functionCalls.push({
|
|
1426
1451
|
id: (_a = tc.id) != null ? _a : `call_${i}`,
|
|
1427
1452
|
name: tc.name,
|
|
@@ -1472,7 +1497,8 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
|
|
|
1472
1497
|
controller.abort();
|
|
1473
1498
|
};
|
|
1474
1499
|
const unref = (t) => {
|
|
1475
|
-
if (typeof t === "object" && "unref" in t)
|
|
1500
|
+
if (typeof t === "object" && "unref" in t)
|
|
1501
|
+
t.unref();
|
|
1476
1502
|
return t;
|
|
1477
1503
|
};
|
|
1478
1504
|
const totalTimer = unref(
|
|
@@ -1538,88 +1564,98 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
|
|
|
1538
1564
|
const reader = response.body.getReader();
|
|
1539
1565
|
const decoder = new TextDecoder();
|
|
1540
1566
|
let lineBuffer = "";
|
|
1541
|
-
outer:
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
let
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
id,
|
|
1564
|
-
"OpenRouter stream: unparseable data line:",
|
|
1565
|
-
dataStr.slice(0, 200)
|
|
1566
|
-
);
|
|
1567
|
-
continue;
|
|
1568
|
-
}
|
|
1569
|
-
dataChunks++;
|
|
1570
|
-
if (json.error) {
|
|
1571
|
-
logger_default.error(id, "OpenRouter stream error event:", json.error);
|
|
1572
|
-
const error2 = new Error(
|
|
1573
|
-
`OpenRouter error: ${json.error.message}`
|
|
1574
|
-
);
|
|
1575
|
-
error2.data = json.error;
|
|
1576
|
-
throw error2;
|
|
1577
|
-
}
|
|
1578
|
-
if (json.provider) provider = json.provider;
|
|
1579
|
-
let useful = false;
|
|
1580
|
-
if (json.usage) {
|
|
1581
|
-
usage = json.usage;
|
|
1582
|
-
useful = true;
|
|
1583
|
-
}
|
|
1584
|
-
const choice = (_c = json.choices) == null ? void 0 : _c[0];
|
|
1585
|
-
if (choice) {
|
|
1586
|
-
const delta = (_d = choice.delta) != null ? _d : {};
|
|
1587
|
-
if (delta.content) {
|
|
1588
|
-
paragraph += delta.content;
|
|
1589
|
-
useful = true;
|
|
1567
|
+
outer:
|
|
1568
|
+
while (true) {
|
|
1569
|
+
const { done, value } = await reader.read();
|
|
1570
|
+
if (done)
|
|
1571
|
+
break;
|
|
1572
|
+
lineBuffer += decoder.decode(value, { stream: true });
|
|
1573
|
+
let newlineIdx;
|
|
1574
|
+
while ((newlineIdx = lineBuffer.indexOf("\n")) !== -1) {
|
|
1575
|
+
let line = lineBuffer.slice(0, newlineIdx);
|
|
1576
|
+
lineBuffer = lineBuffer.slice(newlineIdx + 1);
|
|
1577
|
+
if (line.endsWith("\r"))
|
|
1578
|
+
line = line.slice(0, -1);
|
|
1579
|
+
if (!line)
|
|
1580
|
+
continue;
|
|
1581
|
+
if (line.startsWith(":"))
|
|
1582
|
+
continue;
|
|
1583
|
+
if (!line.startsWith("data:"))
|
|
1584
|
+
continue;
|
|
1585
|
+
const dataStr = line.slice(5).trimStart();
|
|
1586
|
+
if (dataStr === "[DONE]") {
|
|
1587
|
+
sawDone = true;
|
|
1588
|
+
break outer;
|
|
1590
1589
|
}
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1590
|
+
let json;
|
|
1591
|
+
try {
|
|
1592
|
+
json = JSON.parse(dataStr);
|
|
1593
|
+
} catch (e) {
|
|
1594
|
+
logger_default.error(
|
|
1595
|
+
id,
|
|
1596
|
+
"OpenRouter stream: unparseable data line:",
|
|
1597
|
+
dataStr.slice(0, 200)
|
|
1598
|
+
);
|
|
1599
|
+
continue;
|
|
1600
|
+
}
|
|
1601
|
+
dataChunks++;
|
|
1602
|
+
if (json.error) {
|
|
1603
|
+
logger_default.error(id, "OpenRouter stream error event:", json.error);
|
|
1604
|
+
const error2 = new Error(
|
|
1605
|
+
`OpenRouter error: ${json.error.message}`
|
|
1606
|
+
);
|
|
1607
|
+
error2.data = json.error;
|
|
1608
|
+
throw error2;
|
|
1594
1609
|
}
|
|
1595
|
-
if (
|
|
1596
|
-
|
|
1610
|
+
if (json.provider)
|
|
1611
|
+
provider = json.provider;
|
|
1612
|
+
let useful = false;
|
|
1613
|
+
if (json.usage) {
|
|
1614
|
+
usage = json.usage;
|
|
1597
1615
|
useful = true;
|
|
1598
1616
|
}
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1617
|
+
const choice = (_c = json.choices) == null ? void 0 : _c[0];
|
|
1618
|
+
if (choice) {
|
|
1619
|
+
const delta = (_d = choice.delta) != null ? _d : {};
|
|
1620
|
+
if (delta.content) {
|
|
1621
|
+
paragraph += delta.content;
|
|
1622
|
+
useful = true;
|
|
1623
|
+
}
|
|
1624
|
+
if (delta.reasoning) {
|
|
1625
|
+
reasoning += delta.reasoning;
|
|
1626
|
+
useful = true;
|
|
1627
|
+
}
|
|
1628
|
+
if (Array.isArray(delta.reasoning_details) && delta.reasoning_details.length) {
|
|
1629
|
+
reasoningDetails.push(...delta.reasoning_details);
|
|
1630
|
+
useful = true;
|
|
1631
|
+
}
|
|
1632
|
+
if (Array.isArray(delta.tool_calls)) {
|
|
1633
|
+
for (const toolCall of delta.tool_calls) {
|
|
1634
|
+
const idx = (_e = toolCall.index) != null ? _e : 0;
|
|
1635
|
+
while (toolCalls.length <= idx) {
|
|
1636
|
+
toolCalls.push({ name: "", argumentsJson: "" });
|
|
1637
|
+
}
|
|
1638
|
+
if (toolCall.id)
|
|
1639
|
+
toolCalls[idx].id = toolCall.id;
|
|
1640
|
+
if ((_f = toolCall.function) == null ? void 0 : _f.name)
|
|
1641
|
+
toolCalls[idx].name += toolCall.function.name;
|
|
1642
|
+
if ((_g = toolCall.function) == null ? void 0 : _g.arguments)
|
|
1643
|
+
toolCalls[idx].argumentsJson += toolCall.function.arguments;
|
|
1644
|
+
useful = true;
|
|
1604
1645
|
}
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
if ((_g = toolCall.function) == null ? void 0 : _g.arguments)
|
|
1609
|
-
toolCalls[idx].argumentsJson += toolCall.function.arguments;
|
|
1646
|
+
}
|
|
1647
|
+
if (choice.finish_reason) {
|
|
1648
|
+
finishReason = choice.finish_reason;
|
|
1610
1649
|
useful = true;
|
|
1611
1650
|
}
|
|
1612
1651
|
}
|
|
1613
|
-
if (
|
|
1614
|
-
|
|
1615
|
-
useful = true;
|
|
1616
|
-
}
|
|
1652
|
+
if (useful)
|
|
1653
|
+
armStallTimer();
|
|
1617
1654
|
}
|
|
1618
|
-
if (useful) armStallTimer();
|
|
1619
1655
|
}
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1656
|
+
if (sawDone)
|
|
1657
|
+
reader.cancel().catch(() => {
|
|
1658
|
+
});
|
|
1623
1659
|
if (!sawDone && !finishReason) {
|
|
1624
1660
|
logger_default.error(
|
|
1625
1661
|
id,
|
|
@@ -1658,7 +1694,9 @@ function parseOpenRouterBody(id, data) {
|
|
|
1658
1694
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1659
1695
|
if (data.error) {
|
|
1660
1696
|
logger_default.error(id, "OpenRouter error:", data.error);
|
|
1661
|
-
|
|
1697
|
+
const error2 = new Error(`OpenRouter error: ${data.error.message}`);
|
|
1698
|
+
error2.data = data.error;
|
|
1699
|
+
throw error2;
|
|
1662
1700
|
}
|
|
1663
1701
|
const answer = (_b = (_a = data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message;
|
|
1664
1702
|
if (!answer) {
|
|
@@ -1695,11 +1733,32 @@ async function callOpenRouterNonStreaming(id, payload, requestTimeoutMs = OPENRO
|
|
|
1695
1733
|
);
|
|
1696
1734
|
return parseOpenRouterBody(id, response.data);
|
|
1697
1735
|
}
|
|
1736
|
+
var normalizeProviderKey = (name) => name.split("/")[0].toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1737
|
+
var MODERATION_RE = /moderat|inappropriate content|content polic|content management|flagged/i;
|
|
1738
|
+
function moderationEvictionSlug(error2, payload) {
|
|
1739
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1740
|
+
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;
|
|
1741
|
+
if (!body)
|
|
1742
|
+
return null;
|
|
1743
|
+
const message = String((_d = body.message) != null ? _d : "");
|
|
1744
|
+
const isModeration = body.code === 403 || Array.isArray((_e = body.metadata) == null ? void 0 : _e.reasons) || MODERATION_RE.test(message);
|
|
1745
|
+
if (!isModeration)
|
|
1746
|
+
return null;
|
|
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];
|
|
1748
|
+
if (!display)
|
|
1749
|
+
return null;
|
|
1750
|
+
const key = normalizeProviderKey(display);
|
|
1751
|
+
const fromOrder = (_j = (_i = payload.provider) == null ? void 0 : _i.order) == null ? void 0 : _j.find(
|
|
1752
|
+
(entry) => normalizeProviderKey(entry) === key
|
|
1753
|
+
);
|
|
1754
|
+
return fromOrder ? fromOrder.split("/")[0] : display.toLowerCase();
|
|
1755
|
+
}
|
|
1698
1756
|
async function callOpenRouterWithRetries(id, payload, retries = 5, options, signal) {
|
|
1757
|
+
const evicted = [];
|
|
1699
1758
|
return withRetries(
|
|
1700
1759
|
id,
|
|
1701
1760
|
"OpenRouter",
|
|
1702
|
-
() => options.streaming ? callOpenRouterStream(
|
|
1761
|
+
() => (options.streaming ? callOpenRouterStream(
|
|
1703
1762
|
id,
|
|
1704
1763
|
payload,
|
|
1705
1764
|
options.streamTimeoutMs,
|
|
@@ -1710,7 +1769,25 @@ async function callOpenRouterWithRetries(id, payload, retries = 5, options, sign
|
|
|
1710
1769
|
payload,
|
|
1711
1770
|
options.requestTimeoutMs,
|
|
1712
1771
|
signal
|
|
1713
|
-
)
|
|
1772
|
+
)).catch((error2) => {
|
|
1773
|
+
var _a, _b, _c, _d;
|
|
1774
|
+
const slug = moderationEvictionSlug(error2, payload);
|
|
1775
|
+
if (slug && !evicted.includes(slug)) {
|
|
1776
|
+
evicted.push(slug);
|
|
1777
|
+
payload.provider = {
|
|
1778
|
+
...payload.provider,
|
|
1779
|
+
ignore: [...(_b = (_a = payload.provider) == null ? void 0 : _a.ignore) != null ? _b : [], slug],
|
|
1780
|
+
order: (_d = (_c = payload.provider) == null ? void 0 : _c.order) == null ? void 0 : _d.filter(
|
|
1781
|
+
(entry) => normalizeProviderKey(entry) !== normalizeProviderKey(slug)
|
|
1782
|
+
)
|
|
1783
|
+
};
|
|
1784
|
+
logger_default.log(
|
|
1785
|
+
id,
|
|
1786
|
+
`OpenRouter moderation eviction: ignoring provider "${slug}" for remaining attempts`
|
|
1787
|
+
);
|
|
1788
|
+
}
|
|
1789
|
+
throw error2;
|
|
1790
|
+
}),
|
|
1714
1791
|
{ retries, signal }
|
|
1715
1792
|
);
|
|
1716
1793
|
}
|
|
@@ -1817,7 +1894,8 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
|
|
|
1817
1894
|
(_e = result.provider) != null ? _e : result.provider = provider;
|
|
1818
1895
|
return result;
|
|
1819
1896
|
} catch (error2) {
|
|
1820
|
-
if ((_f = aiPayload.signal) == null ? void 0 : _f.aborted)
|
|
1897
|
+
if ((_f = aiPayload.signal) == null ? void 0 : _f.aborted)
|
|
1898
|
+
throw error2;
|
|
1821
1899
|
if (aiPayload.fallbackModel) {
|
|
1822
1900
|
logger_default.error(
|
|
1823
1901
|
id,
|