190proof 1.0.108 → 1.0.109

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.mjs CHANGED
@@ -1377,47 +1377,25 @@ function parseDsmlToolCalls(content) {
1377
1377
  const remaining = first === -1 ? content : (content.slice(0, first) + content.slice(last)).trim();
1378
1378
  return { calls, remainingContent: remaining.length ? remaining : null };
1379
1379
  }
1380
- async function callOpenRouter(id, payload, requestTimeoutMs = 12e4, signal) {
1381
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1382
- const response = await withRequestDeadline(
1383
- "OpenRouter",
1384
- requestTimeoutMs,
1385
- signal,
1386
- (mergedSignal) => axios.post(
1387
- // Override point for tests (deadline behavior needs a local server).
1388
- `${process.env.OPENROUTER_BASE_URL || "https://openrouter.ai"}/api/v1/chat/completions`,
1389
- payload,
1390
- {
1391
- headers: {
1392
- "content-type": "application/json",
1393
- Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`
1394
- },
1395
- timeout: requestTimeoutMs,
1396
- signal: mergedSignal
1397
- }
1398
- )
1399
- );
1400
- if (response.data.error) {
1401
- logger_default.error(id, "OpenRouter error:", response.data.error);
1402
- throw new Error(`OpenRouter error: ${response.data.error.message}`);
1403
- }
1404
- const answer = (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message;
1405
- if (!answer) {
1406
- logger_default.error(id, "Missing answer in OpenRouter API response:", response.data);
1407
- throw new Error("Missing answer in OpenRouter API");
1408
- }
1380
+ var OPENROUTER_STREAM_TIMEOUT_MS = 6e5;
1381
+ var OPENROUTER_NONSTREAM_TIMEOUT_MS = 18e4;
1382
+ function openRouterEndpoint() {
1383
+ return `${process.env.OPENROUTER_BASE_URL || "https://openrouter.ai"}/api/v1/chat/completions`;
1384
+ }
1385
+ function finalizeOpenRouterMessage(id, raw) {
1386
+ var _a, _b, _c, _d, _e;
1409
1387
  const functionCalls = [];
1410
- if ((_c = answer.tool_calls) == null ? void 0 : _c.length) {
1411
- for (let i = 0; i < answer.tool_calls.length; i++) {
1412
- const tc = answer.tool_calls[i];
1413
- functionCalls.push({
1414
- id: (_d = tc.id) != null ? _d : `call_${i}`,
1415
- name: tc.function.name,
1416
- arguments: JSON.parse(tc.function.arguments)
1417
- });
1418
- }
1388
+ for (let i = 0; i < raw.toolCalls.length; i++) {
1389
+ const tc = raw.toolCalls[i];
1390
+ if (!tc.name) continue;
1391
+ functionCalls.push({
1392
+ id: (_a = tc.id) != null ? _a : `call_${i}`,
1393
+ name: tc.name,
1394
+ // Streamed no-arg calls can close with an empty fragment; treat as {}.
1395
+ arguments: tc.argumentsJson.trim() ? JSON.parse(tc.argumentsJson) : {}
1396
+ });
1419
1397
  }
1420
- let content = (_e = answer.content) != null ? _e : null;
1398
+ let content = raw.content;
1421
1399
  if (!functionCalls.length && content && DSML_ENVELOPE_RE.test(content)) {
1422
1400
  const { calls, remainingContent } = parseDsmlToolCalls(content);
1423
1401
  if (calls.length) {
@@ -1427,11 +1405,7 @@ async function callOpenRouter(id, payload, requestTimeoutMs = 12e4, signal) {
1427
1405
  }
1428
1406
  const hasUnparsedDsml = !!content && DSML_DELIMITER_RE.test(content);
1429
1407
  if (!functionCalls.length && (!content || hasUnparsedDsml)) {
1430
- logger_default.error(
1431
- id,
1432
- "OpenRouter: empty or unparseable completion:",
1433
- JSON.stringify(response.data)
1434
- );
1408
+ logger_default.error(id, "OpenRouter: empty or unparseable completion:", raw.forLog());
1435
1409
  throw new Error(
1436
1410
  "OpenRouter: received message without usable content or function_call"
1437
1411
  );
@@ -1442,24 +1416,267 @@ async function callOpenRouter(id, payload, requestTimeoutMs = 12e4, signal) {
1442
1416
  function_call: functionCalls[0] || null,
1443
1417
  function_calls: functionCalls,
1444
1418
  files: [],
1445
- reasoning: (_f = answer.reasoning) != null ? _f : void 0,
1446
- reasoningDetails: (_g = answer.reasoning_details) != null ? _g : void 0,
1419
+ reasoning: raw.reasoning || void 0,
1420
+ reasoningDetails: (_b = raw.reasoningDetails) != null ? _b : void 0,
1447
1421
  // The upstream provider OpenRouter routed to (e.g. "Baidu") — finer-grained
1448
1422
  // than the "openrouter" stamp callWithRetries would apply.
1449
- provider: (_h = response.data.provider) != null ? _h : void 0,
1450
- usage: response.data.usage ? {
1451
- prompt_tokens: response.data.usage.prompt_tokens,
1452
- completion_tokens: response.data.usage.completion_tokens,
1453
- total_tokens: response.data.usage.total_tokens,
1454
- cached_tokens: (_j = (_i = response.data.usage.prompt_tokens_details) == null ? void 0 : _i.cached_tokens) != null ? _j : 0
1423
+ provider: (_c = raw.provider) != null ? _c : void 0,
1424
+ usage: raw.usage ? {
1425
+ prompt_tokens: raw.usage.prompt_tokens,
1426
+ completion_tokens: raw.usage.completion_tokens,
1427
+ total_tokens: raw.usage.total_tokens,
1428
+ cached_tokens: (_e = (_d = raw.usage.prompt_tokens_details) == null ? void 0 : _d.cached_tokens) != null ? _e : 0
1455
1429
  } : null
1456
1430
  };
1457
1431
  }
1458
- async function callOpenRouterWithRetries(id, payload, retries = 5, requestTimeoutMs = 12e4, signal) {
1432
+ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_STREAM_TIMEOUT_MS, chunkTimeoutMs = 15e3, signal) {
1433
+ var _a, _b, _c, _d, _e, _f, _g;
1434
+ const controller = new AbortController();
1435
+ let abortReason = null;
1436
+ const abortWith = (reason) => {
1437
+ abortReason = reason;
1438
+ controller.abort();
1439
+ };
1440
+ const unref = (t) => {
1441
+ if (typeof t === "object" && "unref" in t) t.unref();
1442
+ return t;
1443
+ };
1444
+ const totalTimer = unref(
1445
+ setTimeout(
1446
+ () => abortWith(
1447
+ `OpenRouter stream exceeded total deadline of ${streamTimeoutMs}ms`
1448
+ ),
1449
+ streamTimeoutMs
1450
+ )
1451
+ );
1452
+ let stallTimer;
1453
+ const armStallTimer = () => {
1454
+ clearTimeout(stallTimer);
1455
+ stallTimer = unref(
1456
+ setTimeout(
1457
+ () => abortWith(
1458
+ `OpenRouter stream stalled: no useful chunk for ${chunkTimeoutMs}ms`
1459
+ ),
1460
+ chunkTimeoutMs
1461
+ )
1462
+ );
1463
+ };
1464
+ let paragraph = "";
1465
+ let reasoning = "";
1466
+ const reasoningDetails = [];
1467
+ const toolCalls = [];
1468
+ let provider;
1469
+ let usage = null;
1470
+ let finishReason = null;
1471
+ let sawDone = false;
1472
+ let dataChunks = 0;
1473
+ try {
1474
+ armStallTimer();
1475
+ const response = await fetch(openRouterEndpoint(), {
1476
+ method: "POST",
1477
+ headers: {
1478
+ "content-type": "application/json",
1479
+ Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`
1480
+ },
1481
+ body: JSON.stringify({ ...payload, stream: true, usage: { include: true } }),
1482
+ signal: signal ? anySignal([controller.signal, signal]) : controller.signal
1483
+ });
1484
+ if (!response.ok) {
1485
+ let data;
1486
+ try {
1487
+ data = await response.json();
1488
+ } catch (e) {
1489
+ data = void 0;
1490
+ }
1491
+ logger_default.error(id, `OpenRouter stream HTTP ${response.status}:`, data);
1492
+ const error2 = new Error(
1493
+ `OpenRouter error: ${((_a = data == null ? void 0 : data.error) == null ? void 0 : _a.message) || `HTTP ${response.status}`}`
1494
+ );
1495
+ error2.response = { status: response.status, data };
1496
+ throw error2;
1497
+ }
1498
+ if ((_b = response.headers.get("content-type")) == null ? void 0 : _b.includes("application/json")) {
1499
+ return parseOpenRouterBody(id, await response.json());
1500
+ }
1501
+ if (!response.body) {
1502
+ throw new Error("OpenRouter stream error: no response body");
1503
+ }
1504
+ const reader = response.body.getReader();
1505
+ const decoder = new TextDecoder();
1506
+ let lineBuffer = "";
1507
+ outer: while (true) {
1508
+ const { done, value } = await reader.read();
1509
+ if (done) break;
1510
+ lineBuffer += decoder.decode(value, { stream: true });
1511
+ let newlineIdx;
1512
+ while ((newlineIdx = lineBuffer.indexOf("\n")) !== -1) {
1513
+ let line = lineBuffer.slice(0, newlineIdx);
1514
+ lineBuffer = lineBuffer.slice(newlineIdx + 1);
1515
+ if (line.endsWith("\r")) line = line.slice(0, -1);
1516
+ if (!line) continue;
1517
+ if (line.startsWith(":")) continue;
1518
+ if (!line.startsWith("data:")) continue;
1519
+ const dataStr = line.slice(5).trimStart();
1520
+ if (dataStr === "[DONE]") {
1521
+ sawDone = true;
1522
+ break outer;
1523
+ }
1524
+ let json;
1525
+ try {
1526
+ json = JSON.parse(dataStr);
1527
+ } catch (e) {
1528
+ logger_default.error(
1529
+ id,
1530
+ "OpenRouter stream: unparseable data line:",
1531
+ dataStr.slice(0, 200)
1532
+ );
1533
+ continue;
1534
+ }
1535
+ dataChunks++;
1536
+ if (json.error) {
1537
+ logger_default.error(id, "OpenRouter stream error event:", json.error);
1538
+ const error2 = new Error(
1539
+ `OpenRouter error: ${json.error.message}`
1540
+ );
1541
+ error2.data = json.error;
1542
+ throw error2;
1543
+ }
1544
+ if (json.provider) provider = json.provider;
1545
+ let useful = false;
1546
+ if (json.usage) {
1547
+ usage = json.usage;
1548
+ useful = true;
1549
+ }
1550
+ const choice = (_c = json.choices) == null ? void 0 : _c[0];
1551
+ if (choice) {
1552
+ const delta = (_d = choice.delta) != null ? _d : {};
1553
+ if (delta.content) {
1554
+ paragraph += delta.content;
1555
+ useful = true;
1556
+ }
1557
+ if (delta.reasoning) {
1558
+ reasoning += delta.reasoning;
1559
+ useful = true;
1560
+ }
1561
+ if (Array.isArray(delta.reasoning_details) && delta.reasoning_details.length) {
1562
+ reasoningDetails.push(...delta.reasoning_details);
1563
+ useful = true;
1564
+ }
1565
+ if (Array.isArray(delta.tool_calls)) {
1566
+ for (const toolCall of delta.tool_calls) {
1567
+ const idx = (_e = toolCall.index) != null ? _e : 0;
1568
+ while (toolCalls.length <= idx) {
1569
+ toolCalls.push({ name: "", argumentsJson: "" });
1570
+ }
1571
+ if (toolCall.id) toolCalls[idx].id = toolCall.id;
1572
+ if ((_f = toolCall.function) == null ? void 0 : _f.name)
1573
+ toolCalls[idx].name += toolCall.function.name;
1574
+ if ((_g = toolCall.function) == null ? void 0 : _g.arguments)
1575
+ toolCalls[idx].argumentsJson += toolCall.function.arguments;
1576
+ useful = true;
1577
+ }
1578
+ }
1579
+ if (choice.finish_reason) {
1580
+ finishReason = choice.finish_reason;
1581
+ useful = true;
1582
+ }
1583
+ }
1584
+ if (useful) armStallTimer();
1585
+ }
1586
+ }
1587
+ if (sawDone) reader.cancel().catch(() => {
1588
+ });
1589
+ if (!sawDone && !finishReason) {
1590
+ logger_default.error(
1591
+ id,
1592
+ `OpenRouter stream ended prematurely after ${dataChunks} data chunks`
1593
+ );
1594
+ throw new Error("OpenRouter stream error: ended prematurely");
1595
+ }
1596
+ return finalizeOpenRouterMessage(id, {
1597
+ content: paragraph || null,
1598
+ toolCalls,
1599
+ reasoning,
1600
+ reasoningDetails: reasoningDetails.length ? reasoningDetails : void 0,
1601
+ provider,
1602
+ usage,
1603
+ forLog: () => JSON.stringify({
1604
+ finishReason,
1605
+ provider,
1606
+ usage,
1607
+ paragraph: paragraph.slice(0, 500),
1608
+ reasoningChars: reasoning.length,
1609
+ toolCalls
1610
+ })
1611
+ });
1612
+ } catch (error2) {
1613
+ if (abortReason && !(signal == null ? void 0 : signal.aborted)) {
1614
+ logger_default.error(id, abortReason);
1615
+ throw new Error(abortReason);
1616
+ }
1617
+ throw error2;
1618
+ } finally {
1619
+ clearTimeout(totalTimer);
1620
+ clearTimeout(stallTimer);
1621
+ }
1622
+ }
1623
+ function parseOpenRouterBody(id, data) {
1624
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1625
+ if (data.error) {
1626
+ logger_default.error(id, "OpenRouter error:", data.error);
1627
+ throw new Error(`OpenRouter error: ${data.error.message}`);
1628
+ }
1629
+ const answer = (_b = (_a = data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message;
1630
+ if (!answer) {
1631
+ logger_default.error(id, "Missing answer in OpenRouter API response:", data);
1632
+ throw new Error("Missing answer in OpenRouter API");
1633
+ }
1634
+ return finalizeOpenRouterMessage(id, {
1635
+ content: (_c = answer.content) != null ? _c : null,
1636
+ toolCalls: ((_d = answer.tool_calls) != null ? _d : []).map((tc) => ({
1637
+ id: tc.id,
1638
+ name: tc.function.name,
1639
+ argumentsJson: tc.function.arguments
1640
+ })),
1641
+ reasoning: (_e = answer.reasoning) != null ? _e : void 0,
1642
+ reasoningDetails: (_f = answer.reasoning_details) != null ? _f : void 0,
1643
+ provider: (_g = data.provider) != null ? _g : void 0,
1644
+ usage: (_h = data.usage) != null ? _h : null,
1645
+ forLog: () => JSON.stringify(data)
1646
+ });
1647
+ }
1648
+ async function callOpenRouterNonStreaming(id, payload, requestTimeoutMs = OPENROUTER_NONSTREAM_TIMEOUT_MS, signal) {
1649
+ const response = await withRequestDeadline(
1650
+ "OpenRouter",
1651
+ requestTimeoutMs,
1652
+ signal,
1653
+ (mergedSignal) => axios.post(openRouterEndpoint(), payload, {
1654
+ headers: {
1655
+ "content-type": "application/json",
1656
+ Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`
1657
+ },
1658
+ timeout: requestTimeoutMs,
1659
+ signal: mergedSignal
1660
+ })
1661
+ );
1662
+ return parseOpenRouterBody(id, response.data);
1663
+ }
1664
+ async function callOpenRouterWithRetries(id, payload, retries = 5, options, signal) {
1459
1665
  return withRetries(
1460
1666
  id,
1461
1667
  "OpenRouter",
1462
- () => callOpenRouter(id, payload, requestTimeoutMs, signal),
1668
+ () => options.streaming ? callOpenRouterStream(
1669
+ id,
1670
+ payload,
1671
+ options.streamTimeoutMs,
1672
+ options.chunkTimeoutMs,
1673
+ signal
1674
+ ) : callOpenRouterNonStreaming(
1675
+ id,
1676
+ payload,
1677
+ options.requestTimeoutMs,
1678
+ signal
1679
+ ),
1463
1680
  { retries, signal }
1464
1681
  );
1465
1682
  }
@@ -1501,7 +1718,7 @@ function parseModelString(model) {
1501
1718
  );
1502
1719
  }
1503
1720
  async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeoutMs = 15e3) {
1504
- var _a, _b, _c;
1721
+ var _a, _b, _c, _d, _e, _f;
1505
1722
  try {
1506
1723
  const { provider, modelId } = parseModelString(aiPayload.model);
1507
1724
  const routingPayload = { ...aiPayload, model: modelId };
@@ -1553,15 +1770,20 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
1553
1770
  id,
1554
1771
  prepareOpenRouterPayload(routingPayload),
1555
1772
  retries,
1556
- requestTimeoutMs,
1773
+ {
1774
+ streaming: (_b = aiPayload.streaming) != null ? _b : true,
1775
+ streamTimeoutMs: (_c = aiPayload.streamTimeoutMs) != null ? _c : OPENROUTER_STREAM_TIMEOUT_MS,
1776
+ requestTimeoutMs: (_d = aiPayload.requestTimeoutMs) != null ? _d : OPENROUTER_NONSTREAM_TIMEOUT_MS,
1777
+ chunkTimeoutMs
1778
+ },
1557
1779
  signal
1558
1780
  );
1559
1781
  break;
1560
1782
  }
1561
- (_b = result.provider) != null ? _b : result.provider = provider;
1783
+ (_e = result.provider) != null ? _e : result.provider = provider;
1562
1784
  return result;
1563
1785
  } catch (error2) {
1564
- if ((_c = aiPayload.signal) == null ? void 0 : _c.aborted) throw error2;
1786
+ if ((_f = aiPayload.signal) == null ? void 0 : _f.aborted) throw error2;
1565
1787
  if (aiPayload.fallbackModel) {
1566
1788
  logger_default.error(
1567
1789
  id,
@@ -1591,6 +1813,8 @@ export {
1591
1813
  GPTModel,
1592
1814
  GeminiModel,
1593
1815
  GroqModel,
1816
+ OPENROUTER_NONSTREAM_TIMEOUT_MS,
1817
+ OPENROUTER_STREAM_TIMEOUT_MS,
1594
1818
  OpenRouterModel,
1595
1819
  callWithRetries,
1596
1820
  parseModelString