190proof 1.0.113 → 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 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 proof_exports = {};
32
- __export(proof_exports, {
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(proof_exports);
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: { responseModalities: ["TEXT"] }
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
- errorDetails.safetyRatings = error2.safetyRatings;
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
- errorDetails.httpStatus = error2.status;
1194
- if (error2.code)
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}`,
@@ -1281,16 +1266,13 @@ function prepareOpenAICompatMessages(messages) {
1281
1266
  }
1282
1267
  };
1283
1268
  });
1284
- if (!content)
1285
- outMessage.content = null;
1269
+ if (!content) outMessage.content = null;
1286
1270
  }
1287
- if (message.reasoning)
1288
- outMessage.reasoning = message.reasoning;
1271
+ if (message.reasoning) outMessage.reasoning = message.reasoning;
1289
1272
  const reasoningDetails = filterOpenAICompatReasoningDetails(
1290
1273
  message.reasoningDetails
1291
1274
  );
1292
- if (reasoningDetails)
1293
- outMessage.reasoning_details = reasoningDetails;
1275
+ if (reasoningDetails) outMessage.reasoning_details = reasoningDetails;
1294
1276
  out.push(outMessage);
1295
1277
  }
1296
1278
  return out;
@@ -1433,8 +1415,7 @@ function parseDsmlToolCalls(content) {
1433
1415
  let last = -1;
1434
1416
  let tag;
1435
1417
  while ((tag = DSML_ANY_TAG_RE.exec(content)) !== null) {
1436
- if (first === -1)
1437
- first = tag.index;
1418
+ if (first === -1) first = tag.index;
1438
1419
  last = tag.index + tag[0].length;
1439
1420
  }
1440
1421
  const remaining = first === -1 ? content : (content.slice(0, first) + content.slice(last)).trim();
@@ -1450,8 +1431,7 @@ function finalizeOpenRouterMessage(id, raw) {
1450
1431
  const functionCalls = [];
1451
1432
  for (let i = 0; i < raw.toolCalls.length; i++) {
1452
1433
  const tc = raw.toolCalls[i];
1453
- if (!tc.name)
1454
- continue;
1434
+ if (!tc.name) continue;
1455
1435
  functionCalls.push({
1456
1436
  id: (_a = tc.id) != null ? _a : `call_${i}`,
1457
1437
  name: tc.name,
@@ -1504,8 +1484,7 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
1504
1484
  controller.abort();
1505
1485
  };
1506
1486
  const unref = (t) => {
1507
- if (typeof t === "object" && "unref" in t)
1508
- t.unref();
1487
+ if (typeof t === "object" && "unref" in t) t.unref();
1509
1488
  return t;
1510
1489
  };
1511
1490
  const totalTimer = unref(
@@ -1573,98 +1552,88 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
1573
1552
  const reader = response.body.getReader();
1574
1553
  const decoder = new TextDecoder();
1575
1554
  let lineBuffer = "";
1576
- outer:
1577
- while (true) {
1578
- const { done, value } = await reader.read();
1579
- if (done)
1580
- break;
1581
- lineBuffer += decoder.decode(value, { stream: true });
1582
- let newlineIdx;
1583
- while ((newlineIdx = lineBuffer.indexOf("\n")) !== -1) {
1584
- let line = lineBuffer.slice(0, newlineIdx);
1585
- lineBuffer = lineBuffer.slice(newlineIdx + 1);
1586
- if (line.endsWith("\r"))
1587
- line = line.slice(0, -1);
1588
- if (!line)
1589
- continue;
1590
- if (line.startsWith(":"))
1591
- continue;
1592
- if (!line.startsWith("data:"))
1593
- continue;
1594
- const dataStr = line.slice(5).trimStart();
1595
- if (dataStr === "[DONE]") {
1596
- sawDone = true;
1597
- break outer;
1598
- }
1599
- let json;
1600
- try {
1601
- json = JSON.parse(dataStr);
1602
- } catch (e) {
1603
- logger_default.error(
1604
- id,
1605
- "OpenRouter stream: unparseable data line:",
1606
- dataStr.slice(0, 200)
1607
- );
1608
- continue;
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;
1609
1604
  }
1610
- dataChunks++;
1611
- if (json.error) {
1612
- logger_default.error(id, "OpenRouter stream error event:", json.error);
1613
- const error2 = new Error(
1614
- `OpenRouter error: ${json.error.message}`
1615
- );
1616
- error2.data = json.error;
1617
- throw error2;
1605
+ if (delta.reasoning) {
1606
+ reasoning += delta.reasoning;
1607
+ useful = true;
1618
1608
  }
1619
- if (json.provider)
1620
- provider = json.provider;
1621
- let useful = false;
1622
- if (json.usage) {
1623
- usage = json.usage;
1609
+ if (Array.isArray(delta.reasoning_details) && delta.reasoning_details.length) {
1610
+ reasoningDetails.push(...delta.reasoning_details);
1624
1611
  useful = true;
1625
1612
  }
1626
- const choice = (_c = json.choices) == null ? void 0 : _c[0];
1627
- if (choice) {
1628
- const delta = (_d = choice.delta) != null ? _d : {};
1629
- if (delta.content) {
1630
- paragraph += delta.content;
1631
- useful = true;
1632
- }
1633
- if (delta.reasoning) {
1634
- reasoning += delta.reasoning;
1635
- useful = true;
1636
- }
1637
- if (Array.isArray(delta.reasoning_details) && delta.reasoning_details.length) {
1638
- reasoningDetails.push(...delta.reasoning_details);
1639
- useful = true;
1640
- }
1641
- if (Array.isArray(delta.tool_calls)) {
1642
- for (const toolCall of delta.tool_calls) {
1643
- const idx = (_e = toolCall.index) != null ? _e : 0;
1644
- while (toolCalls.length <= idx) {
1645
- toolCalls.push({ name: "", argumentsJson: "" });
1646
- }
1647
- if (toolCall.id)
1648
- toolCalls[idx].id = toolCall.id;
1649
- if ((_f = toolCall.function) == null ? void 0 : _f.name)
1650
- toolCalls[idx].name += toolCall.function.name;
1651
- if ((_g = toolCall.function) == null ? void 0 : _g.arguments)
1652
- toolCalls[idx].argumentsJson += toolCall.function.arguments;
1653
- 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: "" });
1654
1618
  }
1655
- }
1656
- if (choice.finish_reason) {
1657
- finishReason = choice.finish_reason;
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;
1658
1624
  useful = true;
1659
1625
  }
1660
1626
  }
1661
- if (useful)
1662
- armStallTimer();
1627
+ if (choice.finish_reason) {
1628
+ finishReason = choice.finish_reason;
1629
+ useful = true;
1630
+ }
1663
1631
  }
1632
+ if (useful) armStallTimer();
1664
1633
  }
1665
- if (sawDone)
1666
- reader.cancel().catch(() => {
1667
- });
1634
+ }
1635
+ if (sawDone) reader.cancel().catch(() => {
1636
+ });
1668
1637
  if (!sawDone && !finishReason) {
1669
1638
  logger_default.error(
1670
1639
  id,
@@ -1771,15 +1740,12 @@ var MODERATION_RE = /moderat|inappropriate content|content polic|content managem
1771
1740
  function moderationEvictionSlug(error2, payload) {
1772
1741
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1773
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;
1774
- if (!body)
1775
- return null;
1743
+ if (!body) return null;
1776
1744
  const message = String((_d = body.message) != null ? _d : "");
1777
1745
  const isModeration = body.code === 403 || Array.isArray((_e = body.metadata) == null ? void 0 : _e.reasons) || MODERATION_RE.test(message);
1778
- if (!isModeration)
1779
- return null;
1746
+ if (!isModeration) return null;
1780
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];
1781
- if (!display)
1782
- return null;
1748
+ if (!display) return null;
1783
1749
  const key = normalizeProviderKey(display);
1784
1750
  const fromOrder = (_j = (_i = payload.provider) == null ? void 0 : _i.order) == null ? void 0 : _j.find(
1785
1751
  (entry) => normalizeProviderKey(entry) === key
@@ -1789,11 +1755,9 @@ function moderationEvictionSlug(error2, payload) {
1789
1755
  var MIN_STREAM_ATTEMPT_MS = 1e4;
1790
1756
  var estimateTokens = (text) => Math.round(text.length / 4);
1791
1757
  function streamAttemptBudgetMs(options) {
1792
- if (options.streamDeadlineAt === void 0)
1793
- return options.streamTimeoutMs;
1758
+ if (options.streamDeadlineAt === void 0) return options.streamTimeoutMs;
1794
1759
  const remaining = options.streamDeadlineAt - Date.now();
1795
- if (remaining < MIN_STREAM_ATTEMPT_MS)
1796
- return null;
1760
+ if (remaining < MIN_STREAM_ATTEMPT_MS) return null;
1797
1761
  return Math.min(options.streamTimeoutMs, remaining);
1798
1762
  }
1799
1763
  async function callOpenRouterWithRetries(id, payload, retries = 5, options, signal) {
@@ -1949,8 +1913,7 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
1949
1913
  (_e = result.provider) != null ? _e : result.provider = provider;
1950
1914
  return result;
1951
1915
  } catch (error2) {
1952
- if ((_f = aiPayload.signal) == null ? void 0 : _f.aborted)
1953
- throw error2;
1916
+ if ((_f = aiPayload.signal) == null ? void 0 : _f.aborted) throw error2;
1954
1917
  if (aiPayload.fallbackModel) {
1955
1918
  logger_default.error(
1956
1919
  id,