@genesislcap/ai-assistant 15.14.0 → 15.14.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.
@@ -1041,6 +1041,94 @@ function budgetExhaustedFrom(vendorLabel, payload, fallbackDetail) {
1041
1041
  });
1042
1042
  }
1043
1043
 
1044
+ // ../../foundation-ai/dist/esm/transports/provider-refused.js
1045
+ var PROVIDER_REFUSED_CODE = "PROVIDER_REFUSED";
1046
+ var DEFAULT_PROVIDER_REFUSED_MESSAGE = "AI requests are currently being refused by the provider. This isn't related to your account or your usage and needs no action from you \u2014 please contact your support team so it can be restored.";
1047
+ var ProviderRefusedError = class extends Error {
1048
+ constructor(vendorLabel, kind, upstreamStatus, upstreamType, detail) {
1049
+ super(`${vendorLabel} refused the request (${kind})` + (upstreamStatus != null ? ` \u2014 HTTP ${upstreamStatus}` : "") + (upstreamType ? ` ${upstreamType}` : "") + (detail ? `: ${detail}` : "") + ". Retrying will not clear this \u2014 the provider account must be fixed.");
1050
+ this.vendorLabel = vendorLabel;
1051
+ this.kind = kind;
1052
+ this.upstreamStatus = upstreamStatus;
1053
+ this.upstreamType = upstreamType;
1054
+ this.detail = detail;
1055
+ this.name = "ProviderRefusedError";
1056
+ }
1057
+ };
1058
+ var ANTHROPIC_SPEND_PHRASES = Object.freeze([
1059
+ /credit balance/i,
1060
+ /usage limit/i,
1061
+ /spend limit/i,
1062
+ /insufficient (credit|funds|balance)/i
1063
+ ]);
1064
+ var ANTHROPIC_AUTH_TYPES = Object.freeze([
1065
+ "authentication_error",
1066
+ "permission_error"
1067
+ ]);
1068
+ function anthropicErrorBody(payload) {
1069
+ var _a;
1070
+ const outer = typeof payload === "object" && payload !== null ? payload : {};
1071
+ for (const candidate of [
1072
+ outer.error,
1073
+ (_a = outer.details) === null || _a === void 0 ? void 0 : _a.error
1074
+ ]) {
1075
+ if (typeof candidate === "object" && candidate !== null) {
1076
+ const { type, message } = candidate;
1077
+ return {
1078
+ type: typeof type === "string" ? type : void 0,
1079
+ message: typeof message === "string" ? message : void 0
1080
+ };
1081
+ }
1082
+ }
1083
+ return void 0;
1084
+ }
1085
+ function statedKind(payload) {
1086
+ const outer = typeof payload === "object" && payload !== null ? payload : {};
1087
+ const nested = typeof outer.details === "object" && outer.details !== null ? outer.details : {};
1088
+ for (const candidate of [outer.kind, nested.kind]) {
1089
+ if (candidate === "auth" || candidate === "spend")
1090
+ return candidate;
1091
+ }
1092
+ return void 0;
1093
+ }
1094
+ function kindFromEnvelopeType(payload) {
1095
+ const body = anthropicErrorBody(payload);
1096
+ if (!(body === null || body === void 0 ? void 0 : body.type))
1097
+ return void 0;
1098
+ if (ANTHROPIC_AUTH_TYPES.includes(body.type))
1099
+ return "auth";
1100
+ if (body.type === "billing_error")
1101
+ return "spend";
1102
+ return void 0;
1103
+ }
1104
+ function providerRefusalOf(vendor, code, payload) {
1105
+ var _a, _b;
1106
+ if (code === PROVIDER_REFUSED_CODE) {
1107
+ return (_b = (_a = statedKind(payload)) !== null && _a !== void 0 ? _a : kindFromEnvelopeType(payload)) !== null && _b !== void 0 ? _b : "spend";
1108
+ }
1109
+ if (vendor !== "anthropic")
1110
+ return void 0;
1111
+ const structural = kindFromEnvelopeType(payload);
1112
+ if (structural)
1113
+ return structural;
1114
+ const body = anthropicErrorBody(payload);
1115
+ if ((body === null || body === void 0 ? void 0 : body.type) === "invalid_request_error" && body.message) {
1116
+ const message = body.message;
1117
+ if (ANTHROPIC_SPEND_PHRASES.some((phrase) => phrase.test(message)))
1118
+ return "spend";
1119
+ }
1120
+ return void 0;
1121
+ }
1122
+ function providerRefusedFrom(vendorLabel, kind, upstreamStatus, payload, fallbackDetail) {
1123
+ var _a;
1124
+ const body = anthropicErrorBody(payload);
1125
+ return new ProviderRefusedError(vendorLabel, kind, upstreamStatus, body === null || body === void 0 ? void 0 : body.type, (_a = body === null || body === void 0 ? void 0 : body.message) !== null && _a !== void 0 ? _a : fallbackDetail);
1126
+ }
1127
+ function vendorOfTransportLabel(vendorLabel) {
1128
+ const entry = Object.entries(VENDOR_LABELS).find(([, label]) => label === vendorLabel);
1129
+ return entry === null || entry === void 0 ? void 0 : entry[0];
1130
+ }
1131
+
1044
1132
  // ../../foundation-ai/dist/esm/types/config.types.js
