@ykurilov/agent-chat-core 0.63.1 → 0.63.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @ykurilov/agent-chat-core
2
2
 
3
+ ## 0.63.2
4
+
5
+ ### Patch Changes
6
+
7
+ - c772243: Исчерпанный предел расходов ключа (OpenRouter 403 «Key limit exceeded», `limit_source: openrouter_key_limit`; бюджеты ключа у шлюзов — «ExceededBudget», «Budget has been exceeded») — теперь `insufficient_funds`, а не `invalid_key`: переход к запасному, пауза основного, человеку «кончились средства», громкая строка «исчерпан предел расходов ключа». Обычный 403 — как раньше.
8
+
3
9
  ## 0.63.1
4
10
 
5
11
  No changes in this release.
@@ -3331,7 +3331,8 @@ function sleep(ms, signal) {
3331
3331
 
3332
3332
  // src/provider-errors/classify-provider-error.ts
3333
3333
  var KEY_SIGNS = /api[ _-]?key|authenticat|unauthori[sz]ed|credential|access[ _-]?token|key (?:is )?(?:invalid|revoked|expired|disabled)/i;
3334
- var FUNDS_SIGNS = /key limit exceeded|insufficient (?:credits|funds|balance)/i;
3334
+ var KEY_LIMIT_SIGNS = /key limit exceeded|openrouter_key_limit|ExceededBudget|budget has been exceeded|(?:key|token) has (?:reached|exceeded) its (?:spend(?:ing)?|budget|usage) limit/i;
3335
+ var FUNDS_SIGNS = /insufficient (?:credits|funds|balance)/i;
3335
3336
  var MODERATION_SIGNS = /flagged|moderation|content[ _-]?policy|safety/i;
3336
3337
  var RATE_LIMIT_SIGNS = /rate.?limit|too many requests|throttl|please wait|ResourceExhausted/i;
3337
3338
  function classifyProviderError(error, provider) {
@@ -3342,6 +3343,7 @@ function classifyProviderError(error, provider) {
3342
3343
  for (const hint of provider?.errorHints ?? []) {
3343
3344
  if (hint.match.test(text)) return hint.kind;
3344
3345
  }
3346
+ if (KEY_LIMIT_SIGNS.test(text)) return "insufficient_funds";
3345
3347
  if (status === 401) return "invalid_key";
3346
3348
  if (status === 403) {
3347
3349
  if (KEY_SIGNS.test(text)) return "invalid_key";
@@ -3359,6 +3361,9 @@ function isAccessRefusal(error) {
3359
3361
  const cause = underlyingError(error);
3360
3362
  return errorStatusCode(cause) === 403 && !MODERATION_SIGNS.test(errorText(cause));
3361
3363
  }
3364
+ function isKeyLimit(error) {
3365
+ return KEY_LIMIT_SIGNS.test(errorText(underlyingError(error)));
3366
+ }
3362
3367
 
3363
3368
  // src/provider-errors/provider-failure-log.ts
3364
3369
  import { APICallError as APICallError3 } from "ai";
@@ -3405,14 +3410,15 @@ function createProviderOutages(options2) {
3405
3410
  return time < outage.pausedUntil || time < (outage.probeUntil ?? 0) ? outage.kind : void 0;
3406
3411
  };
3407
3412
  return {
3408
- report({ providerId, kind, fallbackProviderId, fallbacksPaused }) {
3413
+ report({ providerId, kind, fallbackProviderId, fallbacksPaused, keyLimit }) {
3409
3414
  const time = options2.now();
3410
3415
  outages.set(providerId, { kind, pausedUntil: time + PROVIDER_OUTAGE_PAUSE_MS });
3411
3416
  const last = alertedAt.get(providerId);
3412
3417
  if (last !== void 0 && time - last < PROVIDER_OUTAGE_ALERT_EVERY_MS) return;
3413
3418
  alertedAt.set(providerId, time);
3414
3419
  const route = fallbackProviderId !== void 0 ? `\u0445\u043E\u0434\u044B \u0438\u0434\u0443\u0442 \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u0430\u0441\u043D\u043E\u0439 ${fallbackProviderId}` : `${fallbacksPaused ? "\u0437\u0430\u043F\u0430\u0441\u043D\u044B\u0435 \u0442\u043E\u0436\u0435 \u043D\u0430 \u043F\u0430\u0443\u0437\u0435" : "\u0437\u0430\u043F\u0430\u0441\u043D\u043E\u0433\u043E \u043D\u0435\u0442"}, \u0445\u043E\u0434\u044B \u043F\u0430\u0434\u0430\u044E\u0442 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439`;
3415
- options2.logError(`[\u0412\u041D\u0418\u041C\u0410\u041D\u0418\u0415 \u043F\u0440\u043E\u0432\u0430\u0439\u0434\u0435\u0440] ${providerId}: ${SAID[kind]} \u2014 ${route}`);
3420
+ const said = keyLimit && kind === "insufficient_funds" ? "\u0438\u0441\u0447\u0435\u0440\u043F\u0430\u043D \u043F\u0440\u0435\u0434\u0435\u043B \u0440\u0430\u0441\u0445\u043E\u0434\u043E\u0432 \u043A\u043B\u044E\u0447\u0430" : SAID[kind];
3421
+ options2.logError(`[\u0412\u041D\u0418\u041C\u0410\u041D\u0418\u0415 \u043F\u0440\u043E\u0432\u0430\u0439\u0434\u0435\u0440] ${providerId}: ${said} \u2014 ${route}`);
3416
3422
  },
3417
3423
  pausedKind,
3418
3424
  admit(providerId) {
@@ -6788,6 +6794,7 @@ async function runTurn(turnInput, emitRaw) {
6788
6794
  outages.report({
6789
6795
  providerId,
6790
6796
  kind: outage,
6797
+ ...isKeyLimit(result.error) && { keyLimit: true },
6791
6798
  ...next.action === "fallback" ? { fallbackProviderId: next.providerId } : { fallbacksPaused: allFallbackIds.some((candidate) => candidate !== providerId && outages.pausedKind(candidate) !== void 0) }
6792
6799
  });
6793
6800
  }
@@ -7780,6 +7787,7 @@ async function* helperSteps(input) {
7780
7787
  outages.report({
7781
7788
  providerId,
7782
7789
  kind: outage,
7790
+ ...isKeyLimit(error) && { keyLimit: true },
7783
7791
  ...next.action === "fallback" ? { fallbackProviderId: next.providerId } : { fallbacksPaused: allFallbackIds.some((candidate) => candidate !== providerId && outages.pausedKind(candidate) !== void 0) }
7784
7792
  });
7785
7793
  }
@@ -14276,4 +14284,4 @@ export {
14276
14284
  InvalidWidgetAnswerError,
14277
14285
  createChatService
14278
14286
  };
14279
- //# sourceMappingURL=chunk-XQ5FJ2VT.js.map
14287
+ //# sourceMappingURL=chunk-4Y26SCCM.js.map