190proof 1.0.100 → 1.0.102

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
@@ -110,8 +110,13 @@ function isHeicImage(name, mime) {
110
110
  // index.ts
111
111
  var sharp = __require("sharp");
112
112
  var decode = __require("heic-decode");
113
+ function anySignal(signals) {
114
+ return AbortSignal.any(
115
+ signals
116
+ );
117
+ }
113
118
  async function withRetries(identifier, apiName, fn, options = {}) {
114
- var _a, _b, _c, _d;
119
+ var _a, _b, _c, _d, _e;
115
120
  const { retries = 5, baseDelayMs = 125, onError } = options;
116
121
  logger_default.log(identifier, `Calling ${apiName} API with retries`);
117
122
  let lastError;
@@ -120,19 +125,21 @@ async function withRetries(identifier, apiName, fn, options = {}) {
120
125
  return await fn();
121
126
  } catch (error3) {
122
127
  lastError = error3;
128
+ if ((_a = options.signal) == null ? void 0 : _a.aborted)
129
+ throw error3;
123
130
  if (onError) {
124
131
  onError(error3, attempt);
125
132
  } else {
126
133
  logger_default.error(
127
134
  identifier,
128
135
  `Retry #${attempt} error: ${error3.message}`,
129
- ((_a = error3.response) == null ? void 0 : _a.data) || error3
136
+ ((_b = error3.response) == null ? void 0 : _b.data) || error3
130
137
  );
131
138
  }
132
139
  await timeout(baseDelayMs * attempt);
133
140
  }
134
141
  }
135
- const detail = ((_d = (_c = (_b = lastError == null ? void 0 : lastError.response) == null ? void 0 : _b.data) == null ? void 0 : _c.error) == null ? void 0 : _d.message) || (lastError == null ? void 0 : lastError.message) || String(lastError);
142
+ const detail = ((_e = (_d = (_c = lastError == null ? void 0 : lastError.response) == null ? void 0 : _c.data) == null ? void 0 : _d.error) == null ? void 0 : _e.message) || (lastError == null ? void 0 : lastError.message) || String(lastError);
136
143
  const error2 = new Error(
137
144
  `Failed to call ${apiName} API after ${retries} attempts: ${detail}`
138
145
  );
@@ -355,7 +362,7 @@ async function prepareOpenAIPayload(identifier, payload) {
355
362
  }
356
363
  return preparedPayload;
357
364
  }
358
- async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs, requestTimeoutMs = 12e4) {
365
+ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs, requestTimeoutMs = 12e4, signal) {
359
366
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
360
367
  const functionNames = openAiPayload.tools ? new Set(openAiPayload.tools.map((fn) => fn.function.name)) : null;
361
368
  const { endpoint, headers } = buildOpenAIRequestConfig(
@@ -375,7 +382,10 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
375
382
  method: "POST",
376
383
  headers,
377
384
  body: JSON.stringify({ ...openAiPayload, stream: true }),
378
- signal: controller.signal
385
+ // Merge (don't overwrite) the internal timeout controller with the caller's
386
+ // cancellation signal so both an internal timeout and an external abort stop
387
+ // the stream.
388
+ signal: signal ? anySignal([controller.signal, signal]) : controller.signal
379
389
  });
380
390
  if (!response.body) {
381
391
  throw new Error("Stream error: no response body");
@@ -465,7 +475,7 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
465
475
  }
466
476
  }
467
477
  }