1045
1133
  var SUPPORTED_GEMINI_MODEL_IDS = [
1046
1134
  "gemini-2.5-pro",
@@ -1459,13 +1547,81 @@ function readFramedBody(stream, onChunk, vendorLabel, stallTimeout) {
1459
1547
  });
1460
1548
  }
1461
1549
 
1550
+ // ../../foundation-ai/dist/esm/transports/retry-hints.js
1551
+ var MAX_SERVER_REQUESTED_BACKOFF_MS = 6e4;
1552
+ var MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS = 12e4;
1553
+ var SHOULD_RETRY_HEADER = "x-should-retry";
1554
+ var MS_PER_SECOND = 1e3;
1555
+ function shouldNotRetry(headers) {
1556
+ var _a;
1557
+ const value = (_a = headers === null || headers === void 0 ? void 0 : headers.get) === null || _a === void 0 ? void 0 : _a.call(headers, SHOULD_RETRY_HEADER);
1558
+ return typeof value === "string" && value.trim().toLowerCase() === "false";
1559
+ }
1560
+ function retryAfterMs(headers) {
1561
+ var _a;
1562
+ const raw = (_a = headers === null || headers === void 0 ? void 0 : headers.get) === null || _a === void 0 ? void 0 : _a.call(headers, "retry-after");
1563
+ if (typeof raw !== "string" || raw.trim() === "")
1564
+ return void 0;
1565
+ const seconds = Number(raw.trim());
1566
+ if (Number.isFinite(seconds))
1567
+ return Math.max(0, seconds * MS_PER_SECOND);
1568
+ const at = Date.parse(raw);
1569
+ if (Number.isNaN(at))
1570
+ return void 0;
1571
+ return Math.max(0, at - Date.now());
1572
+ }
1573
+ function retryInfoMs(payload) {
1574
+ const outer = typeof payload === "object" && payload !== null ? payload : {};
1575
+ const framed = typeof outer.details === "object" && outer.details !== null ? outer.details : void 0;
1576
+ for (const holder of [outer.error, framed === null || framed === void 0 ? void 0 : framed.error]) {
1577
+ const details = holder === null || holder === void 0 ? void 0 : holder.details;
1578
+ if (!Array.isArray(details))
1579
+ continue;
1580
+ for (const entry of details) {
1581
+ const type = entry === null || entry === void 0 ? void 0 : entry["@type"];
1582
+ if (typeof type !== "string" || !type.endsWith("google.rpc.RetryInfo"))
1583
+ continue;
1584
+ const delay = entry === null || entry === void 0 ? void 0 : entry.retryDelay;
1585
+ if (typeof delay !== "string")
1586
+ continue;
1587
+ const seconds = Number(delay.replace(/s$/, ""));
1588
+ if (Number.isFinite(seconds) && seconds >= 0)
1589
+ return seconds * MS_PER_SECOND;
1590
+ }
1591
+ }
1592
+ return void 0;
1593
+ }
1594
+ function resolveBackoffMs(attempt, baseMs, serverMs, serverAllowanceMs = Number.POSITIVE_INFINITY) {
1595
+ const ladder = baseMs * Math.pow(2, attempt);
1596
+ if (serverMs == null || !Number.isFinite(serverMs))
1597
+ return ladder;
1598
+ const honoured = Math.min(serverMs, MAX_SERVER_REQUESTED_BACKOFF_MS, Math.max(0, serverAllowanceMs));
1599
+ return Math.max(ladder, honoured);
1600
+ }
1601
+ function serverBackoffSpentMs(resolvedMs, ladderMs) {
1602
+ return Math.max(0, resolvedMs - ladderMs);
1603
+ }
1604
+
1462
1605
  // ../../foundation-ai/dist/esm/transports/post-with-retry.js
