190proof 1.0.115 → 1.0.117

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,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,
@@ -39,9 +39,10 @@ __export(proof_exports, {
39
39
  OPENROUTER_STREAM_TIMEOUT_MS: () => OPENROUTER_STREAM_TIMEOUT_MS,
40
40
  OpenRouterModel: () => OpenRouterModel,
41
41
  callWithRetries: () => callWithRetries,
42
+ openRouterImageRejectedModels: () => openRouterImageRejectedModels,
42
43
  parseModelString: () => parseModelString
43
44
  });
44
- module.exports = __toCommonJS(proof_exports);
45
+ module.exports = __toCommonJS(index_exports);
45
46
 
46
47
  // interfaces.ts
47
48
  var ClaudeModel = /* @__PURE__ */ ((ClaudeModel2) => {
@@ -172,8 +173,7 @@ async function withRetries(identifier, apiName, fn, options = {}) {
172
173
  return await fn();
173
174
  } catch (error3) {
174
175
  lastError = error3;
175
- if ((_a = options.signal) == null ? void 0 : _a.aborted)
176
- throw error3;
176
+ if ((_a = options.signal) == null ? void 0 : _a.aborted) throw error3;
177
177
  if (onError) {
178
178
  onError(error3, attempt);
179
179
  } else {
@@ -197,8 +197,7 @@ function parseStreamedResponse(identifier, paragraph, toolCallAccumulators, allo
197
197
  const functionCalls = [];
198
198
  for (let i = 0; i < toolCallAccumulators.length; i++) {
199
199
  const acc = toolCallAccumulators[i];
200
- if (!acc.name || !acc.arguments)
201
- continue;
200
+ if (!acc.name || !acc.arguments) continue;
202
201
  if (allowedFunctionNames && !allowedFunctionNames.has(acc.name)) {
203
202
  throw new Error(
204
203
  `Stream error: received function call with unknown name: ${acc.name}`
@@ -337,8 +336,7 @@ function buildOpenAIRequestConfig(identifier, model, config) {
337
336
  };
338
337
  }
339
338
  function filterOpenAICompatReasoningDetails(details) {
340
- if (!Array.isArray(details))
341
- return details || void 0;
339
+ if (!Array.isArray(details)) return details || void 0;
342
340
  const blocks = details.filter(
343
341
  (block) => typeof (block == null ? void 0 : block.type) === "string" && block.type.startsWith("reasoning.")
344
342
  );
@@ -410,19 +408,17 @@ async function prepareOpenAIPayload(identifier, payload) {
410
408
  };
411
409
  });
412
410
  }
413
- if (message.reasoning)
414
- outMessage.reasoning = message.reasoning;
411
+ if (message.reasoning) outMessage.reasoning = message.reasoning;
415
412
  const reasoningDetails = filterOpenAICompatReasoningDetails(
416
413
  message.reasoningDetails
417
414
  );
418
- if (reasoningDetails)
419
- outMessage.reasoning_details = reasoningDetails;
415
+ if (reasoningDetails) outMessage.reasoning_details = reasoningDetails;
420
416
  preparedPayload.messages.push(outMessage);
421
417
  }
422
418
  return preparedPayload;
423
419
  }
424
420
  async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs, requestTimeoutMs = 12e4, signal) {
425
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
421
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
426
422
  const functionNames = openAiPayload.tools ? new Set(openAiPayload.tools.map((fn) => fn.function.name)) : null;
427
423
  const { endpoint, headers } = buildOpenAIRequestConfig(
428
424
  id,
@@ -440,7 +436,15 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
440
436
  const response = await fetch(endpoint, {
441
437
  method: "POST",
442
438
  headers,
443
- body: JSON.stringify({ ...openAiPayload, stream: true }),
439
+ // include_usage: OpenAI only reports token usage on streams when asked,
440
+ // via a final choices-less chunk — without it every streamed call is
441
+ // invisible to usage accounting. Skipped for Azure, where older
442
+ // api-versions reject stream_options.
443
+ body: JSON.stringify({
444
+ ...openAiPayload,
445
+ stream: true,
446
+ ...(openAiConfig == null ? void 0 : openAiConfig.service) !== "azure" ? { stream_options: { include_usage: true } } : {}
447
+ }),
444
448
  // Merge (don't overwrite) the internal timeout controller with the caller's
445
449
  // cancellation signal so both an internal timeout and an external abort stop
446
450
  // the stream.
@@ -451,6 +455,7 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
451
455
  }
452
456
  let paragraph = "";
453
457
  let reasoning = "";
458
+ let streamUsage = null;
454
459
  const toolCallAccumulators = [];
455
460
  const reader = response.body.getReader();
456
461
  let partialChunk = "";
@@ -478,17 +483,18 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
478
483
  }
479
484
  const jsonStrings = chunk.split(/^data: /gm);
480
485
  for (const jsonString of jsonStrings) {
481
- if (!jsonString)
482
- continue;
486
+ if (!jsonString) continue;
483
487
  if (jsonString.includes("[DONE]")) {
484
488
  clearTimeout(overallTimeout);
485
- return parseStreamedResponse(
489
+ const parsed = parseStreamedResponse(
486
490
  id,
487
491
  paragraph,
488
492
  toolCallAccumulators,
489
493
  functionNames,
490
494
  reasoning
491
495
  );
496
+ parsed.usage = streamUsage;
497
+ return parsed;
492
498
  }
493
499
  let json;
494
500
  try {
@@ -498,6 +504,15 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
498
504
  continue;
499
505
  }
500
506
  if (!((_a = json.choices) == null ? void 0 : _a.length)) {
507
+ if (json.usage) {
508
+ streamUsage = {
509
+ prompt_tokens: json.usage.prompt_tokens,
510
+ completion_tokens: json.usage.completion_tokens,
511
+ total_tokens: json.usage.total_tokens,
512
+ cached_tokens: (_c = (_b = json.usage.prompt_tokens_details) == null ? void 0 : _b.cached_tokens) != null ? _c : 0
513
+ };
514
+ continue;
515
+ }
501
516
  if (json.error) {
502
517
  logger_default.error(id, "Stream error from OpenAI:", json.error);
503
518
  const error2 = new Error("Stream error: OpenAI error");
@@ -510,27 +525,24 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
510
525
  }
511
526
  continue;
512
527
  }
513
- const toolCalls = (_c = (_b = json.choices[0]) == null ? void 0 : _b.delta) == null ? void 0 : _c.tool_calls;
528
+ const toolCalls = (_e = (_d = json.choices[0]) == null ? void 0 : _d.delta) == null ? void 0 : _e.tool_calls;
514
529
  if (toolCalls) {
515
530
  for (const toolCall of toolCalls) {
516
- const idx = (_d = toolCall.index) != null ? _d : 0;
531
+ const idx = (_f = toolCall.index) != null ? _f : 0;
517
532
  while (toolCallAccumulators.length <= idx) {
518
533
  toolCallAccumulators.push({ name: "", arguments: "" });
519
534
  }
520
- if (toolCall.id)
521
- toolCallAccumulators[idx].id = toolCall.id;
522
- if ((_e = toolCall.function) == null ? void 0 : _e.name)
535
+ if (toolCall.id) toolCallAccumulators[idx].id = toolCall.id;
536
+ if ((_g = toolCall.function) == null ? void 0 : _g.name)
523
537
  toolCallAccumulators[idx].name += toolCall.function.name;
524
- if ((_f = toolCall.function) == null ? void 0 : _f.arguments)
538
+ if ((_h = toolCall.function) == null ? void 0 : _h.arguments)
525
539
  toolCallAccumulators[idx].arguments += toolCall.function.arguments;
526
540
  }
527
541
  }
528
- const text = (_h = (_g = json.choices[0]) == null ? void 0 : _g.delta) == null ? void 0 : _h.content;
529
- if (text)
530
- paragraph += text;
531
- const reasoningDelta = (_j = (_i = json.choices[0]) == null ? void 0 : _i.delta) == null ? void 0 : _j.reasoning;
532
- if (reasoningDelta)
533
- reasoning += reasoningDelta;
542
+ const text = (_j = (_i = json.choices[0]) == null ? void 0 : _i.delta) == null ? void 0 : _j.content;
543
+ if (text) paragraph += text;
544
+ const reasoningDelta = (_l = (_k = json.choices[0]) == null ? void 0 : _k.delta) == null ? void 0 : _l.reasoning;
545
+ if (reasoningDelta) reasoning += reasoningDelta;
534
546
  }
535
547
  }
536
548
  }
@@ -675,8 +687,7 @@ function jigAnthropicMessages(messages) {
675
687
  ];
676
688
  }
677
689
  jiggedMessages = jiggedMessages.reduce((acc, message) => {
678
- if (acc.length === 0)
679
- return [message];
690
+ if (acc.length === 0) return [message];
680
691
  const lastMessage = acc[acc.length - 1];
681
692
  if (lastMessage.role === message.role) {
682
693
  const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
@@ -930,8 +941,7 @@ function jigGoogleMessages(messages) {
930
941
  ];
931
942
  }
932
943
  jiggedMessages = jiggedMessages.reduce((acc, message) => {
933
- if (acc.length === 0)
934
- return [message];
944
+ if (acc.length === 0) return [message];
935
945
  const lastMessage = acc[acc.length - 1];
936
946
  if (lastMessage.role === message.role) {
937
947
  lastMessage.parts = [...lastMessage.parts, ...message.parts];
@@ -970,8 +980,7 @@ async function prepareGoogleAIPayload(_identifier, payload) {
970
980
  const toolNameById = /* @__PURE__ */ new Map();
971
981
  for (const m of payload.messages) {
972
982
  for (const fc of m.functionCalls || []) {
973
- if (fc.id)
974
- toolNameById.set(fc.id, fc.name);
983
+ if (fc.id) toolNameById.set(fc.id, fc.name);
975
984
  }
976
985
  }
977
986
  for (const message of payload.messages) {
@@ -1051,8 +1060,7 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
1051
1060
  ...payload.thinkingConfig ? { thinkingConfig: payload.thinkingConfig } : {}
1052
1061
  }
1053
1062
  };
1054
- if (payload.tools)
1055
- requestBody.tools = [payload.tools];
1063
+ if (payload.tools) requestBody.tools = [payload.tools];
1056
1064
  if (payload.tools && payload.toolConfig) {
1057
1065
  requestBody.toolConfig = payload.toolConfig;
1058
1066
  }
@@ -1110,8 +1118,7 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
1110
1118
  });
1111
1119
  continue;
1112
1120
  }
1113
- if (part.text)
1114
- text += part.text;
1121
+ if (part.text) text += part.text;
1115
1122
  if ((_m = part.inlineData) == null ? void 0 : _m.data) {
1116
1123
  files.push({ mimeType: "image/png", data: part.inlineData.data });
1117
1124
  }
@@ -1189,21 +1196,15 @@ async function callGoogleAIWithRetries(id, payload, retries = 5, requestTimeoutM
1189
1196
  finishReason: error2.finishReason,
1190
1197
  modelVersion: error2.modelVersion
1191
1198
  };
1192
- if (error2.safetyRatings)
1193
- errorDetails.safetyRatings = error2.safetyRatings;
1194
- if (error2.usageMetadata)
1195
- errorDetails.usageMetadata = error2.usageMetadata;
1199
+ if (error2.safetyRatings) errorDetails.safetyRatings = error2.safetyRatings;
1200
+ if (error2.usageMetadata) errorDetails.usageMetadata = error2.usageMetadata;
1196
1201
  if (error2.promptFeedback)
1197
1202
  errorDetails.promptFeedback = error2.promptFeedback;
1198
- if (error2.status)
1199
- errorDetails.httpStatus = error2.status;
1200
- if (error2.code)
1201
- errorDetails.errorCode = error2.code;
1202
- if (error2.details)
1203
- errorDetails.errorDetails = error2.details;
1203
+ if (error2.status) errorDetails.httpStatus = error2.status;
1204
+ if (error2.code) errorDetails.errorCode = error2.code;
1205
+ if (error2.details) errorDetails.errorDetails = error2.details;
1204
1206
  const fileUris = payload.messages.flatMap((m) => m.parts).filter((p) => "fileData" in p).map((p) => p.fileData.fileUri);
1205
- if (fileUris.length)
1206
- errorDetails.fileUris = fileUris;
1207
+ if (fileUris.length) errorDetails.fileUris = fileUris;
1207
1208
  logger_default.error(
1208
1209
  id,
1209
1210
  `Retry #${attempt} error: ${error2.message}`,
@@ -1253,7 +1254,7 @@ async function callGoogleAIWithRetries(id, payload, retries = 5, requestTimeoutM
1253
1254
  function normalizeMessageContent(content) {
1254
1255
  return Array.isArray(content) ? content.map((c) => c.type === "text" ? c.text : `[${c.type}]`).join("\n") : content;
1255
1256
  }
1256
- function prepareOpenAICompatMessages(messages) {
1257
+ function prepareOpenAICompatMessages(messages, opts = {}) {
1257
1258
  var _a;
1258
1259
  const out = [];
1259
1260
  for (const message of messages) {
@@ -1275,6 +1276,22 @@ function prepareOpenAICompatMessages(messages) {
1275
1276
  role: message.role,
1276
1277
  content
1277
1278
  };
1279
+ if (opts.imageParts) {
1280
+ const imageBlocks = (message.files || []).filter(
1281
+ (file) => ALLOWED_IMAGE_MIME_TYPES.includes(file.mimeType) && (file.url || file.data)
1282
+ ).map((file) => ({
1283
+ type: "image_url",
1284
+ image_url: {
1285
+ url: file.url || `data:${file.mimeType};base64,${file.data}`
1286
+ }
1287
+ }));
1288
+ if (imageBlocks.length) {
1289
+ outMessage.content = [
1290
+ ...content ? [{ type: "text", text: content }] : [],
1291
+ ...imageBlocks
1292
+ ];
1293
+ }
1294
+ }
1278
1295
  if ((_a = message.functionCalls) == null ? void 0 : _a.length) {
1279
1296
  outMessage.tool_calls = message.functionCalls.map((fc, i) => {
1280
1297
  var _a2;
@@ -1287,16 +1304,14 @@ function prepareOpenAICompatMessages(messages) {
1287
1304
  }
1288
1305
  };
1289
1306
  });
1290
- if (!content)
1307
+ if (!content && !Array.isArray(outMessage.content))
1291
1308
  outMessage.content = null;
1292
1309
  }
1293
- if (message.reasoning)
1294
- outMessage.reasoning = message.reasoning;
1310
+ if (message.reasoning) outMessage.reasoning = message.reasoning;
1295
1311
  const reasoningDetails = filterOpenAICompatReasoningDetails(
1296
1312
  message.reasoningDetails
1297
1313
  );
1298
- if (reasoningDetails)
1299
- outMessage.reasoning_details = reasoningDetails;
1314
+ if (reasoningDetails) outMessage.reasoning_details = reasoningDetails;
1300
1315
  out.push(outMessage);
1301
1316
  }
1302
1317
  return out;
@@ -1384,18 +1399,22 @@ async function callGroqWithRetries(id, payload, retries = 5, requestTimeoutMs =
1384
1399
  signal
1385
1400
  });
1386
1401
  }
1402
+ var openRouterImageRejectedModels = /* @__PURE__ */ new Set();
1387
1403
  function prepareOpenRouterPayload(payload) {
1388
1404
  var _a;
1389
1405
  return {
1390
1406
  model: payload.model,
1391
- messages: prepareOpenAICompatMessages(payload.messages),
1407
+ messages: prepareOpenAICompatMessages(payload.messages, {
1408
+ imageParts: !openRouterImageRejectedModels.has(String(payload.model))
1409
+ }),
1392
1410
  tools: (_a = payload.functions) == null ? void 0 : _a.map((fn) => ({
1393
1411
  type: "function",
1394
1412
  function: fn
1395
1413
  })),
1396
1414
  tool_choice: payload.function_call ? typeof payload.function_call === "string" ? payload.function_call : { type: "function", function: payload.function_call } : void 0,
1397
1415
  temperature: payload.temperature,
1398
- provider: payload.provider
1416
+ provider: payload.provider,
1417
+ reasoning_effort: payload.reasoningEffort
1399
1418
  };
1400
1419
  }
1401
1420
  var DSML_ENVELOPE_RE = /<|+DSML|+tool_calls>/;
@@ -1439,8 +1458,7 @@ function parseDsmlToolCalls(content) {
1439
1458
  let last = -1;
1440
1459
  let tag;
1441
1460
  while ((tag = DSML_ANY_TAG_RE.exec(content)) !== null) {
1442
- if (first === -1)
1443
- first = tag.index;
1461
+ if (first === -1) first = tag.index;
1444
1462
  last = tag.index + tag[0].length;
1445
1463
  }
1446
1464
  const remaining = first === -1 ? content : (content.slice(0, first) + content.slice(last)).trim();
@@ -1456,8 +1474,7 @@ function finalizeOpenRouterMessage(id, raw) {
1456
1474
  const functionCalls = [];
1457
1475
  for (let i = 0; i < raw.toolCalls.length; i++) {
1458
1476
  const tc = raw.toolCalls[i];
1459
- if (!tc.name)
1460
- continue;
1477
+ if (!tc.name) continue;
1461
1478
  functionCalls.push({
1462
1479
  id: (_a = tc.id) != null ? _a : `call_${i}`,
1463
1480
  name: tc.name,
@@ -1510,8 +1527,7 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
1510
1527
  controller.abort();
1511
1528
  };
1512
1529
  const unref = (t) => {
1513
- if (typeof t === "object" && "unref" in t)
1514
- t.unref();
1530
+ if (typeof t === "object" && "unref" in t) t.unref();
1515
1531
  return t;
1516
1532
  };
1517
1533
  const totalTimer = unref(
@@ -1579,98 +1595,88 @@ async function callOpenRouterStream(id, payload, streamTimeoutMs = OPENROUTER_ST
1579
1595
  const reader = response.body.getReader();
1580
1596
  const decoder = new TextDecoder();
1581
1597
  let lineBuffer = "";
1582
- outer:
1583
- while (true) {
1584
- const { done, value } = await reader.read();
1585
- if (done)
1586
- break;
1587
- lineBuffer += decoder.decode(value, { stream: true });
1588
- let newlineIdx;
1589
- while ((newlineIdx = lineBuffer.indexOf("\n")) !== -1) {
1590
- let line = lineBuffer.slice(0, newlineIdx);
1591
- lineBuffer = lineBuffer.slice(newlineIdx + 1);
1592
- if (line.endsWith("\r"))
1593
- line = line.slice(0, -1);
1594
- if (!line)
1595
- continue;
1596
- if (line.startsWith(":"))
1597
- continue;
1598
- if (!line.startsWith("data:"))
1599
- continue;
1600
- const dataStr = line.slice(5).trimStart();
1601
- if (dataStr === "[DONE]") {
1602
- sawDone = true;
1603
- break outer;
1604
- }
1605
- let json;
1606
- try {
1607
- json = JSON.parse(dataStr);
1608
- } catch (e) {
1609
- logger_default.error(
1610
- id,
1611
- "OpenRouter stream: unparseable data line:",
1612
- dataStr.slice(0, 200)
1613
- );
1614
- continue;
1598
+ outer: while (true) {
1599
+ const { done, value } = await reader.read();
1600
+ if (done) break;
1601
+ lineBuffer += decoder.decode(value, { stream: true });
1602
+ let newlineIdx;
1603
+ while ((newlineIdx = lineBuffer.indexOf("\n")) !== -1) {
1604
+ let line = lineBuffer.slice(0, newlineIdx);
1605
+ lineBuffer = lineBuffer.slice(newlineIdx + 1);
1606
+ if (line.endsWith("\r")) line = line.slice(0, -1);
1607
+ if (!line) continue;
1608
+ if (line.startsWith(":")) continue;
1609
+ if (!line.startsWith("data:")) continue;
1610
+ const dataStr = line.slice(5).trimStart();
1611
+ if (dataStr === "[DONE]") {
1612
+ sawDone = true;
1613
+ break outer;
1614
+ }
1615
+ let json;
1616
+ try {
1617
+ json = JSON.parse(dataStr);
1618
+ } catch (e) {
1619
+ logger_default.error(
1620
+ id,
1621
+ "OpenRouter stream: unparseable data line:",
1622
+ dataStr.slice(0, 200)
1623
+ );
1624
+ continue;
1625
+ }
1626
+ dataChunks++;
1627
+ if (json.error) {
1628
+ logger_default.error(id, "OpenRouter stream error event:", json.error);
1629
+ const error2 = new Error(
1630
+ `OpenRouter error: ${json.error.message}`
1631
+ );
1632
+ error2.data = json.error;
1633
+ throw error2;
1634
+ }
1635
+ if (json.provider) provider = json.provider;
1636
+ let useful = false;
1637
+ if (json.usage) {
1638
+ usage = json.usage;
1639
+ useful = true;
1640
+ }
1641
+ const choice = (_c = json.choices) == null ? void 0 : _c[0];
1642
+ if (choice) {
1643
+ const delta = (_d = choice.delta) != null ? _d : {};
1644
+ if (delta.content) {
1645
+ paragraph += delta.content;
1646
+ useful = true;
1615
1647
  }
1616
- dataChunks++;
1617
- if (json.error) {
1618
- logger_default.error(id, "OpenRouter stream error event:", json.error);
1619
- const error2 = new Error(
1620
- `OpenRouter error: ${json.error.message}`
1621
- );
1622
- error2.data = json.error;
1623
- throw error2;
1648
+ if (delta.reasoning) {
1649
+ reasoning += delta.reasoning;
1650
+ useful = true;
1624
1651
  }
1625
- if (json.provider)
1626
- provider = json.provider;
1627
- let useful = false;
1628
- if (json.usage) {
1629
- usage = json.usage;
1652
+ if (Array.isArray(delta.reasoning_details) && delta.reasoning_details.length) {
1653
+ reasoningDetails.push(...delta.reasoning_details);
1630
1654
  useful = true;
1631
1655
  }
1632
- const choice = (_c = json.choices) == null ? void 0 : _c[0];
1633
- if (choice) {
1634
- const delta = (_d = choice.delta) != null ? _d : {};
1635
- if (delta.content) {
1636
- paragraph += delta.content;
1637
- useful = true;
1638
- }
1639
- if (delta.reasoning) {
1640
- reasoning += delta.reasoning;
1641
- useful = true;
1642
- }
1643
- if (Array.isArray(delta.reasoning_details) && delta.reasoning_details.length) {
1644
- reasoningDetails.push(...delta.reasoning_details);
1645
- useful = true;
1646
- }
1647
- if (Array.isArray(delta.tool_calls)) {
1648
- for (const toolCall of delta.tool_calls) {
1649
- const idx = (_e = toolCall.index) != null ? _e : 0;
1650
- while (toolCalls.length <= idx) {
1651
- toolCalls.push({ name: "", argumentsJson: "" });
1652
- }
1653
- if (toolCall.id)
1654
- toolCalls[idx].id = toolCall.id;
1655
- if ((_f = toolCall.function) == null ? void 0 : _f.name)
1656
- toolCalls[idx].name += toolCall.function.name;
1657
- if ((_g = toolCall.function) == null ? void 0 : _g.arguments)
1658
- toolCalls[idx].argumentsJson += toolCall.function.arguments;
1659
- useful = true;
1656
+ if (Array.isArray(delta.tool_calls)) {
1657
+ for (const toolCall of delta.tool_calls) {
1658
+ const idx = (_e = toolCall.index) != null ? _e : 0;
1659
+ while (toolCalls.length <= idx) {
1660
+ toolCalls.push({ name: "", argumentsJson: "" });
1660
1661
  }
1661
- }
1662
- if (choice.finish_reason) {
1663
- finishReason = choice.finish_reason;
1662
+ if (toolCall.id) toolCalls[idx].id = toolCall.id;
1663
+ if ((_f = toolCall.function) == null ? void 0 : _f.name)
1664
+ toolCalls[idx].name += toolCall.function.name;
1665
+ if ((_g = toolCall.function) == null ? void 0 : _g.arguments)
1666
+ toolCalls[idx].argumentsJson += toolCall.function.arguments;
1664
1667
  useful = true;
1665
1668
  }
1666
1669
  }
1667
- if (useful)
1668
- armStallTimer();
1670
+ if (choice.finish_reason) {
1671
+ finishReason = choice.finish_reason;
1672
+ useful = true;
1673
+ }
1669
1674
  }
1675
+ if (useful) armStallTimer();
1670
1676
  }
1671
- if (sawDone)
1672
- reader.cancel().catch(() => {
1673
- });
1677
+ }
1678
+ if (sawDone) reader.cancel().catch(() => {
1679
+ });
1674
1680
  if (!sawDone && !finishReason) {
1675
1681
  logger_default.error(
1676
1682
  id,
@@ -1777,15 +1783,12 @@ var MODERATION_RE = /moderat|inappropriate content|content polic|content managem
1777
1783
  function moderationEvictionSlug(error2, payload) {
1778
1784
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1779
1785
  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;
1780
- if (!body)
1781
- return null;
1786
+ if (!body) return null;
1782
1787
  const message = String((_d = body.message) != null ? _d : "");
1783
1788
  const isModeration = body.code === 403 || Array.isArray((_e = body.metadata) == null ? void 0 : _e.reasons) || MODERATION_RE.test(message);
1784
- if (!isModeration)
1785
- return null;
1789
+ if (!isModeration) return null;
1786
1790
  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];
1787
- if (!display)
1788
- return null;
1791
+ if (!display) return null;
1789
1792
  const key = normalizeProviderKey(display);
1790
1793
  const fromOrder = (_j = (_i = payload.provider) == null ? void 0 : _i.order) == null ? void 0 : _j.find(
1791
1794
  (entry) => normalizeProviderKey(entry) === key
@@ -1794,12 +1797,15 @@ function moderationEvictionSlug(error2, payload) {
1794
1797
  }
1795
1798
  var MIN_STREAM_ATTEMPT_MS = 1e4;
1796
1799
  var estimateTokens = (text) => Math.round(text.length / 4);
1800
+ function isImageInputRejection(error2) {
1801
+ var _a, _b, _c, _d;
1802
+ 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;
1803
+ return /no endpoints found.*image input/i.test(String((_d = body == null ? void 0 : body.message) != null ? _d : ""));
1804
+ }
1797
1805
  function streamAttemptBudgetMs(options) {
1798
- if (options.streamDeadlineAt === void 0)
1799
- return options.streamTimeoutMs;
1806
+ if (options.streamDeadlineAt === void 0) return options.streamTimeoutMs;
1800
1807
  const remaining = options.streamDeadlineAt - Date.now();
1801
- if (remaining < MIN_STREAM_ATTEMPT_MS)
1802
- return null;
1808
+ if (remaining < MIN_STREAM_ATTEMPT_MS) return null;
1803
1809
  return Math.min(options.streamTimeoutMs, remaining);
1804
1810
  }
1805
1811
  async function callOpenRouterWithRetries(id, payload, retries = 5, options, signal) {
@@ -1846,6 +1852,16 @@ async function callOpenRouterWithRetries(id, payload, retries = 5, options, sign
1846
1852
  `OpenRouter moderation eviction: ignoring provider "${slug}" for remaining attempts`
1847
1853
  );
1848
1854
  }
1855
+ if (isImageInputRejection(error2) && options.genericMessages) {
1856
+ openRouterImageRejectedModels.add(String(payload.model));
1857
+ payload.messages = prepareOpenAICompatMessages(
1858
+ options.genericMessages
1859
+ );
1860
+ logger_default.log(
1861
+ id,
1862
+ `OpenRouter: ${payload.model} has no image-capable endpoints; retrying with images as text refs`
1863
+ );
1864
+ }
1849
1865
  throw error2;
1850
1866
  }),
1851
1867
  { retries, signal }
@@ -1946,7 +1962,8 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
1946
1962
  streamTimeoutMs: (_c = aiPayload.streamTimeoutMs) != null ? _c : OPENROUTER_STREAM_TIMEOUT_MS,
1947
1963
  streamDeadlineAt: aiPayload.streamDeadlineAt,
1948
1964
  requestTimeoutMs: (_d = aiPayload.requestTimeoutMs) != null ? _d : OPENROUTER_NONSTREAM_TIMEOUT_MS,
1949
- chunkTimeoutMs
1965
+ chunkTimeoutMs,
1966
+ genericMessages: routingPayload.messages
1950
1967
  },
1951
1968
  signal
1952
1969
  );
@@ -1955,8 +1972,7 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
1955
1972
  (_e = result.provider) != null ? _e : result.provider = provider;
1956
1973
  return result;
1957
1974
  } catch (error2) {
1958
- if ((_f = aiPayload.signal) == null ? void 0 : _f.aborted)
1959
- throw error2;
1975
+ if ((_f = aiPayload.signal) == null ? void 0 : _f.aborted) throw error2;
1960
1976
  if (aiPayload.fallbackModel) {
1961
1977
  logger_default.error(
1962
1978
  id,
@@ -1992,6 +2008,7 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
1992
2008
  OPENROUTER_STREAM_TIMEOUT_MS,
1993
2009
  OpenRouterModel,
1994
2010
  callWithRetries,
2011
+ openRouterImageRejectedModels,
1995
2012
  parseModelString
1996
2013
  });
1997
2014
  //# sourceMappingURL=index.js.map