468
- async function callOpenAI(id, openAiPayload, openAiConfig, requestTimeoutMs = 12e4) {
478
+ async function callOpenAI(id, openAiPayload, openAiConfig, requestTimeoutMs = 12e4, signal) {
469
479
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
470
480
  const { endpoint, headers } = buildOpenAIRequestConfig(
471
481
  id,
@@ -480,7 +490,8 @@ async function callOpenAI(id, openAiPayload, openAiConfig, requestTimeoutMs = 12
480
490
  method: "POST",
481
491
  headers,
482
492
  body: JSON.stringify({ ...openAiPayload, stream: false }),
483
- signal: controller.signal
493
+ // Merge the internal timeout controller with the caller's cancellation signal.
494
+ signal: signal ? anySignal([controller.signal, signal]) : controller.signal
484
495
  });
485
496
  if (!response.ok) {
486
497
  const errorData = await response.json();
@@ -543,7 +554,7 @@ async function callOpenAI(id, openAiPayload, openAiConfig, requestTimeoutMs = 12
543
554
  } : null
544
555
  };
545
556
  }
546
- async function callOpenAiWithRetries(id, openAiPayload, openAiConfig, retries = 5, chunkTimeoutMs = 15e3, requestTimeoutMs = 12e4) {
557
+ async function callOpenAiWithRetries(id, openAiPayload, openAiConfig, retries = 5, chunkTimeoutMs = 15e3, requestTimeoutMs = 12e4, signal) {
547
558
  logger_default.log(
548
559
  id,
549
560
  "Calling OpenAI API with retries:",
@@ -562,14 +573,16 @@ async function callOpenAiWithRetries(id, openAiPayload, openAiConfig, retries =
562
573
  openAiPayload,
563
574
  openAiConfig,
564
575
  chunkTimeoutMs,
565
- requestTimeoutMs
576
+ requestTimeoutMs,
577
+ signal
566
578
  );
567
579
  } else {
568
- return callOpenAI(id, openAiPayload, openAiConfig, requestTimeoutMs);
580
+ return callOpenAI(id, openAiPayload, openAiConfig, requestTimeoutMs, signal);
569
581
  }
570
582
  },
571
583
  {
572
584
  retries,
585
+ signal,
573
586
  baseDelayMs: 250,
574
587
  onError: (error2, attempt) => {
575
588
  var _a, _b;
@@ -701,7 +714,7 @@ async function prepareAnthropicPayload(_identifier, payload) {
701
714
  }
702
715
  return preparedPayload;
703
716
  }
704
- async function callAnthropic(id, payload, config, requestTimeoutMs = 12e4) {
717
+ async function callAnthropic(id, payload, config, requestTimeoutMs = 12e4, signal) {
705
718
  var _a, _b, _c;
706
719
  const anthropicMessages = jigAnthropicMessages(payload.messages);
707
720
  const tools = (_a = payload.functions) == null ? void 0 : _a.map((f) => ({
@@ -725,7 +738,8 @@ async function callAnthropic(id, payload, config, requestTimeoutMs = 12e4) {
725
738
  contentType: "application/json",
726
739
  body: JSON.stringify(bedrockPayload),
727
740
  modelId: MODEL_ID
728
- })
741
+ }),
742
+ { abortSignal: signal }
729
743
  );
730
744
  const decodedResponseBody = new TextDecoder().decode(response.body);
731
745
  data = JSON.parse(decodedResponseBody);
@@ -751,7 +765,8 @@ async function callAnthropic(id, payload, config, requestTimeoutMs = 12e4) {
751
765
  "anthropic-version": "2023-06-01",
752
766
  "anthropic-beta": "tools-2024-04-04"
753
767
  },
754
- timeout: requestTimeoutMs
768
+ timeout: requestTimeoutMs,
769
+ signal
755
770
  }
756
771
  );
757
772
  data = response.data;
@@ -821,13 +836,14 @@ ${text}` : text;
821
836
  usage
822
837
  };
823
838
  }
824
- async function callAnthropicWithRetries(id, payload, config, retries = 5, requestTimeoutMs = 12e4) {
839
+ async function callAnthropicWithRetries(id, payload, config, retries = 5, requestTimeoutMs = 12e4, signal) {
825
840
  return withRetries(
826
841
  id,
827
842
  "Anthropic",
828
- () => callAnthropic(id, payload, config, requestTimeoutMs),
843
+ () => callAnthropic(id, payload, config, requestTimeoutMs, signal),
829
844
  {
830
- retries
845
+ retries,
846
+ signal
831
847
  }
832
848
  );
833
849
  }
@@ -945,7 +961,7 @@ async function prepareGoogleAIPayload(_identifier, payload) {
945
961
  }
946
962
  return preparedPayload;
947
963
  }
948
- async function callGoogleAI(id, payload, requestTimeoutMs = 12e4) {
964
+ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
949
965
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
950
966
  const contents = jigGoogleMessages(payload.messages);
951
967
  const requestBody = {
@@ -969,7 +985,8 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4) {
969
985
  "content-type": "application/json",
970
986
  "x-goog-api-key": process.env.GEMINI_API_KEY
971
987
  },
972
- timeout: requestTimeoutMs
988
+ timeout: requestTimeoutMs,
989
+ signal
973
990
  }
974
991
  );
975
992
  response = httpResponse.data;
@@ -1068,10 +1085,11 @@ function removeImagesFromGooglePayload(payload) {
1068
1085
  }
1069
1086
  return removedImages;
1070
1087
  }
1071
- async function callGoogleAIWithRetries(id, payload, retries = 5, requestTimeoutMs = 12e4) {
1088
+ async function callGoogleAIWithRetries(id, payload, retries = 5, requestTimeoutMs = 12e4, signal) {
1072
1089
  let hasTriedWithoutImages = false;
1073
- return withRetries(id, "Google AI", () => callGoogleAI(id, payload, requestTimeoutMs), {
1090
+ return withRetries(id, "Google AI", () => callGoogleAI(id, payload, requestTimeoutMs, signal), {
1074
1091
  retries,
1092
+ signal,
1075
1093
  onError: (error2, attempt) => {
1076
1094
  var _a, _b;
1077
1095
  const errorDetails = {
@@ -1197,7 +1215,7 @@ function prepareGroqPayload(payload) {
1197
1215
  temperature: payload.temperature
1198
1216
  };
1199
1217
  }
1200
- async function callGroq(id, payload, requestTimeoutMs = 12e4) {
1218
+ async function callGroq(id, payload, requestTimeoutMs = 12e4, signal) {
1201
1219
  var _a, _b, _c, _d, _e, _f, _g;
1202
1220
  const response = await axios.post(
1203
1221
  "https://api.groq.com/openai/v1/chat/completions",
@@ -1207,7 +1225,8 @@ async function callGroq(id, payload, requestTimeoutMs = 12e4) {
1207
1225
  "content-type": "application/json",
1208
1226
  Authorization: `Bearer ${process.env.GROQ_API_KEY}`
1209
1227
  },
1210
- timeout: requestTimeoutMs
1228
+ timeout: requestTimeoutMs,
1229
+ signal
1211
1230
  }
1212
1231
  );
1213
1232
  if (response.data.error) {
@@ -1255,9 +1274,10 @@ async function callGroq(id, payload, requestTimeoutMs = 12e4) {
1255
1274
  } : null
1256
1275
  };
1257
1276
  }
1258
- async function callGroqWithRetries(id, payload, retries = 5, requestTimeoutMs = 12e4) {
1259
- return withRetries(id, "Groq", () => callGroq(id, payload, requestTimeoutMs), {
1260
- retries
1277
+ async function callGroqWithRetries(id, payload, retries = 5, requestTimeoutMs = 12e4, signal) {
1278
+ return withRetries(id, "Groq", () => callGroq(id, payload, requestTimeoutMs, signal), {
1279
+ retries,
1280
+ signal
1261
1281
  });
1262
1282
  }
1263
1283
  function prepareOpenRouterPayload(payload) {
@@ -1274,8 +1294,56 @@ function prepareOpenRouterPayload(payload) {
1274
1294
  provider: payload.provider
1275
1295
  };
1276
1296
  }
1277
- async function callOpenRouter(id, payload, requestTimeoutMs = 12e4) {
1278
- var _a, _b, _c, _d, _e, _f, _g, _h;
1297
+ var DSML_ENVELOPE_RE = /<|+DSML|+tool_calls>/;
1298
+ var DSML_DELIMITER_RE = /<\/?|+DSML|+/;
1299
+ var DSML_INVOKE_RE = /<|+DSML|+invoke\s+name="([^"]+)"\s*>([\s\S]*?)<\/|+DSML|+invoke>/g;
1300
+ var DSML_PARAM_RE = /<|+DSML|+parameter\s+name="([^"]+)"(?:\s+string="(true|false)")?\s*>([\s\S]*?)<\/|+DSML|+parameter>/g;
1301
+ var DSML_ANY_TAG_RE = /<\/?|+DSML|+[^>]*>/g;
1302
+ function parseDsmlToolCalls(content) {
1303
+ const calls = [];
1304
+ DSML_INVOKE_RE.lastIndex = 0;
1305
+ let invokeMatch;
1306
+ while ((invokeMatch = DSML_INVOKE_RE.exec(content)) !== null) {
1307
+ const name = invokeMatch[1];
1308
+ const inner = invokeMatch[2];
1309
+ const args = {};
1310
+ let ok = true;
1311
+ DSML_PARAM_RE.lastIndex = 0;
1312
+ let paramMatch;
1313
+ while ((paramMatch = DSML_PARAM_RE.exec(inner)) !== null) {
1314
+ const [, paramName, stringAttr, rawValue] = paramMatch;
1315
+ if (stringAttr === "false") {
1316
+ try {
1317
+ args[paramName] = JSON.parse(rawValue);
1318
+ } catch (e) {
1319
+ ok = false;
1320
+ break;
1321
+ }
1322
+ } else {
1323
+ args[paramName] = rawValue;
1324
+ }
1325
+ }
1326
+ if (ok && name) {
1327
+ calls.push({ id: `call_${calls.length}`, name, arguments: args });
1328
+ }
1329
+ }
1330
+ if (!calls.length) {
1331
+ return { calls, remainingContent: content };
1332
+ }
1333
+ DSML_ANY_TAG_RE.lastIndex = 0;
1334
+ let first = -1;
1335
+ let last = -1;
1336
+ let tag;
1337
+ while ((tag = DSML_ANY_TAG_RE.exec(content)) !== null) {
1338
+ if (first === -1)
1339
+ first = tag.index;
1340
+ last = tag.index + tag[0].length;
1341
+ }
1342
+ const remaining = first === -1 ? content : (content.slice(0, first) + content.slice(last)).trim();
1343
+ return { calls, remainingContent: remaining.length ? remaining : null };
1344
+ }
1345
+ async function callOpenRouter(id, payload, requestTimeoutMs = 12e4, signal) {
1346
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1279
1347
  const response = await axios.post(
1280
1348
  "https://openrouter.ai/api/v1/chat/completions",
1281
1349
  payload,
@@ -1284,7 +1352,8 @@ async function callOpenRouter(id, payload, requestTimeoutMs = 12e4) {
1284
1352
  "content-type": "application/json",
1285
1353
  Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`
1286
1354
  },
1287
- timeout: requestTimeoutMs
1355
+ timeout: requestTimeoutMs,
1356
+ signal
1288
1357
  }
