190proof 1.0.108 → 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/dist/index.js CHANGED
@@ -28,17 +28,19 @@ 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 index_exports = {};
32
- __export(index_exports, {
31
+ var proof_exports = {};
32
+ __export(proof_exports, {
33
33
  ClaudeModel: () => ClaudeModel,
34
34
  GPTModel: () => GPTModel,
35
35
  GeminiModel: () => GeminiModel,
36
36
  GroqModel: () => GroqModel,
37
+ OPENROUTER_NONSTREAM_TIMEOUT_MS: () => OPENROUTER_NONSTREAM_TIMEOUT_MS,
38
+ OPENROUTER_STREAM_TIMEOUT_MS: () => OPENROUTER_STREAM_TIMEOUT_MS,
37
39
  OpenRouterModel: () => OpenRouterModel,
38
40
  callWithRetries: () => callWithRetries,
39
41
  parseModelString: () => parseModelString
40
42
  });
41
- module.exports = __toCommonJS(index_exports);
43
+ module.exports = __toCommonJS(proof_exports);
42
44
 
43
45
  // interfaces.ts
44
46
  var ClaudeModel = /* @__PURE__ */ ((ClaudeModel2) => {
@@ -169,7 +171,8 @@ async function withRetries(identifier, apiName, fn, options = {}) {
169
171
  return await fn();
170
172
  } catch (error3) {
171
173
  lastError = error3;
172
- if ((_a = options.signal) == null ? void 0 : _a.aborted) throw error3;
174
+ if ((_a = options.signal) == null ? void 0 : _a.aborted)
175
+ throw error3;
173
176
  if (onError) {
174
177
  onError(error3, attempt);
175
178
  } else {
@@ -193,7 +196,8 @@ function parseStreamedResponse(identifier, paragraph, toolCallAccumulators, allo
193
196
  const functionCalls = [];
194
197
  for (let i = 0; i < toolCallAccumulators.length; i++) {
195
198
  const acc = toolCallAccumulators[i];
196
- if (!acc.name || !acc.arguments) continue;
199
+ if (!acc.name || !acc.arguments)
200
+ continue;
197
201
  if (allowedFunctionNames && !allowedFunctionNames.has(acc.name)) {
198
202
  throw new Error(
199
203
  `Stream error: received function call with unknown name: ${acc.name}`
@@ -332,7 +336,8 @@ function buildOpenAIRequestConfig(identifier, model, config) {
332
336
  };
333
337
  }
334
338
  function filterOpenAICompatReasoningDetails(details) {
335
- if (!Array.isArray(details)) return details || void 0;
339
+ if (!Array.isArray(details))
340
+ return details || void 0;
336
341
  const blocks = details.filter(
337
342
  (block) => typeof (block == null ? void 0 : block.type) === "string" && block.type.startsWith("reasoning.")
338
343
  );
@@ -403,11 +408,13 @@ async function prepareOpenAIPayload(identifier, payload) {
403
408
  };
404
409
  });
405
410
  }
406
- if (message.reasoning) outMessage.reasoning = message.reasoning;
411
+ if (message.reasoning)
412
+ outMessage.reasoning = message.reasoning;
407
413
  const reasoningDetails = filterOpenAICompatReasoningDetails(
408
414
  message.reasoningDetails
409
415
  );
410
- if (reasoningDetails) outMessage.reasoning_details = reasoningDetails;
416
+ if (reasoningDetails)
417
+ outMessage.reasoning_details = reasoningDetails;
411
418
  preparedPayload.messages.push(outMessage);
412
419
  }
413
420
  return preparedPayload;
@@ -469,7 +476,8 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
469
476
  }
470
477
  const jsonStrings = chunk.split(/^data: /gm);
471
478
  for (const jsonString of jsonStrings) {
472
- if (!jsonString) continue;
479
+ if (!jsonString)
480
+ continue;
473
481
  if (jsonString.includes("[DONE]")) {
474
482
  clearTimeout(overallTimeout);
475
483
  return parseStreamedResponse(
@@ -507,7 +515,8 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
507
515
  while (toolCallAccumulators.length <= idx) {
508
516
  toolCallAccumulators.push({ name: "", arguments: "" });
509
517
  }
510
- if (toolCall.id) toolCallAccumulators[idx].id = toolCall.id;
518
+ if (toolCall.id)
519
+ toolCallAccumulators[idx].id = toolCall.id;
511
520
  if ((_e = toolCall.function) == null ? void 0 : _e.name)
512
521
  toolCallAccumulators[idx].name += toolCall.function.name;
513
522
  if ((_f = toolCall.function) == null ? void 0 : _f.arguments)
@@ -515,9 +524,11 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
515
524
  }
516
525
  }
517
526
  const text = (_h = (_g = json.choices[0]) == null ? void 0 : _g.delta) == null ? void 0 : _h.content;
518
- if (text) paragraph += text;
527
+ if (text)
528
+ paragraph += text;
519
529
  const reasoningDelta = (_j = (_i = json.choices[0]) == null ? void 0 : _i.delta) == null ? void 0 : _j.reasoning;
520
- if (reasoningDelta) reasoning += reasoningDelta;
530
+ if (reasoningDelta)
531
+ reasoning += reasoningDelta;
521
532
  }
522
533
  }
523
534
  }
@@ -662,7 +673,8 @@ function jigAnthropicMessages(messages) {
662
673
  ];
663
674
  }
664
675
  jiggedMessages = jiggedMessages.reduce((acc, message) => {
665
- if (acc.length === 0) return [message];
676
+ if (acc.length === 0)
677
+ return [message];
666
678
  const lastMessage = acc[acc.length - 1];
667
679
  if (lastMessage.role === message.role) {
668
680
  const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
@@ -916,7 +928,8 @@ function jigGoogleMessages(messages) {
916
928
  ];
917
929
  }
918
930
  jiggedMessages = jiggedMessages.reduce((acc, message) => {
919
- if (acc.length === 0) return [message];
931
+ if (acc.length === 0)
932
+ return [message];
920
933
  const lastMessage = acc[acc.length - 1];
921
934
  if (lastMessage.role === message.role) {
922
935
  lastMessage.parts = [...lastMessage.parts, ...message.parts];
@@ -954,7 +967,8 @@ async function prepareGoogleAIPayload(_identifier, payload) {
954
967
  const toolNameById = /* @__PURE__ */ new Map();
955
968
  for (const m of payload.messages) {
956
969
  for (const fc of m.functionCalls || []) {
957
- if (fc.id) toolNameById.set(fc.id, fc.name);
970
+ if (fc.id)
971
+ toolNameById.set(fc.id, fc.name);
958
972
  }
959
973
  }
960
974
  for (const message of payload.messages) {
@@ -1031,7 +1045,8 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
1031
1045
  contents,
1032
1046
  generationConfig: { responseModalities: ["TEXT"] }
1033
1047
  };
1034
- if (payload.tools) requestBody.tools = [payload.tools];
1048
+ if (payload.tools)
1049
+ requestBody.tools = [payload.tools];
1035
1050
  if (payload.tools && payload.toolConfig) {
1036
1051
  requestBody.toolConfig = payload.toolConfig;
1037
1052
  }
@@ -1089,7 +1104,8 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
1089
1104
  });
1090
1105
  continue;
1091
1106
  }
1092
- if (part.text) text += part.text;
1107
+ if (part.text)
1108
+ text += part.text;
1093
1109
  if ((_m = part.inlineData) == null ? void 0 : _m.data) {
1094
1110
  files.push({ mimeType: "image/png", data: part.inlineData.data });
1095
1111
  }
@@ -1166,15 +1182,21 @@ async function callGoogleAIWithRetries(id, payload, retries = 5, requestTimeoutM
1166
1182
  finishReason: error2.finishReason,
1167
1183
  modelVersion: error2.modelVersion
1168
1184
  };
1169
- if (error2.safetyRatings) errorDetails.safetyRatings = error2.safetyRatings;
1170
- if (error2.usageMetadata) errorDetails.usageMetadata = error2.usageMetadata;
1185
+ if (error2.safetyRatings)
1186
+ errorDetails.safetyRatings = error2.safetyRatings;
1187
+ if (error2.usageMetadata)
1188
+ errorDetails.usageMetadata = error2.usageMetadata;
1171
1189
  if (error2.promptFeedback)
1172
1190
  errorDetails.promptFeedback = error2.promptFeedback;
1173
- if (error2.status) errorDetails.httpStatus = error2.status;
1174
- if (error2.code) errorDetails.errorCode = error2.code;
1175
- if (error2.details) errorDetails.errorDetails = error2.details;
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;
1176
1197
  const fileUris = payload.messages.flatMap((m) => m.parts).filter((p) => "fileData" in p).map((p) => p.fileData.fileUri);
1177
- if (fileUris.length) errorDetails.fileUris = fileUris;
1198
+ if (fileUris.length)
1199
+ errorDetails.fileUris = fileUris;
1178
1200
  logger_default.error(
1179
1201
  id,
1180
1202
  `Retry #${attempt} error: ${error2.message}`,
@@ -1254,13 +1276,16 @@ function prepareOpenAICompatMessages(messages) {
1254
1276
  }
1255
1277
  };
1256
1278
  });
1257
- if (!message.content) outMessage.content = null;
1279
+ if (!message.content)
1280
+ outMessage.content = null;
1258
1281
  }
1259
- if (message.reasoning) outMessage.reasoning = message.reasoning;
1282
+ if (message.reasoning)
1283
+ outMessage.reasoning = message.reasoning;
1260
1284
  const reasoningDetails = filterOpenAICompatReasoningDetails(
1261
1285
  message.reasoningDetails
1262
1286
  );
1263
- if (reasoningDetails) outMessage.reasoning_details = reasoningDetails;
1287
+ if (reasoningDetails)
1288
+ outMessage.reasoning_details = reasoningDetails;
1264
1289
  out.push(outMessage);
1265
1290
  }
1266
1291
  return out;
@@ -1403,53 +1428,33 @@ function parseDsmlToolCalls(content) {
1403
1428
  let last = -1;
1404
1429
  let tag;
1405
1430
  while ((tag = DSML_ANY_TAG_RE.exec(content)) !== null) {
1406
- if (first === -1) first = tag.index;
1431
+ if (first === -1)
1432
+ first = tag.index;
1407
1433
  last = tag.index + tag[0].length;
1408
1434
  }
1409
1435
  const remaining = first === -1 ? content : (content.slice(0, first) + content.slice(last)).trim();
1410
1436
  return { calls, remainingContent: remaining.length ? remaining : null };
1411
1437
  }
1412
- async function callOpenRouter(id, payload, requestTimeoutMs = 12e4, signal) {
1413
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1414
- const response = await withRequestDeadline(
1415
- "OpenRouter",
1416
- requestTimeoutMs,
1417
- signal,
1418
- (mergedSignal) => import_axios.default.post(
1419
- // Override point for tests (deadline behavior needs a local server).
1420
- `${process.env.OPENROUTER_BASE_URL || "https://openrouter.ai"}/api/v1/chat/completions`,
1421
- payload,
1422
- {
1423
- headers: {
1424
- "content-type": "application/json",
1425
- Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`
1426
- },
1427
- timeout: requestTimeoutMs,
1428
- signal: mergedSignal
1429
- }
1430
- )
1431
- );
1432
- if (response.data.error) {
1433
- logger_default.error(id, "OpenRouter error:", response.data.error);
1434
- throw new Error(`OpenRouter error: ${response.data.error.message}`);
1435
- }
1436
- const answer = (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message;
1437
- if (!answer) {
1438
- logger_default.error(id, "Missing answer in OpenRouter API response:", response.data);
1439
- throw new Error("Missing answer in OpenRouter API");
1440
- }
1438
+ var OPENROUTER_STREAM_TIMEOUT_MS = 6e5;
1439
+ var OPENROUTER_NONSTREAM_TIMEOUT_MS = 18e4;
1440
+ function openRouterEndpoint() {
1441
+ return `${process.env.OPENROUTER_BASE_URL || "https://openrouter.ai"}/api/v1/chat/completions`;
1442
+ }
1443
+ function finalizeOpenRouterMessage(id, raw) {
1444
+ var _a, _b, _c, _d, _e;
1441
1445
  const functionCalls = [];
1442
- if ((_c = answer.tool_calls) == null ? void 0 : _c.length) {
1443
- for (let i = 0; i < answer.tool_calls.length; i++) {
1444
- const tc = answer.tool_calls[i];
1445
- functionCalls.push({
1446
- id: (_d = tc.id) != null ? _d : `call_${i}`,
1447
- name: tc.function.name,
1448
- arguments: JSON.parse(tc.function.arguments)
1449
- });
1450
- }
1446
+ for (let i = 0; i < raw.toolCalls.length; i++) {
1447
+ const tc = raw.toolCalls[i];
1448
+ if (!tc.name)
1449
+ continue;
1450
+ functionCalls.push({
1451
+ id: (_a = tc.id) != null ? _a : `call_${i}`,
1452
+ name: tc.name,
1453
+ // Streamed no-arg calls can close with an empty fragment; treat as {}.
1454
+ arguments: tc.argumentsJson.trim() ? JSON.parse(tc.argumentsJson) : {}
1455
+ });
1451
1456
  }
1452
- let content = (_e = answer.content) != null ? _e : null;
1457
+ let content = raw.content;
1453
1458
  if (!functionCalls.length && content && DSML_ENVELOPE_RE.test(content)) {
1454
1459
  const { calls, remainingContent } = parseDsmlToolCalls(content);
1455
1460
  if (calls.length) {
@@ -1459,11 +1464,7 @@ async function callOpenRouter(id, payload, requestTimeoutMs = 12e4, signal) {
1459
1464
  }
1460
1465
  const hasUnparsedDsml = !!content && DSML_DELIMITER_RE.test(content);
1461
1466
  if (!functionCalls.length && (!content || hasUnparsedDsml)) {
1462
- logger_default.error(
1463
- id,
1464
- "OpenRouter: empty or unparseable completion:",
1465
- JSON.stringify(response.data)
1466
- );
1467
+ logger_default.error(id, "OpenRouter: empty or unparseable completion:", raw.forLog());
1467
1468
  throw new Error(
1468
1469
  "OpenRouter: received message without usable content or function_call"
1469
1470
  );
@@ -1474,24 +1475,319 @@ async function callOpenRouter(id, payload, requestTimeoutMs = 12e4, signal) {
1474
1475
  function_call: functionCalls[0] || null,
1475
1476
  function_calls: functionCalls,
1476
1477
  files: [],
1477
- reasoning: (_f = answer.reasoning) != null ? _f : void 0,
1478
- reasoningDetails: (_g = answer.reasoning_details) != null ? _g : void 0,
1478
+ reasoning: raw.reasoning || void 0,
1479
+ reasoningDetails: (_b = raw.reasoningDetails) != null ? _b : void 0,
1479
1480
  // The upstream provider OpenRouter routed to (e.g. "Baidu") — finer-grained
1480
1481
  // than the "openrouter" stamp callWithRetries would apply.
1481
- provider: (_h = response.data.provider) != null ? _h : void 0,
1482
- usage: response.data.usage ? {
1483
- prompt_tokens: response.data.usage.prompt_tokens,
1484
- completion_tokens: response.data.usage.completion_tokens,
1485
- total_tokens: response.data.usage.total_tokens,
1486
- cached_tokens: (_j = (_i = response.data.usage.prompt_tokens_details) == null ? void 0 : _i.cached_tokens) != null ? _j : 0
1482
+ provider: (_c = raw.provider) != null ? _c : void 0,
1483
+ usage: raw.usage ? {
1484
+ prompt_tokens: raw.usage.prompt_tokens,
1485
+ completion_tokens: raw.usage.completion_tokens,
1486
+ total_tokens: raw.usage.total_tokens,
1487
+ cached_tokens: (_e = (_d = raw.usage.prompt_tokens_details) == null ? void 0 : _d.cached_tokens) != null ? _e : 0
1487
1488
  } : null
1488
1489
  };
1489
1490
  }
1490
- async function callOpenRouterWithRetries(id, payload, retries = 5, requestTimeoutMs = 12e4, signal) {
1491
+ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_STREAM_TIMEOUT_MS, chunkTimeoutMs = 15e3, signal) {
1492
+ var _a, _b, _c, _d, _e, _f, _g;
1493
+ const controller = new AbortController();
1494
+ let abortReason = null;
1495
+ const abortWith = (reason) => {
1496
+ abortReason = reason;
1497
+ controller.abort();
1498
+ };
1499
+ const unref = (t) => {
1500
+ if (typeof t === "object" && "unref" in t)
1501
+ t.unref();
1502
+ return t;
1503
+ };
1504
+ const totalTimer = unref(
1505
+ setTimeout(
1506
+ () => abortWith(
1507
+ `OpenRouter stream exceeded total deadline of ${streamTimeoutMs}ms`
1508
+ ),
1509
+ streamTimeoutMs
1510
+ )
1511
+ );
1512
+ let stallTimer;
1513
+ const armStallTimer = () => {
1514
+ clearTimeout(stallTimer);
1515
+ stallTimer = unref(
1516
+ setTimeout(
1517
+ () => abortWith(
1518
+ `OpenRouter stream stalled: no useful chunk for ${chunkTimeoutMs}ms`
1519
+ ),
1520
+ chunkTimeoutMs
1521
+ )
1522
+ );
1523
+ };
1524
+ let paragraph = "";
1525
+ let reasoning = "";
1526
+ const reasoningDetails = [];
1527
+ const toolCalls = [];
1528
+ let provider;
1529
+ let usage = null;
1530
+ let finishReason = null;
1531
+ let sawDone = false;
1532
+ let dataChunks = 0;
1533
+ try {
1534
+ armStallTimer();
1535
+ const response = await fetch(openRouterEndpoint(), {
1536
+ method: "POST",
1537
+ headers: {
1538
+ "content-type": "application/json",
1539
+ Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`
1540
+ },
1541
+ body: JSON.stringify({ ...payload, stream: true, usage: { include: true } }),
1542
+ signal: signal ? anySignal([controller.signal, signal]) : controller.signal
1543
+ });
1544
+ if (!response.ok) {
1545
+ let data;
1546
+ try {
1547
+ data = await response.json();
1548
+ } catch (e) {
1549
+ data = void 0;
1550
+ }
1551
+ logger_default.error(id, `OpenRouter stream HTTP ${response.status}:`, data);
1552
+ const error2 = new Error(
1553
+ `OpenRouter error: ${((_a = data == null ? void 0 : data.error) == null ? void 0 : _a.message) || `HTTP ${response.status}`}`
1554
+ );
1555
+ error2.response = { status: response.status, data };
1556
+ throw error2;
1557
+ }
1558
+ if ((_b = response.headers.get("content-type")) == null ? void 0 : _b.includes("application/json")) {
1559
+ return parseOpenRouterBody(id, await response.json());
1560
+ }
1561
+ if (!response.body) {
1562
+ throw new Error("OpenRouter stream error: no response body");
1563
+ }
1564
+ const reader = response.body.getReader();
1565
+ const decoder = new TextDecoder();
1566
+ let lineBuffer = "";
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;
1589
+ }
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;
1609
+ }
1610
+ if (json.provider)
1611
+ provider = json.provider;
1612
+ let useful = false;
1613
+ if (json.usage) {
1614
+ usage = json.usage;
1615
+ useful = true;
1616
+ }
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;
1645
+ }
1646
+ }
1647
+ if (choice.finish_reason) {
1648
+ finishReason = choice.finish_reason;
1649
+ useful = true;
1650
+ }
1651
+ }
1652
+ if (useful)
1653
+ armStallTimer();
1654
+ }
1655
+ }
1656
+ if (sawDone)
1657
+ reader.cancel().catch(() => {
1658
+ });
1659
+ if (!sawDone && !finishReason) {
1660
+ logger_default.error(
1661
+ id,
1662
+ `OpenRouter stream ended prematurely after ${dataChunks} data chunks`
1663
+ );
1664
+ throw new Error("OpenRouter stream error: ended prematurely");
1665
+ }
1666
+ return finalizeOpenRouterMessage(id, {
1667
+ content: paragraph || null,
1668
+ toolCalls,
1669
+ reasoning,
1670
+ reasoningDetails: reasoningDetails.length ? reasoningDetails : void 0,
1671
+ provider,
1672
+ usage,
1673
+ forLog: () => JSON.stringify({
1674
+ finishReason,
1675
+ provider,
1676
+ usage,
1677
+ paragraph: paragraph.slice(0, 500),
1678
+ reasoningChars: reasoning.length,
1679
+ toolCalls
1680
+ })
1681
+ });
1682
+ } catch (error2) {
1683
+ if (abortReason && !(signal == null ? void 0 : signal.aborted)) {
1684
+ logger_default.error(id, abortReason);
1685
+ throw new Error(abortReason);
1686
+ }
1687
+ throw error2;
1688
+ } finally {
1689
+ clearTimeout(totalTimer);
1690
+ clearTimeout(stallTimer);
1691
+ }
1692
+ }
1693
+ function parseOpenRouterBody(id, data) {
1694
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1695
+ if (data.error) {
1696
+ logger_default.error(id, "OpenRouter error:", data.error);
1697
+ const error2 = new Error(`OpenRouter error: ${data.error.message}`);
1698
+ error2.data = data.error;
1699
+ throw error2;
1700
+ }
1701
+ const answer = (_b = (_a = data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message;
1702
+ if (!answer) {
1703
+ logger_default.error(id, "Missing answer in OpenRouter API response:", data);
1704
+ throw new Error("Missing answer in OpenRouter API");
1705
+ }
1706
+ return finalizeOpenRouterMessage(id, {
1707
+ content: (_c = answer.content) != null ? _c : null,
1708
+ toolCalls: ((_d = answer.tool_calls) != null ? _d : []).map((tc) => ({
1709
+ id: tc.id,
1710
+ name: tc.function.name,
1711
+ argumentsJson: tc.function.arguments
1712
+ })),
1713
+ reasoning: (_e = answer.reasoning) != null ? _e : void 0,
1714
+ reasoningDetails: (_f = answer.reasoning_details) != null ? _f : void 0,
1715
+ provider: (_g = data.provider) != null ? _g : void 0,
1716
+ usage: (_h = data.usage) != null ? _h : null,
1717
+ forLog: () => JSON.stringify(data)
1718
+ });
1719
+ }
1720
+ async function callOpenRouterNonStreaming(id, payload, requestTimeoutMs = OPENROUTER_NONSTREAM_TIMEOUT_MS, signal) {
1721
+ const response = await withRequestDeadline(
1722
+ "OpenRouter",
1723
+ requestTimeoutMs,
1724
+ signal,
1725
+ (mergedSignal) => import_axios.default.post(openRouterEndpoint(), payload, {
1726
+ headers: {
1727
+ "content-type": "application/json",
1728
+ Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`
1729
+ },
1730
+ timeout: requestTimeoutMs,
1731
+ signal: mergedSignal
1732
+ })
1733
+ );
1734
+ return parseOpenRouterBody(id, response.data);
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
+ }
1756
+ async function callOpenRouterWithRetries(id, payload, retries = 5, options, signal) {
1757
+ const evicted = [];
1491
1758
  return withRetries(
1492
1759
  id,
1493
1760
  "OpenRouter",
1494
- () => callOpenRouter(id, payload, requestTimeoutMs, signal),
1761
+ () => (options.streaming ? callOpenRouterStream(
1762
+ id,
1763
+ payload,
1764
+ options.streamTimeoutMs,
1765
+ options.chunkTimeoutMs,
1766
+ signal
1767
+ ) : callOpenRouterNonStreaming(
1768
+ id,
1769
+ payload,
1770
+ options.requestTimeoutMs,
1771
+ signal
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
+ }),
1495
1791
  { retries, signal }
1496
1792
  );
1497
1793
  }
@@ -1533,7 +1829,7 @@ function parseModelString(model) {
1533
1829
  );
1534
1830
  }
1535
1831
  async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeoutMs = 15e3) {
1536
- var _a, _b, _c;
1832
+ var _a, _b, _c, _d, _e, _f;
1537
1833
  try {
1538
1834
  const { provider, modelId } = parseModelString(aiPayload.model);
1539
1835
  const routingPayload = { ...aiPayload, model: modelId };
@@ -1585,15 +1881,21 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
1585
1881
  id,
1586
1882
  prepareOpenRouterPayload(routingPayload),
1587
1883
  retries,
1588
- requestTimeoutMs,
1884
+ {
1885
+ streaming: (_b = aiPayload.streaming) != null ? _b : true,
1886
+ streamTimeoutMs: (_c = aiPayload.streamTimeoutMs) != null ? _c : OPENROUTER_STREAM_TIMEOUT_MS,
1887
+ requestTimeoutMs: (_d = aiPayload.requestTimeoutMs) != null ? _d : OPENROUTER_NONSTREAM_TIMEOUT_MS,
1888
+ chunkTimeoutMs
1889
+ },
1589
1890
  signal
1590
1891
  );
1591
1892
  break;
1592
1893
  }
1593
- (_b = result.provider) != null ? _b : result.provider = provider;
1894
+ (_e = result.provider) != null ? _e : result.provider = provider;
1594
1895
  return result;
1595
1896
  } catch (error2) {
1596
- if ((_c = aiPayload.signal) == null ? void 0 : _c.aborted) throw error2;
1897
+ if ((_f = aiPayload.signal) == null ? void 0 : _f.aborted)
1898
+ throw error2;
1597
1899
  if (aiPayload.fallbackModel) {
1598
1900
  logger_default.error(
1599
1901
  id,
@@ -1624,6 +1926,8 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
1624
1926
  GPTModel,
1625
1927
  GeminiModel,
1626
1928
  GroqModel,
1929
+ OPENROUTER_NONSTREAM_TIMEOUT_MS,
1930
+ OPENROUTER_STREAM_TIMEOUT_MS,
1627
1931
  OpenRouterModel,
1628
1932
  callWithRetries,
1629
1933
  parseModelString