1463
1606
  var MAX_RETRIES = 5;
1464
1607
  function postWithRetry(options) {
1465
1608
  return __awaiter(this, void 0, void 0, function* () {
1466
1609
  var _a, _b, _c, _d, _e, _f, _g;
1467
1610
  const { url, headers, body, credentials, vendorLabel, retryableStatuses, timeout, stallTimeout, backoffBaseMs, signal } = options;
1468
- const backoff = (attempt) => abortableDelay(backoffBaseMs * (1 << attempt), signal);
1611
+ const vendor = vendorOfTransportLabel(vendorLabel);
1612
+ let serverBackoffSpent = 0;
1613
+ const backoff = (attempt, serverMs) => {
1614
+ const ladderMs = backoffBaseMs * Math.pow(2, attempt);
1615
+ const allowanceMs = MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS - serverBackoffSpent;
1616
+ const waitMs = resolveBackoffMs(attempt, backoffBaseMs, serverMs, allowanceMs);
1617
+ serverBackoffSpent += serverBackoffSpentMs(waitMs, ladderMs);
1618
+ if (serverMs != null && waitMs > ladderMs) {
1619
+ logger.warn(`${vendorLabel}Transport: honouring the server's requested retry delay (${Math.round(waitMs)}ms, asked ${Math.round(serverMs)}ms)`);
1620
+ } else if (serverMs != null && serverMs > ladderMs) {
1621
+ logger.warn(`${vendorLabel}Transport: declining the server's requested retry delay (asked ${Math.round(serverMs)}ms; the ${MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS}ms sequence allowance is spent) \u2014 using the ladder's ${Math.round(waitMs)}ms`);
1622
+ }
1623
+ return abortableDelay(waitMs, signal);
1624
+ };
1469
1625
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt += 1) {
1470
1626
  const timeoutController = new AbortController();
1471
1627
  const startedAt = performance.now();
@@ -1499,13 +1655,18 @@ function postWithRetry(options) {
1499
1655
  if (!response.ok) {
1500
1656
  const errText = yield response.text();
1501
1657
  const parsed = parseJsonOrUndefined(errText);
1658
+ const refusal = providerRefusalOf(vendor, codeOf(parsed), parsed);
1659
+ if (refusal) {
1660
+ throw providerRefusedFrom(vendorLabel, refusal, response.status, parsed, errText || void 0);
1661
+ }
1502
1662
  if (isBudgetRejection(response.status, codeOf(parsed))) {
1503
1663
  throw budgetExhaustedFrom(vendorLabel, parsed, errText || void 0);
1504
1664
  }
1505
- if (retryableStatuses.includes(response.status) && attempt < MAX_RETRIES) {
1665
+ const refusedRetry = shouldNotRetry(response.headers);
1666
+ if (retryableStatuses.includes(response.status) && !refusedRetry && attempt < MAX_RETRIES) {
1506
1667
  logger.warn(`${vendorLabel}Transport: retryable status ${response.status}, retrying (attempt ${attempt + 1}/${MAX_RETRIES})`);
1507
1668
  clearTimeout(timeoutId);
1508
- yield backoff(attempt);
1669
+ yield backoff(attempt, retryAfterMs(response.headers) || retryInfoMs(parsed));
1509
1670
  continue;
1510
1671
  }
1511
1672
  throw new Error(`${vendorLabel} request error ${response.status}: ${errText}`);
@@ -1518,13 +1679,17 @@ function postWithRetry(options) {
1518
1679
  if (frame.code === "UPSTREAM_STALLED") {
1519
1680
  throw new DOMException(`${vendorLabel} request stalled: ${(_f = frame.error) !== null && _f !== void 0 ? _f : "no upstream data"}`, "TimeoutError");
1520
1681
  }
1682
+ const framedRefusal = providerRefusalOf(vendor, frame.code, frame);
1683
+ if (framedRefusal) {
1684
+ throw providerRefusedFrom(vendorLabel, framedRefusal, frame.status, frame, frame.error);
1685
+ }
1521
1686
  if (isBudgetRejection(frame.status, frame.code)) {
1522
1687
  throw budgetExhaustedFrom(vendorLabel, frame);
1523
1688
  }
1524
1689
  if (retryableStatuses.includes(frame.status) && attempt < MAX_RETRIES) {
1525
1690
  logger.warn(`${vendorLabel}Transport: retryable status ${frame.status} (err frame), retrying (attempt ${attempt + 1}/${MAX_RETRIES})`);
1526
1691
  clearTimeout(timeoutId);
1527
- yield backoff(attempt);
1692
+ yield backoff(attempt, retryInfoMs(frame));
1528
1693
  continue;
1529
1694
  }
1530
1695
  throw new Error(`${vendorLabel} request error ${frame.status}: ${(_g = frame.error) !== null && _g !== void 0 ? _g : JSON.stringify(frame.details)}`);
@@ -3607,6 +3772,12 @@ function accumulate(messages, into) {
3607
3772
  var TOOL_FOLD_SYMBOL = Symbol("toolFold");
3608
3773
 
3609
3774
  // src/components/chat-driver/chat-driver.ts
3775
+ var providerRefusedDetailOf = (e) => ({
3776
+ vendorLabel: e.vendorLabel,
3777
+ kind: e.kind,
3778
+ ...e.upstreamStatus != null ? { upstreamStatus: e.upstreamStatus } : {},
3779
+ ...e.upstreamType ? { upstreamType: e.upstreamType } : {}
3780
+ });
3610
3781
  var budgetDetailOf = (e) => {
3611
3782
  const vendor = vendorTypeOfLabel(e.vendorLabel) ?? vendorTypeOfLabel(e.serverVendor);
3612
3783
  if (e.budgetUsd == null && e.spentUsd == null && !vendor) return void 0;
@@ -3802,6 +3973,16 @@ var ChatDriver = class _ChatDriver extends EventTarget {
3802
3973
  * picked up on the next turn.
3803
3974
  */
3804
3975
  this.resolvedStatusCache = /* @__PURE__ */ new Map();
3976
+ /**
3977
+ * A provider refusal was observed this turn, so the tool loop must not call the model again
3978
+ * (GENC-1506).
3979
+ *
3980
+ * Exists for the SUB-AGENT path only, exactly like `budgetExhaustedThisTurn`: this driver's own
3981
+ * refusal returns straight out of the catch, whereas a child's refusal reaches the parent as a tool
3982
+ * result, and without this flag the loop would issue another call into the same wall — N batched
3983
+ * children costing N doomed calls plus a doomed parent one.
3984
+ */
3985
+ this.providerRefusedThisTurn = false;
3805
3986
  /**
3806
3987
  * Set the moment a budget wall is observed anywhere in this turn — this
3807
3988
  * driver's own 402, or a sub-agent's (which surfaces here only as a
@@ -3829,13 +4010,15 @@ var ChatDriver = class _ChatDriver extends EventTarget {
3829
4010
  maxTurnSnapshots = DEFAULT_MAX_TURN_SNAPSHOTS,
3830
4011
  sessionKey = "",
3831
4012
  activityBus = NOOP_ACTIVITY_BUS,
3832
- budgetExhaustedMessage
4013
+ budgetExhaustedMessage,
4014
+ providerRefusedMessage
3833
4015
  } = config;
3834
4016
  this.maxToolIterations = maxToolIterations;
3835
4017
  this.condenseBatchCalls = condenseBatchCalls;
3836
4018
  this.sessionKey = sessionKey;
3837
4019
  this.activityBus = activityBus;
3838
4020
  this.budgetExhaustedMessageOverride = budgetExhaustedMessage;
4021
+ this.providerRefusedMessageOverride = providerRefusedMessage;
3839
4022
  if (typeof toolHandlers === "function") {
3840
4023
  this.toolHandlersFactory = toolHandlers;
3841
4024
  this.toolHandlers = {};
@@ -3942,9 +4125,14 @@ var ChatDriver = class _ChatDriver extends EventTarget {
3942
4125
  * (rather than set to `undefined`) so a happy-path result stays byte-identical to
3943
4126
  * the historical `{ reason: 'done' }`.
3944
4127
  */
3945
- turnDone(failureReason, budget) {
4128
+ turnDone(failureReason, budget, providerRefused) {
3946
4129
  if (!failureReason) return { reason: "done" };
3947
- return budget ? { reason: "done", failureReason, budget } : { reason: "done", failureReason };
4130
+ return {
4131
+ reason: "done",
4132
+ failureReason,
4133
+ ...budget ? { budget } : {},
4134
+ ...providerRefused ? { providerRefused } : {}
4135
+ };
3948
4136
  }
3949
4137
  /**
3950
4138
  * Terminal budget outcome for a wall hit **outside** the tool loop — today,
@@ -3999,6 +4187,42 @@ var ChatDriver = class _ChatDriver extends EventTarget {
3999
4187
  this.appendToHistory({ role: "assistant", content: this.budgetExhaustedBubble(e) });
4000
4188
  return this.turnDone("budget-exhausted", budgetDetailOf(e));
4001
4189
  }
4190
+ /**
4191
+ * The sentence shown when the upstream provider refuses (GENC-1506).
4192
+ *
4193
+ * Deliberately far simpler than `budgetExhaustedBubble`: no vendor name, no figures, no
4194
+ * switch-provider advice, and no branching on `kind`. The copy is cause-free by design — a user who
4195
+ * can see their own remaining spend must not be told about a limit, and we must not imply the bill
4196
+ * has gone unpaid — so there is nothing here to compose. A host override wins verbatim.
4197
+ */
4198
+ providerRefusedBubble() {
4199
+ return this.providerRefusedMessageOverride ?? DEFAULT_PROVIDER_REFUSED_MESSAGE;
4200
+ }
4201
+ /**
4202
+ * Terminal provider-refusal outcome. Mirrors `reportBudgetExhausted` so the two walls behave
4203
+ * identically from the caller's side, while keeping their diagnostics distinct.
4204
+ *
4205
+ * `kind` reaches the debug log and the result but never the transcript: it is what lets an operator
4206
+ * tell "top up the account" from "rotate the key", and with cause-free user copy this is the only
4207
+ * place that distinction survives.
4208
+ */
4209
+ reportProviderRefused(e) {
4210
+ const detail = providerRefusedDetailOf(e);
4211
+ this.providerRefusedThisTurn = true;
4212
+ this.providerRefusedDetail = detail;
4213
+ logger2.error("ChatDriver: provider refused the request", e);
4214
+ recordTurnError(this.sessionKey, "provider-refused", {
4215
+ agent: this.activeAgentName,
4216
+ provider: this.lastResolvedProviderName,
4217
+ vendor: vendorTypeOfLabel(e.vendorLabel) ?? this.lastResolvedProvider,
4218
+ kind: e.kind,
4219
+ upstreamStatus: e.upstreamStatus,
4220
+ upstreamType: e.upstreamType,
4221
+ isSubAgent: this.isSubAgent
4222
+ });
4223
+ this.appendToHistory({ role: "assistant", content: this.providerRefusedBubble() });
4224
+ return this.turnDone("provider-refused", void 0, detail);
4225
+ }
4002
4226
  /** The typed failure reason on a loop result, or `undefined` for a clean turn / handoff. */
4003
4227
  static failureReasonOf(result) {
4004
4228
  return result.reason === "done" ? result.failureReason : void 0;
@@ -4222,9 +4446,13 @@ var ChatDriver = class _ChatDriver extends EventTarget {
4222
4446
  * under a separate session key, so recording here would orphan the event off
4223
4447
  * the user-visible debug-log timeline.)
4224
4448
  */
4225
- failSubAgent(reason, budget) {
4449
+ failSubAgent(reason, budget, providerRefused) {
4226
4450
  if (!this.isSubAgent || this.subAgentFailure) return;
4227
- this.subAgentFailure = budget ? { reason, budget } : { reason };
4451
+ this.subAgentFailure = {
4452
+ reason,
4453
+ ...budget ? { budget } : {},
4454
+ ...providerRefused ? { providerRefused } : {}
4455
+ };
4228
4456
  }
4229
4457
  /**
4230
4458
  * Returns true if `releaseAgent` was called during the most recent turn.
@@ -4683,6 +4911,8 @@ Output format (strict):
4683
4911
  this.budgetExhaustedThisTurn = false;
4684
4912
  this.budgetWallDetail = void 0;
4685
4913
  this.budgetWallViaSubAgent = false;
4914
+ this.providerRefusedThisTurn = false;
4915
+ this.providerRefusedDetail = void 0;
4686
4916
  this.appendToHistory({ role: "user", content: userInput, attachments });
4687
4917
  this.turnStartedAt = Date.now();
4688
4918
  recordMetaEvent(this.sessionKey, "turn.start", {
@@ -4927,6 +5157,10 @@ Output format (strict):
4927
5157
  this.budgetWallViaSubAgent = true;
4928
5158
  this.budgetWallDetail ??= failure?.budget;
4929
5159
  }
5160
+ if (reason === "provider_refused") {
5161
+ this.providerRefusedThisTurn = true;
5162
+ this.providerRefusedDetail ??= failure?.providerRefused;
5163
+ }
4930
5164
  return { outcome: { ok: false, reason }, trace };
4931
5165
  }
4932
5166
  /**
@@ -4942,6 +5176,8 @@ Output format (strict):
4942
5176
  this.budgetExhaustedThisTurn = false;
4943
5177
  this.budgetWallDetail = void 0;
4944
5178
  this.budgetWallViaSubAgent = false;
5179
+ this.providerRefusedThisTurn = false;
5180
+ this.providerRefusedDetail = void 0;
4945
5181
  this.turnStartedAt = Date.now();
4946
5182
  recordMetaEvent(this.sessionKey, "turn.start", {
4947
5183
  phase: "continueFromHistory",
@@ -5131,6 +5367,22 @@ Output format (strict):
5131
5367
  if (this.turnController.signal.aborted) {
5132
5368
  return this.completeAbortedTurn();
5133
5369
  }
5370
+ if (this.providerRefusedThisTurn) {
5371
+ logger2.error("ChatDriver: ending the turn \u2014 a sub-agent hit the provider wall");
5372
+ recordTurnError(this.sessionKey, "provider-refused", {
5373
+ agent: this.activeAgentName,
5374
+ provider: this.lastResolvedProviderName,
5375
+ kind: this.providerRefusedDetail?.kind,
5376
+ via: "sub-agent",
5377
+ isSubAgent: this.isSubAgent
5378
+ });
5379
+ if (this.isSubAgent) {
5380
+ this.failSubAgent("provider_refused", void 0, this.providerRefusedDetail);
5381
+ } else {
5382
+ this.appendToHistory({ role: "assistant", content: this.providerRefusedBubble() });
5383
+ }
5384
+ return this.turnDone("provider-refused", void 0, this.providerRefusedDetail);
5385
+ }
5134
5386
  if (this.budgetExhaustedThisTurn) {
5135
5387
  logger2.error("ChatDriver: ending the turn \u2014 a sub-agent hit the AI budget wall");
5136
5388
  recordTurnError(this.sessionKey, "budget-exhausted", {
@@ -5358,6 +5610,24 @@ ${tailBody}
5358
5610
  }
5359
5611
  return this.turnDone("response-truncated");
5360
5612
  }
5613
+ if (e instanceof ProviderRefusedError) {
5614
+ if (this.isSubAgent) {
5615
+ logger2.error("ChatDriver: provider refused the request", e);
5616
+ recordTurnError(this.sessionKey, "provider-refused", {
5617
+ agent: this.activeAgentName,
5618
+ provider: this.lastResolvedProviderName,
5619
+ vendor: vendorTypeOfLabel(e.vendorLabel) ?? this.lastResolvedProvider,
5620
+ kind: e.kind,
5621
+ upstreamStatus: e.upstreamStatus,
5622
+ upstreamType: e.upstreamType,
5623
+ isSubAgent: true
5624
+ });
5625
+ const detail = providerRefusedDetailOf(e);
5626
+ this.failSubAgent("provider_refused", void 0, detail);
5627
+ return this.turnDone("provider-refused", void 0, detail);
5628
+ }
5629
+ return this.reportProviderRefused(e);
5630
+ }
5361
5631
  if (e instanceof BudgetExhaustedError) {
5362
5632
  this.budgetExhaustedThisTurn = true;
5363
5633
  this.budgetWallDetail = budgetDetailOf(e);
@@ -6714,6 +6984,7 @@ export {
6714
6984
  AnthropicProvider,
6715
6985
  AnthropicTransport,
6716
6986
  ChatDriver,
6987
+ DEFAULT_PROVIDER_REFUSED_MESSAGE,
6717
6988
  GEMINI_CACHED_INPUT_MULTIPLIER,
6718
6989
  GEMINI_LONG_CONTEXT_THRESHOLD,
6719
6990
  GeminiProvider,
@@ -6721,6 +6992,8 @@ export {
6721
6992
  MutableAIProviderRegistry,
6722
6993
  NOOP_ACTIVITY_BUS,
6723
6994
  OrchestratingDriver,
6995
+ PROVIDER_REFUSED_CODE,
6996
+ ProviderRefusedError,
6724
6997
  REQUEST_CONTINUATION_TOOL,
6725
6998
  SUPPORTED_ANTHROPIC_MODEL_IDS,
6726
6999
  SUPPORTED_GEMINI_MODEL_IDS,