1289
1358
  );
1290
1359
  if (response.data.error) {
@@ -1307,38 +1376,47 @@ async function callOpenRouter(id, payload, requestTimeoutMs = 12e4) {
1307
1376
  });
1308
1377
  }
1309
1378
  }
1310
- if (!answer.content && !functionCalls.length) {
1379
+ let content = (_e = answer.content) != null ? _e : null;
1380
+ if (!functionCalls.length && content && DSML_ENVELOPE_RE.test(content)) {
1381
+ const { calls, remainingContent } = parseDsmlToolCalls(content);
1382
+ if (calls.length) {
1383
+ functionCalls.push(...calls);
1384
+ content = remainingContent;
1385
+ }
1386
+ }
1387
+ const hasUnparsedDsml = !!content && DSML_DELIMITER_RE.test(content);
1388
+ if (!functionCalls.length && (!content || hasUnparsedDsml)) {
1311
1389
  logger_default.error(
1312
1390
  id,
1313
- "OpenRouter: received message without content or function_call:",
1391
+ "OpenRouter: empty or unparseable completion:",
1314
1392
  JSON.stringify(response.data)
1315
1393
  );
1316
1394
  throw new Error(
1317
- "OpenRouter: received message without content or function_call"
1395
+ "OpenRouter: received message without usable content or function_call"
1318
1396
  );
1319
1397
  }
1320
1398
  return {
1321
1399
  role: "assistant",
1322
- content: answer.content || null,
1400
+ content: content || null,
1323
1401
  function_call: functionCalls[0] || null,
1324
1402
  function_calls: functionCalls,
1325
1403
  files: [],
1326
- reasoning: (_e = answer.reasoning) != null ? _e : void 0,
1327
- reasoningDetails: (_f = answer.reasoning_details) != null ? _f : void 0,
1404
+ reasoning: (_f = answer.reasoning) != null ? _f : void 0,
1405
+ reasoningDetails: (_g = answer.reasoning_details) != null ? _g : void 0,
1328
1406
  usage: response.data.usage ? {
1329
1407
  prompt_tokens: response.data.usage.prompt_tokens,
1330
1408
  completion_tokens: response.data.usage.completion_tokens,
1331
1409
  total_tokens: response.data.usage.total_tokens,
1332
- cached_tokens: (_h = (_g = response.data.usage.prompt_tokens_details) == null ? void 0 : _g.cached_tokens) != null ? _h : 0
1410
+ cached_tokens: (_i = (_h = response.data.usage.prompt_tokens_details) == null ? void 0 : _h.cached_tokens) != null ? _i : 0
1333
1411
  } : null
1334
1412
  };
1335
1413
  }
1336
- async function callOpenRouterWithRetries(id, payload, retries = 5, requestTimeoutMs = 12e4) {
1414
+ async function callOpenRouterWithRetries(id, payload, retries = 5, requestTimeoutMs = 12e4, signal) {
1337
1415
  return withRetries(
1338
1416
  id,
1339
1417
  "OpenRouter",
1340
- () => callOpenRouter(id, payload, requestTimeoutMs),
1341
- { retries }
1418
+ () => callOpenRouter(id, payload, requestTimeoutMs, signal),
1419
+ { retries, signal }
1342
1420
  );
1343
1421
  }
1344
1422
  var VALID_PROVIDERS = ["openai", "anthropic", "google", "groq", "openrouter"];
@@ -1379,11 +1457,12 @@ function parseModelString(model) {
1379
1457
  );
1380
1458
  }
1381
1459
  async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeoutMs = 15e3) {
1382
- var _a;
1460
+ var _a, _b;
1383
1461
  try {
1384
1462
  const { provider, modelId } = parseModelString(aiPayload.model);
1385
1463
  const routingPayload = { ...aiPayload, model: modelId };
1386
1464
  const requestTimeoutMs = (_a = aiPayload.requestTimeoutMs) != null ? _a : 12e4;
1465
+ const signal = aiPayload.signal;
1387
1466
  switch (provider) {
1388
1467
  case "anthropic":
1389
1468
  return await callAnthropicWithRetries(
@@ -1391,7 +1470,8 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
1391
1470
  await prepareAnthropicPayload(id, routingPayload),
1392
1471
  aiConfig,
1393
1472
  retries,
1394
- requestTimeoutMs
1473
+ requestTimeoutMs,
1474
+ signal
1395
1475
  );
1396
1476
  case "openai":
1397
1477
  return await callOpenAiWithRetries(
@@ -1400,31 +1480,37 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
1400
1480
  aiConfig,
1401
1481
  retries,
1402
1482
  chunkTimeoutMs,
1403
- requestTimeoutMs
1483
+ requestTimeoutMs,
1484
+ signal
1404
1485
  );
1405
1486
  case "groq":
1406
1487
  return await callGroqWithRetries(
1407
1488
  id,
1408
1489
  prepareGroqPayload(routingPayload),
1409
1490
  retries,
1410
- requestTimeoutMs
1491
+ requestTimeoutMs,
1492
+ signal
1411
1493
  );
1412
1494
  case "google":
1413
1495
  return await callGoogleAIWithRetries(
1414
1496
  id,
1415
1497
  await prepareGoogleAIPayload(id, routingPayload),
1416
1498
  retries,
1417
- requestTimeoutMs
1499
+ requestTimeoutMs,
1500
+ signal
1418
1501
  );
1419
1502
  case "openrouter":
1420
1503
  return await callOpenRouterWithRetries(
1421
1504
  id,
1422
1505
  prepareOpenRouterPayload(routingPayload),
1423
1506
  retries,
1424
- requestTimeoutMs
1507
+ requestTimeoutMs,
1508
+ signal
1425
1509
  );
1426
1510
  }
1427
1511
  } catch (error2) {
1512
+ if ((_b = aiPayload.signal) == null ? void 0 : _b.aborted)
1513
+ throw error2;
1428
1514
  if (aiPayload.fallbackModel) {
1429
1515
  logger_default.error(
1430
1516
  id,