@xiaoso/dsh-tool-plus 0.1.6 → 0.1.7-beta.0

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.
Files changed (119) hide show
  1. package/THIRD_PARTY_NOTICES.md +9 -3
  2. package/lib/{abort-Cwwm4Err.mjs → abort-Caqff3M6.mjs} +2 -2
  3. package/lib/alibaba-coding-plan-DTupMiAi.mjs +73 -0
  4. package/lib/alibaba-token-plan-CHGyWOfX.mjs +46 -0
  5. package/lib/alibaba-token-plan-Dj3OZhEE.mjs +82 -0
  6. package/lib/{amazon-bedrock-TVMpUTRG.mjs → amazon-bedrock-DbFSYXfJ.mjs} +117 -38
  7. package/lib/{anthropic-BL6LFDQS.mjs → anthropic-CTJ3IQVa.mjs} +675 -166
  8. package/lib/anthropic-CXfWlp-x.mjs +105 -0
  9. package/lib/{aws-credentials-B20dliS7.mjs → anthropic-wire-CKuhDwZ1.mjs} +74 -14
  10. package/lib/{api-key-login-CIDnXeYd.mjs → api-key-validation-CGCJFbFr.mjs} +27 -68
  11. package/lib/{azure-openai-responses-BkhsLmN3.mjs → azure-openai-responses-ChFbWaGj.mjs} +27 -16
  12. package/lib/{browser-render-CmgvSNte.mjs → browser-render-9o0Rknop.mjs} +4 -4
  13. package/lib/bun-shim.mjs +71 -2
  14. package/lib/{bundled-references-ChZSPDFw.mjs → bundled-references-DY3EJxZV.mjs} +6 -5
  15. package/lib/cline-pass-Bwg3esu9.mjs +44 -0
  16. package/lib/cloudflare-ai-gateway-BupNXyKK.mjs +35 -0
  17. package/lib/cloudflare-ai-gateway-EWo0VkP5.mjs +44 -0
  18. package/lib/collapse-DOR8sOGf.mjs +2304 -0
  19. package/lib/coreweave-C82HrLpb.mjs +31 -0
  20. package/lib/coreweave-Ct8cF-da.mjs +14 -0
  21. package/lib/{cursor-B6HcmplF.mjs → cursor-B95LzVWV.mjs} +11 -3
  22. package/lib/{cursor-CRpLpaZ3.mjs → cursor-DJV_dcgB.mjs} +887 -1784
  23. package/lib/{cursor-B8m6SqAH.mjs → cursor-LKGjucn2.mjs} +48 -38
  24. package/lib/cursor-proto-B8Wj8bv9.mjs +10513 -0
  25. package/lib/{deterministic-id-D-yIV_eI.mjs → deterministic-id-CUEIMSqR.mjs} +1 -1
  26. package/lib/devin-BMTdx_hx.mjs +316 -0
  27. package/lib/{devin-DUAfvBsW.mjs → devin-DSp0Rw_E.mjs} +172 -86
  28. package/lib/devin-ExGIghmx.mjs +69 -0
  29. package/lib/devin-proto-Br8fdyNl.mjs +2888 -0
  30. package/lib/{dom-CawWi8fa.mjs → dom-DG3sPESc.mjs} +8 -8
  31. package/lib/effort-BdtQMN-_.mjs +23 -0
  32. package/lib/{error-C-f_Wnw4.mjs → error-CORgGg5a.mjs} +275 -154
  33. package/lib/{event-stream-Dh2guZxS.mjs → event-stream-ulcDenZD.mjs} +20 -4
  34. package/lib/{gemini-headers-DKUShltF.mjs → gemini-headers-Co9cVvex.mjs} +2 -2
  35. package/lib/{github-copilot-suDymKrx.mjs → github-copilot-Dstq1D3s.mjs} +69 -29
  36. package/lib/github-copilot-headers-DOh1gt_w.mjs +312 -0
  37. package/lib/gitlab-duo-DSCMrU0m.mjs +11 -0
  38. package/lib/google-CtsKkOQK.mjs +38 -0
  39. package/lib/google-antigravity-z-5KsEci.mjs +252 -0
  40. package/lib/{google-auth-DYJLM792.mjs → google-auth-ieLBaneO.mjs} +4 -4
  41. package/lib/{google-gemini-cli-8BT513Ul.mjs → google-gemini-cli-C6NE5mWz.mjs} +28 -54
  42. package/lib/{google-gemini-cli-D6cSmfvB.mjs → google-gemini-cli-CAIPSl7e.mjs} +23 -29
  43. package/lib/google-oauth-shared-DhMllAkt.mjs +53 -0
  44. package/lib/{google-shared-CVbHK5vZ.mjs → google-shared-B0aNCYEH.mjs} +140 -44
  45. package/lib/{google-validation-Cgbn3tWJ.mjs → google-validation-BEkNs-Bx.mjs} +1 -1
  46. package/lib/{google-vertex-Bui-ypAe.mjs → google-vertex-Bbd1tYNc.mjs} +8 -8
  47. package/lib/hosts-00rjRzUD.mjs +203 -0
  48. package/lib/id-AL5obQzR.mjs +71 -0
  49. package/lib/{idle-iterator-CYAxUkSD.mjs → idle-iterator-DlUkEfzW.mjs} +3 -3
  50. package/lib/index.mjs +587 -5266
  51. package/lib/kilo-ChJL54wq.mjs +81 -0
  52. package/lib/kimi-C2c_Zq8A.mjs +67 -0
  53. package/lib/{launch-BmgEUycu.mjs → launch-DKDH71En.mjs} +1 -1
  54. package/lib/markit-CmRfm4E2.mjs +9885 -0
  55. package/lib/models-DnXMYGcJ.mjs +381604 -0
  56. package/lib/muse-code-Di1VZmB1.mjs +143 -0
  57. package/lib/{ollama-Df9ce-Cp.mjs → ollama-B8ic3sEp.mjs} +15 -30
  58. package/lib/{openai-codex-CAVI3Me-.mjs → openai-codex-DuJNC99x.mjs} +29 -99
  59. package/lib/{openai-codex-responses-BcnOotRB.mjs → openai-codex-responses-BL29nh9K.mjs} +204 -116
  60. package/lib/{openai-completions-Bq4WT47M.mjs → openai-completions-BK2f2dBv.mjs} +152 -82
  61. package/lib/openai-configuration-update-xMYUjaK_.mjs +150 -0
  62. package/lib/{openai-reasoning-fallback-DXsfiSXO.mjs → openai-reasoning-fallback-BdB3RCbj.mjs} +106 -12
  63. package/lib/{openai-responses-Mq_-PjvE.mjs → openai-responses-CGQPlIIy.mjs} +76 -82
  64. package/lib/{perplexity-XgLF73E7.mjs → perplexity-TBjz3VMB.mjs} +52 -9
  65. package/lib/{pkce-BlQikGPu.mjs → pkce-BYjmugmw.mjs} +1 -1
  66. package/lib/protobuf-aab1UGVn.mjs +717 -0
  67. package/lib/{provider-response-C6vcbQyO.mjs → provider-response-SqKSkkUc.mjs} +1 -1
  68. package/lib/{proxy-D9lm7ONA.mjs → proxy-5nWqRL1f.mjs} +45 -5
  69. package/lib/{readability-Cpm-ocau.mjs → readability-uGhqb4GC.mjs} +2 -2
  70. package/lib/reference-CtvM4zLU.mjs +114 -0
  71. package/lib/{request-debug-HJMoJncL.mjs → request-debug-NQN0BjHH.mjs} +1 -1
  72. package/lib/{sanitize-text-CfcXzw5X.mjs → sanitize-text-BCf5KmCf.mjs} +1 -1
  73. package/lib/{scrapers-Cg5w77td.mjs → scrapers-D8oWspgW.mjs} +12 -12
  74. package/lib/{src-BcD0_rQR.mjs → src-BwW51vA5.mjs} +979 -388
  75. package/lib/{sse-debug-CYdjOC96.mjs → sse-debug-B-tkLCPW.mjs} +1 -1
  76. package/lib/{stream-Bjq8wjfr.mjs → stream-B_7qN-bA.mjs} +3802 -2623
  77. package/lib/stream-markup-healing-DKT1lnkW.mjs +267 -0
  78. package/lib/{strict-tool-validation-imVLUcbI.mjs → strict-tool-validation-CBTz1dAA.mjs} +2 -2
  79. package/lib/taxonomy-DSIM99rS.mjs +15392 -0
  80. package/lib/{stream-markup-healing-DZ6bVDxH.mjs → thinking-CiLa2LFB.mjs} +31 -186
  81. package/lib/{turndown-DN7ByzEI.mjs → turndown-DrX1M4WG.mjs} +4 -4
  82. package/lib/{type-guards-B9VVjRDK.mjs → type-guards-CttAANEx.mjs} +1 -1
  83. package/lib/{types-DX_bvuus.mjs → types-PVueGi9S.mjs} +2 -2
  84. package/lib/{utils-C-dSORPa.mjs → utils-CCfhUQen.mjs} +2364 -2676
  85. package/lib/{utils-Cp2Mxf_U.mjs → utils-CUPhpw9A.mjs} +413 -134
  86. package/lib/{utils-CQHPEQ3W.mjs → utils-DeWqNWV8.mjs} +2 -2
  87. package/lib/{vision-guard-mBmtAHx0.mjs → vision-guard-_XwsL1DF.mjs} +14 -29
  88. package/lib/xai-oauth-CXhnz0gO.mjs +210 -0
  89. package/lib/{xiaomi-7mE345KX.mjs → xiaomi-psoUItal.mjs} +8 -37
  90. package/lib/{zai-CeNpMV3W.mjs → zai-ApJ8HBgT.mjs} +8 -71
  91. package/lib/{zip-BK7UHCwX.mjs → zip-Kd602XNe.mjs} +1 -1
  92. package/package.json +11 -11
  93. package/presets/package.json +1 -1
  94. package/presets/tool-plus-ptc/agent.cordis.yml +1 -1
  95. package/presets/tool-plus-standard/agent.cordis.yml +1 -1
  96. package/lib/agent_pb-Rizyt9Zg.mjs +0 -805
  97. package/lib/anthropic-CDmj476p.mjs +0 -262
  98. package/lib/api_server_pb-CDZgLMta.mjs +0 -252
  99. package/lib/callback-server-CFJK-jvK.mjs +0 -398
  100. package/lib/codex-P1dGpX7G.mjs +0 -54
  101. package/lib/device-code-CuXTWYwY.mjs +0 -51
  102. package/lib/devin-BcQwht1W.mjs +0 -114
  103. package/lib/devin-BvMfGevz.mjs +0 -95
  104. package/lib/github-copilot-B3kQl0g0.mjs +0 -104
  105. package/lib/gitlab-duo-BriUTP8k.mjs +0 -155
  106. package/lib/gitlab-duo-workflow-wK5Ljzmc.mjs +0 -91
  107. package/lib/google-CE5tFDod.mjs +0 -30
  108. package/lib/google-antigravity-C1jgNljz.mjs +0 -198
  109. package/lib/google-oauth-shared-BLVTvokk.mjs +0 -147
  110. package/lib/grammar-D-NqNUxQ.mjs +0 -49
  111. package/lib/identity-HNO1Oe9B.mjs +0 -219
  112. package/lib/kimi-DgcUpPtK.mjs +0 -236
  113. package/lib/markit-DtGoRE6M.mjs +0 -1417
  114. package/lib/minimax-code-Y3h5li9N.mjs +0 -53
  115. package/lib/models-DRA2c_8U.mjs +0 -104660
  116. package/lib/opencode-BsVw9rCD.mjs +0 -38
  117. package/lib/to-binary-B1BEBIPC.mjs +0 -6002
  118. package/lib/wafer-BlhWLweO.mjs +0 -17
  119. package/lib/xai-oauth-5pORHUrg.mjs +0 -446
@@ -1,14 +1,17 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { J as getLogsDir, R as isBunTestRuntime } from "./src-BcD0_rQR.mjs";
3
+ import { J as getLogsDir, L as isBunTestRuntime } from "./src-BwW51vA5.mjs";
4
4
  import * as path from "node:path";
5
5
  import { scheduler } from "node:timers/promises";
6
- //#region node_modules/.pnpm/@oh-my-pi+pi-utils@17.3.5/node_modules/@oh-my-pi/pi-utils/src/fetch-retry.ts
6
+ //#region node_modules/.pnpm/@oh-my-pi+pi-utils@18.1.17/node_modules/@oh-my-pi/pi-utils/src/fetch-retry.ts
7
7
  const QUOTA_RESET_PATTERN = /reset after (?:(\d+)h)?(?:(\d+)m)?(\d+(?:\.\d+)?)s/i;
8
8
  const PLEASE_RETRY_PATTERN = /Please retry in ([0-9.]+)(ms|s)/i;
9
9
  const RETRY_DELAY_FIELD_PATTERN = /"retryDelay":\s*"([0-9.]+)(ms|s)"/i;
10
10
  const TRY_AGAIN_PATTERN = /try again in\s+~?\s*([0-9.]+)\s*(ms|sec|s|minutes?|mins?|m|hours?|hrs?|h)\b/i;
11
11
  const WILL_RESET_IN_PATTERN = /(?:will\s+)?reset in\s+~?\s*([0-9.]+)\s*(ms|sec|s|minutes?|mins?|m|hours?|hrs?|h)\b/i;
12
+ const WILL_RESET_AT_PATTERN = /(?:will\s+)?reset at\s+([0-9]{4}-[0-9]{2}-[0-9]{2}[ T][0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]+)?(?:Z|[+-][0-9]{2}:?[0-9]{2})?)/i;
13
+ const CN_RESET_AT_PATTERN = /将在\s*([0-9]{4}-[0-9]{2}-[0-9]{2}\s+[0-9]{2}:[0-9]{2}:[0-9]{2})\s*重置/;
14
+ const RETRY_AFTER_MS_BODY_PATTERN = /\bretry-after-ms\s*[:=]\s*([0-9]+)\b/i;
12
15
  /**
13
16
  * Server-suggested retry delay extraction. Merges the patterns historically used
14
17
  * by the OpenAI Codex and Google Gemini retry helpers.
@@ -25,8 +28,12 @@ const WILL_RESET_IN_PATTERN = /(?:will\s+)?reset in\s+~?\s*([0-9.]+)\s*(ms|sec|s
25
28
  * - `Please retry in 250ms` / `Please retry in 12s`
26
29
  * - `"retryDelay": "34.074824224s"` (JSON error detail field)
27
30
  * - `try again in 250ms` / `try again in 12s` / `try again in 5 min` / `try again in ~158 min`
31
+ * - `retry-after-ms=98497000` / `retry-after-ms: 7200000` / `retry-after-ms = 7200000`
32
+ * - `Your limit will reset at 2026-09-01 09:44:51` / `将在 2026-09-01 09:44:51 重置`
28
33
  *
29
- * Returns `undefined` if no signal is found.
34
+ * Returns `undefined` if no signal is found, or `0` when the provider
35
+ * explicitly asks for an immediate retry (`retry-after…=0`, or an absolute
36
+ * reset timestamp that has already elapsed).
30
37
  */
31
38
  function extractRetryHint(source, body) {
32
39
  const headers = source instanceof Headers ? source : source?.headers ?? void 0;
@@ -68,6 +75,16 @@ function extractRetryHint(source, body) {
68
75
  }
69
76
  }
70
77
  if (!body) return void 0;
78
+ let longestMs;
79
+ let retryNow = false;
80
+ const consider = (ms) => {
81
+ if (ms !== void 0 && ms > 0 && (longestMs === void 0 || ms > longestMs)) longestMs = ms;
82
+ };
83
+ const considerClamped = (ms) => {
84
+ if (ms === void 0) return;
85
+ if (ms > 0) consider(ms);
86
+ else retryNow = true;
87
+ };
71
88
  const quotaMatch = QUOTA_RESET_PATTERN.exec(body);
72
89
  if (quotaMatch) {
73
90
  const hours = quotaMatch[1] ? Number.parseInt(quotaMatch[1], 10) : 0;
@@ -75,11 +92,32 @@ function extractRetryHint(source, body) {
75
92
  const seconds = Number.parseFloat(quotaMatch[3]);
76
93
  if (!Number.isNaN(seconds)) {
77
94
  const totalMs = ((hours * 60 + minutes) * 60 + seconds) * 1e3;
78
- if (totalMs > 0) return totalMs;
95
+ consider(totalMs > 0 ? totalMs : void 0);
96
+ }
97
+ }
98
+ for (const pattern of [WILL_RESET_AT_PATTERN, CN_RESET_AT_PATTERN]) {
99
+ const match = pattern.exec(body);
100
+ if (match?.[1]) {
101
+ const normalized = match[1].replace(" ", "T");
102
+ const hasOffset = /(?:Z|[+-][0-9]{2}:?[0-9]{2})$/i.test(normalized);
103
+ const parsed = Date.parse(hasOffset ? normalized : `${normalized}Z`);
104
+ if (!Number.isNaN(parsed) && parsed > Date.now()) consider(parsed - Date.now());
79
105
  }
80
106
  }
107
+ const accountResetMatch = WILL_RESET_IN_PATTERN.exec(body);
108
+ if (accountResetMatch?.[1]) {
109
+ const value = Number.parseFloat(accountResetMatch[1]);
110
+ if (Number.isFinite(value) && value > 0) {
111
+ const unitMs = unitToMs(accountResetMatch[2]);
112
+ if (unitMs !== void 0) consider(value * unitMs);
113
+ }
114
+ }
115
+ const retryAfterMsMatch = RETRY_AFTER_MS_BODY_PATTERN.exec(body);
116
+ if (retryAfterMsMatch?.[1]) {
117
+ const ms = Number(retryAfterMsMatch[1]);
118
+ if (Number.isFinite(ms)) considerClamped(ms);
119
+ }
81
120
  for (const pattern of [
82
- WILL_RESET_IN_PATTERN,
83
121
  PLEASE_RETRY_PATTERN,
84
122
  RETRY_DELAY_FIELD_PATTERN,
85
123
  TRY_AGAIN_PATTERN
@@ -89,10 +127,31 @@ function extractRetryHint(source, body) {
89
127
  const value = Number.parseFloat(match[1]);
90
128
  if (Number.isFinite(value) && value > 0) {
91
129
  const unitMs = unitToMs(match[2]);
92
- if (unitMs !== void 0) return value * unitMs;
130
+ if (unitMs !== void 0) consider(value * unitMs);
93
131
  }
94
132
  }
95
133
  }
134
+ const retryAfterMatch = /retry-after\s*[:=]\s*([^\s,;]+)/i.exec(body);
135
+ if (retryAfterMatch) {
136
+ const value = retryAfterMatch[1];
137
+ const seconds = Number(value);
138
+ if (Number.isFinite(seconds)) considerClamped(seconds * 1e3);
139
+ else {
140
+ const dateMs = Date.parse(value);
141
+ if (!Number.isNaN(dateMs)) considerClamped(dateMs - Date.now());
142
+ }
143
+ }
144
+ const resetMsMatch = /x-ratelimit-reset-ms\s*[:=]\s*(\d+)/i.exec(body);
145
+ if (resetMsMatch) {
146
+ const resetMs = Number(resetMsMatch[1]);
147
+ if (!Number.isNaN(resetMs)) considerClamped(resetMs > 0xe8d4a51000 ? resetMs - Date.now() : resetMs);
148
+ }
149
+ const resetMatch = /x-ratelimit-reset\s*[:=]\s*(\d+)/i.exec(body);
150
+ if (resetMatch) {
151
+ const resetSeconds = Number(resetMatch[1]);
152
+ if (!Number.isNaN(resetSeconds)) considerClamped(resetSeconds > 1e9 ? resetSeconds * 1e3 - Date.now() : resetSeconds * 1e3);
153
+ }
154
+ return longestMs ?? (retryNow ? 0 : void 0);
96
155
  }
97
156
  function unitToMs(unit) {
98
157
  switch (unit.toLowerCase()) {
@@ -242,7 +301,7 @@ function isRetryableStatus(status) {
242
301
  * proxies surface these for any HTTP/2 stream reset.
243
302
  */
244
303
  function isUnexpectedSocketCloseMessage(message) {
245
- return /\b(?:the\s+)?socket connection (?:was )?closed unexpectedly\b/i.test(message);
304
+ return /\b(?:the\s+)?socket connection (?:was )?closed unexpectedly\b/i.test(message) || /^(?:error:\s*)?socket is closed\.?$/i.test(message.trim());
246
305
  }
247
306
  const TRANSIENT_MESSAGE_PATTERN = /overloaded|rate.?limit|too many requests|service.?unavailable|server error|internal error|connection.?error|unable to connect|fetch failed|network error|stream stall|other side closed|HTTP2(?:StreamReset|RefusedStream|EnhanceYourCalm)/i;
248
307
  const VALIDATION_MESSAGE_PATTERN = /invalid|validation|bad request|unsupported|schema|missing required|not found|unauthorized|forbidden/i;
@@ -265,7 +324,7 @@ function isRetryableError(error) {
265
324
  return isUnexpectedSocketCloseMessage(message) || TRANSIENT_MESSAGE_PATTERN.test(message);
266
325
  }
267
326
  //#endregion
268
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/aws.ts
327
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/aws.ts
269
328
  /** A failure resolving AWS credentials for the Bedrock provider. */
270
329
  var AwsCredentialsError = class extends Error {
271
330
  kind;
@@ -283,7 +342,7 @@ var EventStreamFrameError = class extends Error {
283
342
  }
284
343
  };
285
344
  //#endregion
286
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/classes.ts
345
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/classes.ts
287
346
  /** Prefix on errors raised when an Anthropic SSE stream envelope is malformed. */
288
347
  const STREAM_ENVELOPE_ERROR_PREFIX = "Anthropic stream envelope error:";
289
348
  /** Non-2xx HTTP response from a provider. */
@@ -378,8 +437,7 @@ var AnthropicApiError = class AnthropicApiError extends ProviderHttpError {
378
437
  if (signal?.aborted) onAbort();
379
438
  else signal?.addEventListener("abort", onAbort, { once: true });
380
439
  const deadline = performance.now() + anthropicErrorBodyReadTimeoutMs;
381
- let timeout;
382
- timeout = setTimeout(() => {
440
+ const timeout = setTimeout(() => {
383
441
  timedOut = true;
384
442
  cancelReader();
385
443
  }, anthropicErrorBodyReadTimeoutMs);
@@ -474,9 +532,10 @@ var OllamaApiError = class extends ProviderHttpError {
474
532
  name = "OllamaApiError";
475
533
  };
476
534
  //#endregion
477
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/rate-limit.ts
535
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/rate-limit.ts
478
536
  const ACCOUNT_RATE_LIMIT_PATTERN = /\baccount(?:'s)?\b[^\n]{0,80}\brate.?limit\b|\brate.?limit\b[^\n]{0,80}\baccount\b/i;
479
537
  const INSUFFICIENT_BALANCE_PATTERN = /insufficient.?balance/i;
538
+ const CREDITS_EXHAUSTED_PATTERN = /\b(?:exceed\w*|insufficient|not enough)\b[^\n]{0,40}\bcredits?\b|\bcredits?\b[^\n]{0,40}\b(?:exhausted|depleted)\b/i;
480
539
  const SPEND_LIMIT_PATTERN = /spend.?limit/i;
481
540
  const SUBSCRIPTION_CAP_PATTERN = /\b(?:subscription|plan|membership)\b[^\n]{0,80}\b(?:rate.?limits?|quota|cap)\b|\b(?:rate.?limits?|quota|cap)\b[^\n]{0,80}\b(?:subscription|plan|membership)\b/i;
482
541
  const TRANSIENT_INTERVAL_RATE_LIMIT_PATTERN = /\bper\s+(?:second|minute)\b/i;
@@ -484,6 +543,7 @@ function matchesSubscriptionCapText(errorMessage) {
484
543
  return SUBSCRIPTION_CAP_PATTERN.test(errorMessage) && !TRANSIENT_INTERVAL_RATE_LIMIT_PATTERN.test(errorMessage);
485
544
  }
486
545
  const OPENROUTER_DAILY_FREE_LIMIT_PATTERN = /\bfree[-_ ]models[-_ ]per[-_ ]day\b/i;
546
+ const CLINE_PASS_QUOTA_PATTERN = /clinepass limit|free limit reached on model/i;
487
547
  const RESOURCE_EXHAUSTED_PATTERN = /resource.?exhausted/gi;
488
548
  const CONCURRENT_LIMIT_PATTERN = /\btoo many\s+concurren\w*\s+(?:requests?|invocations?)\b|\bconcurren\w*\b[^\n]{0,60}\b(?:limit|quota|exceed\w*|reach\w*)\b|\b(?:limit|quota|exceed\w*|reach\w*)\b[^\n]{0,60}\bconcurren\w*\b|\bconcurren[a-z]*[-_](?:[a-z]+[_-])*(?:limit|quota|exceed\w*|reach\w*)/i;
489
549
  const ACCOUNT_SCOPED_403_PATTERN = /\b(?:overall|account|organization|team|workspace)\b[^\n]{0,40}\b(?:message |request )?rate.?limit\b|\byour\b[^\n]{0,30}\b(?:limit )?will reset\b/i;
@@ -497,6 +557,7 @@ function isDashScopeTokenLimitText(errorMessage) {
497
557
  return DASHSCOPE_TOKEN_LIMIT_DOC_PATTERN.test(errorMessage) && DASHSCOPE_TOKEN_LIMIT_MESSAGE_PATTERN.test(errorMessage);
498
558
  }
499
559
  const GOOGLE_RPC_ERROR_INFO_TYPE = "type.googleapis.com/google.rpc.ErrorInfo";
560
+ const ANTIGRAVITY_MODEL_QUOTA_PATTERN = /\bexhausted your capacity on this model\b/i;
500
561
  const LONG_RATE_LIMIT_DELAY_MS = 3e5;
501
562
  function asRecord(value) {
502
563
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
@@ -527,6 +588,7 @@ function parseGoogleRpcRateLimitReason(errorMessage) {
527
588
  case "QUOTA_EXHAUSTED": return "QUOTA_EXHAUSTED";
528
589
  case "INSUFFICIENT_G1_CREDITS_BALANCE": return "INSUFFICIENT_G1_CREDITS_BALANCE";
529
590
  case "RATE_LIMIT_EXCEEDED": {
591
+ if (typeof error.message === "string" && ANTIGRAVITY_MODEL_QUOTA_PATTERN.test(error.message)) return "QUOTA_EXHAUSTED";
530
592
  const retryDelayMs = extractRetryHint(void 0, errorMessage);
531
593
  return retryDelayMs !== void 0 && retryDelayMs >= LONG_RATE_LIMIT_DELAY_MS ? "QUOTA_EXHAUSTED" : "RATE_LIMIT_EXCEEDED";
532
594
  }
@@ -561,26 +623,35 @@ function parseRateLimitReason(errorMessage) {
561
623
  if (SPEND_LIMIT_PATTERN.test(errorMessage)) return "QUOTA_EXHAUSTED";
562
624
  if (matchesSubscriptionCapText(errorMessage)) return "QUOTA_EXHAUSTED";
563
625
  if (OPENROUTER_DAILY_FREE_LIMIT_PATTERN.test(errorMessage)) return "QUOTA_EXHAUSTED";
626
+ if (CLINE_PASS_QUOTA_PATTERN.test(errorMessage)) return "QUOTA_EXHAUSTED";
564
627
  if (lower.includes("per minute") || lower.includes("rate limit") || lower.includes("too many requests") || lower.includes("presque")) return "RATE_LIMIT_EXCEEDED";
565
- if (lower.includes("exhausted") || lower.includes("quota") || lower.includes("usage limit") || lower.includes("run out of credits") || lower.includes("out of credits") || lower.includes("spending-limit") || lower.includes("spending limit") || INSUFFICIENT_BALANCE_PATTERN.test(errorMessage)) return "QUOTA_EXHAUSTED";
628
+ if (lower.includes("exhausted") || lower.includes("quota") || lower.includes("usage limit") || lower.includes("run out of credits") || lower.includes("out of credits") || lower.includes("spending-limit") || lower.includes("spending limit") || INSUFFICIENT_BALANCE_PATTERN.test(errorMessage) || CREDITS_EXHAUSTED_PATTERN.test(errorMessage)) return "QUOTA_EXHAUSTED";
566
629
  if (lower.includes("500") || lower.includes("internal error") || lower.includes("internal server error")) return "SERVER_ERROR";
567
630
  if (hasResourceExhaustedStatus) return "MODEL_CAPACITY_EXHAUSTED";
568
631
  return "UNKNOWN";
569
632
  }
570
633
  /** Detect usage/quota limit errors in error messages (persistent, requires credential switch). */
571
- const USAGE_LIMIT_PATTERN = /usage.?limit|usage_limit_reached|usage_not_included|limit_reached|quota.?(?:exceeded|reached|insufficient)|额度不足|额度耗尽|resource.?exhausted|exhausted your capacity|quota will reset|insufficient.?(?:balance|quota)|balance.?exhausted|run out of credits|out of credits|spending[- _]?limit|personal-team-blocked/i;
634
+ const USAGE_LIMIT_PATTERN = /usage.?limit|usage_limit_reached|usage_not_included|limit_reached|quota.?(?:exceeded|reached|insufficient)|额度不足|额度耗尽|resource.?exhausted|exhausted your capacity|quota will reset|insufficient.?(?:balance|quota)|balance.?exhausted|run out of credits|out of credits|spending[- _]?limit|personal-team-blocked|clinepass limit|free limit reached on model/i;
572
635
  /**
573
636
  * HTTP status codes that, absent richer body classification, represent an
574
637
  * account-local usage cap rather than a bad credential or a transient blip.
575
- * HTTP 402 Payment Required is categorically an account-billing cap (xAI
638
+ * HTTP 402 Payment Required represents an account-billing cap (xAI
576
639
  * Grok Build "usage balance exhausted", DeepSeek "Insufficient Balance",
577
- * OpenRouter credit exhaustion) — never a transient blip or bad credential.
578
- * Always combine with {@link isUsageLimitOutcome} when a message is available
579
- * — a 429 carrying transient rate-limit wording is NOT a usage cap.
640
+ * OpenRouter credit exhaustion) when opaque, payment/deactivation/balance-worded,
641
+ * or QUOTA_EXHAUSTED/CONCURRENT_LIMIT, while informative non-quota 402s (e.g.
642
+ * endpoint subscription requirements) remain non-usage-limits. Always combine
643
+ * with {@link isUsageLimitOutcome} when a message is available.
580
644
  */
581
645
  function isUsageLimitStatus(status) {
582
646
  return status === 429 || status === 402;
583
647
  }
648
+ const STATUS_402_QUOTA_PATTERN = /\b(?:payment(?:\s+is)?[-_.\s]*required|deactivated_workspace|insufficient.?balance)\b/i;
649
+ function is402BillingCapBody(message) {
650
+ if (message === void 0 || isOpaqueStatusBody(message)) return true;
651
+ if (STATUS_402_QUOTA_PATTERN.test(message)) return true;
652
+ const reason = parseRateLimitReason(message);
653
+ return isQuotaExhaustedReason(reason) || reason === "CONCURRENT_LIMIT";
654
+ }
584
655
  /**
585
656
  * A usage-limit status body is opaque when it carries no signal beyond the
586
657
  * status itself — empty, whitespace-only, the status digits with HTTP/JSON
@@ -589,7 +660,7 @@ function isUsageLimitStatus(status) {
589
660
  * classifier.
590
661
  */
591
662
  function isOpaqueStatusBody(message) {
592
- const cleaned = message.replace(/\b(?:429|402)\b/g, "").replace(/\b(?:http|https|status|error|code|response|message)\b/gi, "");
663
+ const cleaned = message.replace(/\b(?:429|402)\b/g, "").replace(/\b(?:http|https|status|error|code|response|message)\b/gi, "").replace(/\(?\bno body\b\)?/gi, "");
593
664
  return !/[a-z\d]{3,}/i.test(cleaned) && !CN_QUOTA_EXHAUSTED_PATTERN.test(cleaned) && !CN_TRANSIENT_CAP_PATTERN.test(cleaned) && !CN_THROTTLE_PATTERN.test(cleaned);
594
665
  }
595
666
  /**
@@ -602,7 +673,7 @@ function matchesUsageLimitText(errorMessage) {
602
673
  const structuredReason = parseGoogleRpcRateLimitReason(errorMessage);
603
674
  if (structuredReason !== void 0) return isQuotaExhaustedReason(structuredReason);
604
675
  if (isDashScopeTokenLimitText(errorMessage)) return false;
605
- return USAGE_LIMIT_PATTERN.test(errorMessage) || CN_QUOTA_EXHAUSTED_PATTERN.test(errorMessage) && !CN_TRANSIENT_CAP_PATTERN.test(errorMessage) || SPEND_LIMIT_PATTERN.test(errorMessage) || ACCOUNT_RATE_LIMIT_PATTERN.test(errorMessage) || matchesSubscriptionCapText(errorMessage) || OPENROUTER_DAILY_FREE_LIMIT_PATTERN.test(errorMessage);
676
+ return USAGE_LIMIT_PATTERN.test(errorMessage) || CREDITS_EXHAUSTED_PATTERN.test(errorMessage) || CN_QUOTA_EXHAUSTED_PATTERN.test(errorMessage) && !CN_TRANSIENT_CAP_PATTERN.test(errorMessage) || SPEND_LIMIT_PATTERN.test(errorMessage) || ACCOUNT_RATE_LIMIT_PATTERN.test(errorMessage) || matchesSubscriptionCapText(errorMessage) || OPENROUTER_DAILY_FREE_LIMIT_PATTERN.test(errorMessage);
606
677
  }
607
678
  /**
608
679
  * Account-scoped cap phrasing delivered on a 403 (or a statusless Connect
@@ -615,7 +686,7 @@ function isAccountScopedCapText(message) {
615
686
  return ACCOUNT_SCOPED_403_PATTERN.test(message);
616
687
  }
617
688
  //#endregion
618
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/flags.ts
689
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/flags.ts
619
690
  const Flag = {
620
691
  Class: 4096,
621
692
  ThinkingLoop: 65536,
@@ -639,11 +710,13 @@ const Flag = {
639
710
  /** Anthropic model/account does not support fast mode / the `speed` parameter. */
640
711
  FastModeUnsupported: 536870912,
641
712
  /** OAuth refresh failed definitively — the stored grant is dead, re-login required. */
642
- OAuthExpiry: 1073741824
713
+ OAuthExpiry: 1073741824,
714
+ /** HTTP 413 byte/media rejection — token compaction cannot shrink bytes or media budgets (#9235). */
715
+ PayloadRejected: 2147483648
643
716
  };
644
- const KIND_MASK = Flag.ThinkingLoop | Flag.Transient | Flag.Timeout | Flag.UsageLimit | Flag.StaleResponsesItem | Flag.MalformedFunctionCall | Flag.ProviderFinishError | Flag.EmptyResponse | Flag.ContentBlocked | Flag.AccountPolicy | Flag.ContextOverflow | Flag.AuthFailed | Flag.SilentAbort | Flag.UserInterrupt | Flag.Abort | Flag.Grammar | Flag.FastModeUnsupported | Flag.OAuthExpiry;
717
+ const KIND_MASK = Flag.ThinkingLoop | Flag.Transient | Flag.Timeout | Flag.UsageLimit | Flag.StaleResponsesItem | Flag.MalformedFunctionCall | Flag.ProviderFinishError | Flag.EmptyResponse | Flag.ContentBlocked | Flag.AccountPolicy | Flag.ContextOverflow | Flag.AuthFailed | Flag.PayloadRejected | Flag.SilentAbort | Flag.UserInterrupt | Flag.Abort | Flag.Grammar | Flag.FastModeUnsupported | Flag.OAuthExpiry;
645
718
  const RETRIABLE_KINDS = Flag.Transient | Flag.UsageLimit | Flag.ThinkingLoop | Flag.StaleResponsesItem | Flag.ProviderFinishError | Flag.EmptyResponse;
646
- const OVERFLOW_PATTERNS = [
719
+ const CONTEXT_OVERFLOW_EVIDENCE_PATTERNS = [
647
720
  /prompt is too long/i,
648
721
  /input is too long for requested model/i,
649
722
  /exceeds the context window/i,
@@ -651,7 +724,6 @@ const OVERFLOW_PATTERNS = [
651
724
  /maximum prompt length is \d+/i,
652
725
  /reduce the length of the messages/i,
653
726
  /maximum context length is \d+ tokens/i,
654
- /exceeds the limit of \d+/i,
655
727
  /exceeds the available context size/i,
656
728
  /requested tokens?.*exceed.*context (window|length|size)/i,
657
729
  /context (window|length|size).*(exceeded|overflow|too small)/i,
@@ -663,26 +735,94 @@ const OVERFLOW_PATTERNS = [
663
735
  /context[_ ]length[_ ]exceeded/i,
664
736
  /too many tokens/i,
665
737
  /token limit exceeded/i,
666
- /request_too_large/i,
667
- /request exceeds the maximum size/i,
668
- /payload too large/i,
669
- /entity too large/i,
670
- /\b413\b.*\b(request|payload|entity)\b.*\btoo large\b/i,
738
+ /request_too_large[^\n]*\btokens?\b/i,
739
+ /\btokens?\b[^\n]*request_too_large/i,
671
740
  /model_context_window_exceeded/i,
672
- /prompt filled the context window/i
741
+ /prompt filled the context window/i,
742
+ /exceeds the limit of \d+ tokens?\b/i,
743
+ /chat history exceeds the \d+-message limit/i
673
744
  ];
745
+ const GENERIC_LIMIT_OVERFLOW_PATTERN = /exceeds the limit of \d+/i;
746
+ const OVERFLOW_PATTERNS = [...CONTEXT_OVERFLOW_EVIDENCE_PATTERNS, GENERIC_LIMIT_OVERFLOW_PATTERN];
747
+ /** Token-context evidence only — excludes GENERIC_LIMIT_OVERFLOW_PATTERN which media budgets also match (#9235). */
748
+ function hasTokenContextOverflowEvidence(text) {
749
+ return CONTEXT_OVERFLOW_EVIDENCE_PATTERNS.some((p) => p.test(text));
750
+ }
751
+ /** Checks every cause-chain link; a wrapper whose nested 413 names the token budget stays overflow-only (#9235). */
752
+ function hasCauseTokenContextOverflowEvidence(error) {
753
+ const seen = /* @__PURE__ */ new Set();
754
+ let link = error;
755
+ while (link !== void 0 && link !== null) {
756
+ if (typeof link !== "object") {
757
+ if (typeof link === "string" && hasTokenContextOverflowEvidence(link)) return true;
758
+ break;
759
+ }
760
+ if (seen.has(link)) break;
761
+ seen.add(link);
762
+ if ("message" in link) {
763
+ const message = link.message;
764
+ if (typeof message === "string" && hasTokenContextOverflowEvidence(message)) return true;
765
+ }
766
+ if ("cause" in link) {
767
+ link = link.cause;
768
+ continue;
769
+ }
770
+ break;
771
+ }
772
+ return false;
773
+ }
674
774
  const OVERFLOW_NO_BODY_PATTERN = /\b4(00|13)\s*(status code)?\s*\(no body\)/i;
775
+ const PAYLOAD_REJECTION_PATTERNS = [
776
+ /\b413\s*(?:status code\s*)?\(no body\)/i,
777
+ /\b413\b[^.\n]{0,120}\b(?:request|payload|entity|body)\b[^.\n]{0,60}\b(?:exceed|too large|limit)/i,
778
+ /request_too_large/i,
779
+ /(?:payload|entity) too large/i,
780
+ /request exceeds the maximum (?:size|number of bytes)/i
781
+ ];
782
+ function matchesPayloadRejectionText(text) {
783
+ if (!PAYLOAD_REJECTION_PATTERNS.some((p) => p.test(text))) return false;
784
+ if (hasTokenContextOverflowEvidence(text)) return false;
785
+ return true;
786
+ }
675
787
  const TIMEOUT_PATTERN = /\b(?:operation\s+)?timed?\s*out\b|\btimeout\b|\bstream stall\b/i;
676
788
  const TRANSIENT_ENVELOPE_PATTERN = /anthropic stream envelope error:/i;
677
- const TRANSIENT_ENVELOPE_BEFORE_START_PATTERN = /before message_start/i;
789
+ const TRANSIENT_ENVELOPE_TRUNCATION_PATTERN = /before message_(?:start|stop)/i;
678
790
  const STREAM_READ_ERROR_PATTERN = /stream[_ -]?read[_ -]?error/i;
679
- const TRANSIENT_TRANSPORT_PATTERN = /\b(?:no[_ -]?capacity|(?:high|peak)[ _-]?demand|(?:at|over|insufficient)[ _-]?capacity|capacity[ _-]?(?:exceeded|exhausted)|peak[ _-]?load)\b|overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|retry your request|network.?error|connection.?error|connection.?refused|unable.?to.?connect\.\s*is the computer able to access the url\?|other side closed|fetch failed|upstream.?connect|upstream.?request.?failed|reset before headers|socket hang up|timed? out|timeout|terminated|retry delay|stream stall|no error details in response|HTTP2(?:StreamReset|RefusedStream|EnhanceYourCalm)|nghttp2_(?:internal_error|refused_stream)|stream closed with error code nghttp2_(?:internal_error|refused_stream)|malformed.?function.?call/i;
791
+ /** Python h2/httpx diagnostics forwarded through provider or proxy error events. */
792
+ const PYTHON_HTTP2_STREAM_RESET_PATTERN = /<StreamReset stream_id:\d+, error_code:(?:2|7), remote_reset:True>/;
793
+ /** Python h11/httpx EOF while reading an HTTP/1.1 chunked response body. */
794
+ const PYTHON_HTTP_INCOMPLETE_CHUNK_PATTERN = /peer closed connection without sending complete message body \(incomplete chunked read\)/;
795
+ const TRANSIENT_TRANSPORT_PATTERN = /\b(?:no[_ -]?capacity|(?:high|peak)[ _-]?demand|(?:at|over|insufficient)[ _-]?capacity|capacity[ _-]?(?:exceeded|exhausted)|peak[ _-]?load)\b|overloaded|provider.?returned.?error|rate.?limit|too many requests|auth-gateway\s+5\d{2}(?=[:\s]|$)|\b(?:429|500|502|503|504)\b|service.?unavailable|server.?error|internal.?error|retry your request|network.?error|connection.?error|connection.?refused|unable.?to.?connect\.\s*is the computer able to access the url\?|other side closed|fetch failed|upstream.?connect|upstream.?request.?failed|reset before headers|socket hang up|timed? out|timeout|terminated|retry delay|stream stall|no error details in response|HTTP2(?:StreamReset|RefusedStream|EnhanceYourCalm)|nghttp2_(?:internal_error|refused_stream)|stream closed with error code nghttp2_(?:internal_error|refused_stream)|malformed.?function.?call/i;
680
796
  const AUTH_FAILURE_PATTERN = /\b(?:401|403|unauthorized|forbidden|authentication|auth[_ ]?unavailable|no auth available|(?:invalid|no)[_ ]?api[_ ]?key)\b/i;
681
797
  const MALFORMED_FUNCTION_CALL_PATTERN = /\bmalformed.?function.?call\b/i;
682
798
  const PROVIDER_FINISH_ERROR_PATTERN = /\bProvider (?:returned error finish_reason|finish_reason:\s*error)\b/i;
683
799
  const EMPTY_RESPONSE_PATTERN = /\bthought-only response without final output\b/i;
684
800
  const CONTENT_FILTER_PATTERN = /\b(?:incomplete:\s*)?content_filter\b/i;
685
801
  const ACCOUNT_POLICY_PATTERN = /\bcyber_policy\b|trusted access for cyber/i;
802
+ const CODEX_CHATGPT_ACCOUNT_MODEL_POLICY_PATTERN = /\bThe ['"]([^'"\r\n]+)['"] model is not supported when using Codex with a ChatGPT account\./i;
803
+ const CODEX_CHATGPT_ACCOUNT_MODEL_MAX_LENGTH = 256;
804
+ const CURSOR_PLAN_POLICY_MARKER_PATTERN = /\bERROR_RATE_LIMITED_CHANGEABLE\b/i;
805
+ const CURSOR_PLAN_POLICY_PATTERN = /\bNamed models unavailable\b|\bModel unavailable on\b|\bFree plans can only use\b/i;
806
+ function isCursorPlanPolicyText(text) {
807
+ return CURSOR_PLAN_POLICY_MARKER_PATTERN.test(text) && CURSOR_PLAN_POLICY_PATTERN.test(text);
808
+ }
809
+ function normalizeCodexChatGPTAccountPolicyModel(modelId) {
810
+ if (typeof modelId !== "string") return void 0;
811
+ const separator = modelId.lastIndexOf("/");
812
+ const bareModelId = (separator === -1 ? modelId : modelId.slice(separator + 1)).trim().toLowerCase();
813
+ if (!bareModelId || bareModelId.length > CODEX_CHATGPT_ACCOUNT_MODEL_MAX_LENGTH || bareModelId.includes("\0")) return;
814
+ return bareModelId;
815
+ }
816
+ function codexChatGPTAccountPolicyModelFromText(text) {
817
+ const modelId = CODEX_CHATGPT_ACCOUNT_MODEL_POLICY_PATTERN.exec(text)?.[1]?.trim();
818
+ return normalizeCodexChatGPTAccountPolicyModel(modelId) === void 0 ? void 0 : modelId;
819
+ }
820
+ function isCodexChatGPTAccountPolicyText(text, provider, modelId) {
821
+ if (provider !== "openai-codex") return false;
822
+ const deniedIdentity = normalizeCodexChatGPTAccountPolicyModel(codexChatGPTAccountPolicyModelFromText(text));
823
+ const requestedIdentity = normalizeCodexChatGPTAccountPolicyModel(modelId);
824
+ return deniedIdentity !== void 0 && deniedIdentity === requestedIdentity;
825
+ }
686
826
  const STALE_RESPONSE_ITEM_PATTERNS = [/\bItem with id ['"][^'"]+['"] not found\.?/i, /previous[ _]?response/i];
687
827
  const STALE_RESPONSE_ITEM_DETAIL_PATTERN = /not[ _]?found|invalid|expired|stale|zero[ _-]?data[ _-]?retention/i;
688
828
  /**
@@ -692,8 +832,7 @@ const STALE_RESPONSE_ITEM_DETAIL_PATTERN = /not[ _]?found|invalid|expired|stale|
692
832
  * output, so callers strip {@link Flag.Transient} when this matches.
693
833
  */
694
834
  const LLAMA_CPP_TOOL_CALL_PARSE_PATTERN = /failed to parse tool call arguments as json|\[json\.exception\.parse_error\.101\]/i;
695
- const COPILOT_TRANSIENT_MODEL_CODES = { model_not_supported: true };
696
- const COPILOT_TRANSIENT_MODEL_PATTERN = /model_not_supported/i;
835
+ const GENERATION_NAN_PATTERN = /floating[ _-]?point nan\b.*\bdetected in generation/is;
697
836
  const GRAMMAR_TOO_LARGE_PATTERN = /compiled grammar/i;
698
837
  const GRAMMAR_TOO_LARGE_DETAIL_PATTERN = /too large/i;
699
838
  const SCHEMA_TOO_COMPLEX_PATTERN = /schema/i;
@@ -722,7 +861,7 @@ function matchesFastModeUnsupported(message, errorStatus) {
722
861
  if (errorStatus === 400 && INVALID_REQUEST_PATTERN.test(message) && FAST_MODE_SPEED_PARAM_PATTERN.test(message) && FAST_MODE_NOT_SUPPORTED_PATTERN.test(message)) return true;
723
862
  return errorStatus === 429 && FAST_MODE_RATE_LIMIT_PATTERN.test(message) && FAST_MODE_ENTITLEMENT_PATTERN.test(message);
724
863
  }
725
- Flag.ThinkingLoop, Flag.Transient, Flag.Timeout, Flag.UsageLimit, Flag.StaleResponsesItem, Flag.MalformedFunctionCall, Flag.ProviderFinishError, Flag.EmptyResponse, Flag.ContentBlocked, Flag.AccountPolicy, Flag.ContextOverflow, Flag.AuthFailed, Flag.SilentAbort, Flag.UserInterrupt, Flag.Abort;
864
+ Flag.ThinkingLoop, Flag.Transient, Flag.Timeout, Flag.UsageLimit, Flag.StaleResponsesItem, Flag.MalformedFunctionCall, Flag.ProviderFinishError, Flag.EmptyResponse, Flag.ContentBlocked, Flag.AccountPolicy, Flag.ContextOverflow, Flag.PayloadRejected, Flag.AuthFailed, Flag.SilentAbort, Flag.UserInterrupt, Flag.Abort;
726
865
  const STATUS_MESSAGE_PATTERNS = [
727
866
  /\bstatus(?:_code)?[:=]\s*(\d{3})\b/i,
728
867
  /\bstatus\s+(\d{3})\b/i,
@@ -740,6 +879,7 @@ function is(id, flag) {
740
879
  }
741
880
  function retriable(id, opts) {
742
881
  if (is(id, Flag.ContentBlocked)) return false;
882
+ if (is(id, Flag.PayloadRejected)) return false;
743
883
  if (opts?.replayUnsafe) return false;
744
884
  if (is(id, Flag.MalformedFunctionCall)) return true;
745
885
  return ((id ?? 0) & RETRIABLE_KINDS) !== 0;
@@ -783,7 +923,7 @@ function isStreamReadErrorText(text) {
783
923
  return STREAM_READ_ERROR_PATTERN.test(text);
784
924
  }
785
925
  function isTransientErrorText(text) {
786
- return isUnexpectedSocketCloseMessage(text) || isStreamReadErrorText(text) || TRANSIENT_ENVELOPE_PATTERN.test(text) && TRANSIENT_ENVELOPE_BEFORE_START_PATTERN.test(text) || TRANSIENT_TRANSPORT_PATTERN.test(text);
926
+ return isUnexpectedSocketCloseMessage(text) || isStreamReadErrorText(text) || PYTHON_HTTP2_STREAM_RESET_PATTERN.test(text) || PYTHON_HTTP_INCOMPLETE_CHUNK_PATTERN.test(text) || TRANSIENT_ENVELOPE_PATTERN.test(text) && TRANSIENT_ENVELOPE_TRUNCATION_PATTERN.test(text) || TRANSIENT_TRANSPORT_PATTERN.test(text);
787
927
  }
788
928
  function isTimeoutText(text) {
789
929
  return TIMEOUT_PATTERN.test(text);
@@ -806,31 +946,35 @@ function isContentBlockedText(text) {
806
946
  function matchesOverflowText(text) {
807
947
  return OVERFLOW_PATTERNS.some((p) => p.test(text)) || OVERFLOW_NO_BODY_PATTERN.test(text);
808
948
  }
809
- function classifyText(errorMessage, errorStatus, api) {
949
+ function classifyText(errorMessage, errorStatus, priorTokenOverflowEvidence = false, api, provider, modelId) {
810
950
  let kinds = 0;
811
951
  if (errorMessage) {
812
952
  if (matchesOverflowText(errorMessage)) kinds |= Flag.ContextOverflow;
953
+ if (matchesPayloadRejectionText(errorMessage)) kinds |= Flag.PayloadRejected;
813
954
  if (isMalformedFunctionCallText(errorMessage)) kinds |= Flag.MalformedFunctionCall;
814
955
  if (isProviderFinishErrorText(errorMessage)) kinds |= Flag.ProviderFinishError;
815
956
  if (EMPTY_RESPONSE_PATTERN.test(errorMessage)) kinds |= Flag.EmptyResponse | Flag.Transient;
816
957
  if (isContentBlockedText(errorMessage)) kinds |= Flag.ContentBlocked;
817
- if (ACCOUNT_POLICY_PATTERN.test(errorMessage)) kinds |= Flag.AccountPolicy | Flag.ContentBlocked;
958
+ if (ACCOUNT_POLICY_PATTERN.test(errorMessage) || isCodexChatGPTAccountPolicyText(errorMessage, provider, modelId) || provider === "cursor" && isCursorPlanPolicyText(errorMessage)) kinds |= Flag.AccountPolicy | Flag.ContentBlocked;
818
959
  if (isAuthFailureText(errorMessage)) kinds |= Flag.AuthFailed;
819
960
  const statusClean = errorStatus ? errorStatus : status({ message: errorMessage }) ?? void 0;
820
961
  const cleanMessage = errorMessage;
821
962
  const isOpaque = isOpaqueStatusBody(cleanMessage);
822
963
  const isLimitStatus = isUsageLimitStatus(statusClean);
823
964
  const reason = parseRateLimitReason(cleanMessage);
824
- const isBillingCapStatus = statusClean === 402;
825
- if (!(reason === "CONCURRENT_LIMIT" && !isBillingCapStatus) && (matchesUsageLimitText(cleanMessage) || (statusClean === 403 || statusClean === void 0) && isAccountScopedCapText(cleanMessage) || isLimitStatus && (isOpaque || reason === "QUOTA_EXHAUSTED" || isBillingCapStatus && reason === "CONCURRENT_LIMIT"))) kinds |= Flag.UsageLimit;
965
+ const is402BillingCap = statusClean === 402 && is402BillingCapBody(cleanMessage);
966
+ if (!(reason === "CONCURRENT_LIMIT" && statusClean !== 402) && (is402BillingCap || matchesUsageLimitText(cleanMessage) || (statusClean === 403 || statusClean === void 0) && isAccountScopedCapText(cleanMessage) || isLimitStatus && (isOpaque || reason === "QUOTA_EXHAUSTED"))) kinds |= Flag.UsageLimit;
826
967
  if (isTimeoutText(errorMessage)) kinds |= Flag.Transient | Flag.Timeout;
827
968
  else if (isTransientErrorText(errorMessage)) kinds |= Flag.Transient;
828
969
  if (reason === "CONCURRENT_LIMIT") kinds |= Flag.Transient;
829
970
  if ((api === "openai-responses" || api === "openai-codex-responses") && isStaleResponsesText(errorMessage)) kinds |= Flag.StaleResponsesItem;
830
- if (statusClean === 400 && COPILOT_TRANSIENT_MODEL_PATTERN.test(cleanMessage)) kinds |= Flag.Transient;
971
+ if (statusClean === 400 && GENERATION_NAN_PATTERN.test(cleanMessage)) kinds |= Flag.Transient;
831
972
  if (matchesStrictToolsRejection(cleanMessage, statusClean)) kinds |= Flag.Grammar;
832
973
  if (matchesFastModeUnsupported(cleanMessage, statusClean)) kinds |= Flag.FastModeUnsupported;
833
974
  }
975
+ const statusEvidence = errorStatus ?? (errorMessage ? status({ message: errorMessage }) : void 0);
976
+ if (statusEvidence === 413 && !priorTokenOverflowEvidence && !(errorMessage && hasTokenContextOverflowEvidence(errorMessage))) kinds |= Flag.PayloadRejected;
977
+ if (statusEvidence === 402 && (errorMessage === void 0 || isOpaqueStatusBody(errorMessage))) kinds |= Flag.UsageLimit;
834
978
  if (kinds !== 0) return create(kinds);
835
979
  const fallbackStatus = errorStatus ?? (errorMessage ? status({ message: errorMessage }) : void 0);
836
980
  if (fallbackStatus === 401 || fallbackStatus === 403) return create(Flag.AuthFailed);
@@ -839,6 +983,7 @@ function classifyText(errorMessage, errorStatus, api) {
839
983
  function classify(error, api) {
840
984
  let kinds = 0;
841
985
  const seen = /* @__PURE__ */ new Set();
986
+ const causeTokenEvidence = hasCauseTokenContextOverflowEvidence(error);
842
987
  let link = error;
843
988
  while (link !== void 0 && link !== null) {
844
989
  if (typeof link === "object") {
@@ -855,7 +1000,7 @@ function classify(error, api) {
855
1000
  else if (link instanceof ProviderHttpError) {
856
1001
  let linkKinds = 0;
857
1002
  const { status: codeStatus, code } = link;
858
- if (code === "usage_limit_reached" || code === "insufficient_quota" && !isDashScopeTokenLimitText(link.message)) linkKinds |= Flag.UsageLimit;
1003
+ if (code === "usage_limit_reached" || code === "insufficient_quota" && !isDashScopeTokenLimitText(link.message) || codeStatus === 402 && (code === "payment_required" || code === "deactivated_workspace" || is402BillingCapBody(link.message))) linkKinds |= Flag.UsageLimit;
859
1004
  if (code === "overloaded_error" || code === "rate_limit_error") linkKinds |= Flag.Transient;
860
1005
  if ((codeStatus === 401 || codeStatus === 403) && !(codeStatus === 403 && parseRateLimitReason(link.message) === "CONCURRENT_LIMIT")) linkKinds |= Flag.AuthFailed;
861
1006
  else if (codeStatus === 429) {
@@ -867,7 +1012,7 @@ function classify(error, api) {
867
1012
  if (link instanceof Error) linkMessage = link.message;
868
1013
  else if (typeof link === "string") linkMessage = link;
869
1014
  else if (typeof link === "object" && "message" in link && typeof link.message === "string") linkMessage = link.message;
870
- const textId = classifyText(linkMessage, status(link), api);
1015
+ const textId = classifyText(linkMessage, status(link), causeTokenEvidence, api);
871
1016
  kinds |= textId & KIND_MASK;
872
1017
  link = typeof link === "object" && "cause" in link ? link.cause : void 0;
873
1018
  }
@@ -897,41 +1042,25 @@ function isGrammarError(error) {
897
1042
  function isFastModeUnsupported(error) {
898
1043
  return is(classify(error), Flag.FastModeUnsupported);
899
1044
  }
1045
+ const CLINE_PASS_SURFACE_GATE_PATTERN = /only available via cline product surfaces/i;
900
1046
  /**
901
- * Depth-bounded search for a provider error `code`. SDK error objects keep the
902
- * parsed response body on `.error`, and Copilot's body is itself
903
- * `{ error: { code } }`, so the code sits up to two envelopes below the thrown
904
- * error depending on which SDK produced it.
1047
+ * Cline's gateway gates some roster entries (certain free-tier models) to its
1048
+ * own product surfaces with a 403. The API key is valid — the restriction is
1049
+ * per-model client policy — so it must neither rotate sibling credentials (they
1050
+ * fail identically) nor surface as an auth failure.
905
1051
  */
906
- function providerErrorCode(error) {
907
- let node = error;
908
- for (let depth = 0; depth < 3; depth++) {
909
- if ("code" in node && typeof node.code === "string") return node.code;
910
- if (!("error" in node)) return void 0;
911
- const nested = node.error;
912
- if (!nested || typeof nested !== "object") return void 0;
913
- node = nested;
914
- }
915
- }
916
- /**
917
- * GitHub Copilot 400 `model_not_supported` response for a model advertised by
918
- * `/models` — transient fleet skew, not a malformed request. Reads the
919
- * structural `code` through the SDK/body envelopes, then falls back to the
920
- * stringified body both SDK families put in `message`.
921
- */
922
- function isCopilotTransientModelError(error) {
923
- if (!error || typeof error !== "object" || status(error) !== 400) return false;
924
- const code = providerErrorCode(error);
925
- if (code !== void 0 && Object.hasOwn(COPILOT_TRANSIENT_MODEL_CODES, code)) return true;
926
- const message = "message" in error ? error.message : void 0;
927
- return typeof message === "string" && COPILOT_TRANSIENT_MODEL_PATTERN.test(message);
1052
+ function isClinePassSurfaceGateMessage(errorMessage) {
1053
+ return errorMessage !== void 0 && CLINE_PASS_SURFACE_GATE_PATTERN.test(errorMessage);
928
1054
  }
929
1055
  function classifyMessage(message) {
930
1056
  const existingId = message.errorId;
931
1057
  const currentStatus = message.errorStatus ?? statusFromId(existingId);
932
- const textId = classifyText(message.errorMessage, currentStatus, message.api);
1058
+ const existingOverflowOnly = existingId !== void 0 && is(existingId, Flag.ContextOverflow) && !is(existingId, Flag.PayloadRejected);
1059
+ const classificationMessage = message.errorClassificationMessage ?? message.errorMessage;
1060
+ const textId = classifyText(classificationMessage, currentStatus, existingOverflowOnly, message.api, message.provider, message.model);
933
1061
  let kinds = ((existingId ?? 0) | textId) & KIND_MASK;
934
- if (message.errorMessage && LLAMA_CPP_TOOL_CALL_PARSE_PATTERN.test(message.errorMessage)) kinds &= ~Flag.Transient;
1062
+ if (currentStatus === 413 && classificationMessage && hasTokenContextOverflowEvidence(classificationMessage) && !(textId & Flag.PayloadRejected)) kinds &= ~Flag.PayloadRejected;
1063
+ if (classificationMessage && LLAMA_CPP_TOOL_CALL_PARSE_PATTERN.test(classificationMessage)) kinds &= ~Flag.Transient;
935
1064
  const id = kinds !== 0 ? create(kinds) : statusFromId(textId) ?? statusFromId(existingId) ?? currentStatus ?? 0;
936
1065
  message.errorId = id;
937
1066
  return id;
@@ -967,7 +1096,7 @@ function isRetryableStreamEnvelopeError(error) {
967
1096
  return error instanceof Error && STREAM_EVENT_ORDER_PATTERN.test(error.message);
968
1097
  }
969
1098
  //#endregion
970
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/abort.ts
1099
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/abort.ts
971
1100
  /**
972
1101
  * A request was cancelled — by the caller's `AbortSignal` or a provider-local
973
1102
  * watchdog. Carries the {@link Flag.Abort} classification structurally so retry
@@ -985,7 +1114,7 @@ var AbortError = class extends Error {
985
1114
  }
986
1115
  };
987
1116
  //#endregion
988
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/auth.ts
1117
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/auth.ts
989
1118
  /**
990
1119
  * No API key / credential was available to dispatch a request.
991
1120
  *
@@ -1029,7 +1158,28 @@ var LoginCancelledError = class extends Error {
1029
1158
  }
1030
1159
  };
1031
1160
  //#endregion
1032
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/utils/retry-after.ts
1161
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/oauth.ts
1162
+ /**
1163
+ * A failure inside an interactive OAuth / device-code login flow. The `kind`
1164
+ * pinpoints the stage. Timeout/polling are classified transient; everything
1165
+ * else is a hard auth failure. The auth-retry classifier separately treats
1166
+ * `token-refresh` as an explicit request to refresh and replay once.
1167
+ */
1168
+ var OAuthError = class extends Error {
1169
+ kind;
1170
+ provider;
1171
+ status;
1172
+ constructor(message, options = {}) {
1173
+ super(message, options.cause === void 0 ? void 0 : { cause: options.cause });
1174
+ this.name = "OAuthError";
1175
+ this.kind = options.kind ?? "http";
1176
+ this.provider = options.provider;
1177
+ this.status = options.status;
1178
+ attach(this, this.kind === "timeout" || this.kind === "polling" ? create(Flag.Transient) : create(Flag.AuthFailed));
1179
+ }
1180
+ };
1181
+ //#endregion
1182
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/utils/retry-after.ts
1033
1183
  const RETRY_AFTER_HINT = "retry-after-ms=";
1034
1184
  function formatErrorMessageWithRetryAfter(error, headers) {
1035
1185
  const message = error instanceof Error ? error.message : JSON.stringify(error);
@@ -1105,45 +1255,7 @@ function parseResetHeader(value, unit) {
1105
1255
  return Math.ceil(targetMs - nowMs);
1106
1256
  }
1107
1257
  //#endregion
1108
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/utils/retry.ts
1109
- const COPILOT_MODEL_RETRY_MAX_ATTEMPTS = 8;
1110
- const COPILOT_GENERIC_RETRY_MAX_ATTEMPTS = 3;
1111
- const COPILOT_MODEL_RETRY_BASE_DELAY_MS = 400;
1112
- /** Longest server-requested backoff we are willing to sit out before giving up. */
1113
- const COPILOT_RETRY_AFTER_MAX_WAIT_MS = 3e4;
1114
- /**
1115
- * Wrap an initial Copilot request so transient `model_not_supported` 400s are
1116
- * retried a small number of times. No-op for non-Copilot providers.
1117
- *
1118
- * The callback **MUST** create a fresh in-flight request each invocation — a
1119
- * once-consumed AsyncIterable cannot be re-iterated.
1120
- */
1121
- async function callWithCopilotModelRetry(fn, options) {
1122
- if (options.provider !== "github-copilot") return fn();
1123
- let lastError;
1124
- const retryBaseDelayMs = options.retryBaseDelayMs ?? COPILOT_MODEL_RETRY_BASE_DELAY_MS;
1125
- for (let attempt = 0; attempt < COPILOT_MODEL_RETRY_MAX_ATTEMPTS; attempt++) try {
1126
- return await fn();
1127
- } catch (error) {
1128
- lastError = error;
1129
- if (options.signal?.aborted) throw error;
1130
- const transientModelError = isCopilotTransientModelError(error);
1131
- if (!transientModelError && !isRetryableError(error)) throw error;
1132
- if (attempt >= (transientModelError ? COPILOT_MODEL_RETRY_MAX_ATTEMPTS : COPILOT_GENERIC_RETRY_MAX_ATTEMPTS) - 1) break;
1133
- let delayMs = transientModelError ? retryBaseDelayMs : retryBaseDelayMs * (attempt + 1);
1134
- if (!transientModelError) {
1135
- if (status(error) !== void 0) {
1136
- const retryAfterMs = getRetryAfterMsFromHeaders(getHeadersFromError(error));
1137
- if (retryAfterMs === void 0 || retryAfterMs > COPILOT_RETRY_AFTER_MAX_WAIT_MS) throw error;
1138
- delayMs = Math.max(delayMs, retryAfterMs);
1139
- }
1140
- }
1141
- await scheduler.wait(delayMs, { signal: options.signal });
1142
- }
1143
- throw lastError;
1144
- }
1145
- //#endregion
1146
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/utils/http-inspector.ts
1258
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/utils/http-inspector.ts
1147
1259
  const SENSITIVE_HEADERS = [
1148
1260
  "authorization",
1149
1261
  "x-api-key",
@@ -1174,8 +1286,8 @@ function buildHttp400DumpPayload(dump, error, message) {
1174
1286
  * are excluded: 429/5xx are retried, so persisting them here would write one
1175
1287
  * dump per attempt. */
1176
1288
  function shouldDumpRejectedRequest(error) {
1177
- const status$2 = status(error);
1178
- return status$2 === 400 || status$2 === 413;
1289
+ const status$1 = status(error);
1290
+ return status$1 === 400 || status$1 === 413;
1179
1291
  }
1180
1292
  async function appendRawHttpRequestDumpFor400(message, error, dump) {
1181
1293
  if (!dump || isBunTestRuntime() || !shouldDumpRejectedRequest(error)) return message;
@@ -1202,20 +1314,47 @@ async function finalizeErrorMessage(error, rawRequestDump, capturedErrorResponse
1202
1314
  * Rewrite error message for GitHub Copilot request failures.
1203
1315
  * Must run AFTER finalizeErrorMessage since it replaces the message entirely.
1204
1316
  *
1205
- * 400 `model_not_supported` = Copilot fleet skew. A model that `/models`
1206
- * advertises can flap between 200 and 400 because only part of
1207
- * Copilot's fleet has it in the integrator allowlist. After the
1208
- * in-request retry exhausts, surface guidance rather than the raw error.
1209
1317
  * 401 = token invalid/expired → credential removal is safe, prompt re-login.
1210
1318
  * 403 = token valid but access denied (plan, model policy, org restriction) →
1211
1319
  * do NOT reuse the auth-failed string (which triggers credential removal).
1320
+ * 400 is left verbatim: GitHub's body names the cause (`model_not_supported`,
1321
+ * `model_not_available_for_integrator` with its `Available models` list)
1322
+ * and a rewrite only hides it.
1212
1323
  */
1213
1324
  function rewriteCopilotError(errorMessage, error, provider) {
1214
1325
  if (provider !== "github-copilot") return errorMessage;
1215
- const status$1 = status(error);
1216
- if (status$1 === 401) return `GitHub Copilot authentication failed (HTTP 401). Your token may have been revoked. Please re-login with /login github-copilot`;
1217
- if (status$1 === 403) return `GitHub Copilot access denied (HTTP 403). Your account may not have access to this model or feature. Check your Copilot plan or model policy settings.`;
1218
- if (isCopilotTransientModelError(error)) return `GitHub Copilot rejected this model (HTTP 400) after retries: only part of its fleet currently serves this model id, even though /models advertises it. Try again in a few seconds or switch to a model Copilot serves fleet-wide (claude-opus-4.7, claude-sonnet-4.5, gpt-4.1).`;
1326
+ const status$2 = status(error);
1327
+ if (status$2 === 401) return `GitHub Copilot authentication failed (HTTP 401). Your token may have been revoked. Please re-login with /login github-copilot`;
1328
+ if (status$2 === 403) return `GitHub Copilot access denied (HTTP 403). Your token is valid but the account may not have access to this model or feature. Check your Copilot plan or model policy settings. Business organizations can also restrict which clients may call the API: omp sends Copilot-Integration-Id copilot-chat by default (COPILOT_INTEGRATION_ID overrides it) and retries a denied default-identity request once as the Copilot CLI (copilot-developer-cli). If both identities are denied, ask your org admin to allow one of them; if you pinned an identity, try the other.`;
1329
+ return errorMessage;
1330
+ }
1331
+ const CLINE_PASS_NOT_SUBSCRIBED_PATTERN = /not subscribed to required model plan|no access to clinepass subscription models/i;
1332
+ const CLINE_PASS_ORG_ACCOUNT_PATTERN = /organization accounts cannot use individual model inference subscriptions/i;
1333
+ const CLINE_PASS_MODEL_NOT_FOUND_PATTERN = /model not found/i;
1334
+ /**
1335
+ * Rewrite error messages for ClinePass request failures. Gated to the
1336
+ * cline-pass provider: the "model not found" marker is too generic to match
1337
+ * for other hosts.
1338
+ *
1339
+ * not-subscribed (400) = the key is valid but the account has no ClinePass
1340
+ * subscription; free-tier models remain usable on the same key.
1341
+ * org restriction (400) = organization accounts cannot use individual
1342
+ * inference subscriptions; a personal-account key is required.
1343
+ * model-not-found (400) = roster rotation removed the model since selection;
1344
+ * the fix is reselection, not retry. (Quota windows — "clinepass
1345
+ * limit", "free limit reached on model" — are classified upstream in
1346
+ * error/rate-limit and need no rewrite.)
1347
+ * surface-gate (403) = the model is restricted to Cline's official clients.
1348
+ * Requests carry the mirrored CLI identity headers, so reaching this
1349
+ * means Cline's gate policy changed; the classifier exempts it from
1350
+ * credential rotation (sibling keys fail identically).
1351
+ */
1352
+ function rewriteClinePassError(errorMessage, provider) {
1353
+ if (provider !== "cline-pass") return errorMessage;
1354
+ if (CLINE_PASS_NOT_SUBSCRIBED_PATTERN.test(errorMessage)) return "This model requires a ClinePass subscription. Free-tier models (marked \"(free)\" in the picker) work with any Cline account.";
1355
+ if (CLINE_PASS_ORG_ACCOUNT_PATTERN.test(errorMessage)) return "ClinePass is unavailable for organization accounts: individual inference subscriptions are personal-plan only. Log in with a personal Cline API key.";
1356
+ if (isClinePassSurfaceGateMessage(errorMessage)) return "Cline restricts this model to its official product surfaces and the mirrored CLI client identity was not accepted. Pick another model with /model and report the regression — the header mirror may need updating.";
1357
+ if (CLINE_PASS_MODEL_NOT_FOUND_PATTERN.test(errorMessage)) return "Cline removed this model from the roster since it was selected. Pick another with /model — the roster refreshes automatically while your API key is configured.";
1219
1358
  return errorMessage;
1220
1359
  }
1221
1360
  function sanitizeDump(dump) {
@@ -1278,7 +1417,7 @@ function isObject(value) {
1278
1417
  return typeof value === "object" && value !== null && !Array.isArray(value);
1279
1418
  }
1280
1419
  //#endregion
1281
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/format.ts
1420
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/format.ts
1282
1421
  function rewriteOllamaToolCallJsonError(message) {
1283
1422
  if (!LLAMA_CPP_TOOL_CALL_PARSE_PATTERN.test(message)) return message;
1284
1423
  return `Local Ollama model emitted malformed tool-call JSON and llama.cpp rejected it (HTTP 500). This is usually a deterministic model-output failure after context degradation, not a transient server outage; reload the model or reduce context, then retry.\n${message}`;
@@ -1295,11 +1434,12 @@ function rewriteOllamaToolCallJsonError(message) {
1295
1434
  async function formatMessage(error, opts = {}) {
1296
1435
  let message = opts.rawRequestDump ? await finalizeErrorMessage(error, opts.rawRequestDump, opts.capturedErrorResponse) : formatErrorMessageWithRetryAfter(error);
1297
1436
  if (opts.provider === "github-copilot") message = rewriteCopilotError(message, error, opts.provider);
1437
+ if (opts.provider === "cline-pass") message = rewriteClinePassError(message, opts.provider);
1298
1438
  if (opts.provider === "ollama") message = rewriteOllamaToolCallJsonError(message);
1299
1439
  return message;
1300
1440
  }
1301
1441
  //#endregion
1302
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/finalize.ts
1442
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/finalize.ts
1303
1443
  /**
1304
1444
  * Build the complete error bundle for a provider catch block, replacing the
1305
1445
  * `stopReason` / `errorStatus` / `errorId` / `errorMessage` boilerplate.
@@ -1321,6 +1461,8 @@ async function finalize(error, opts = {}) {
1321
1461
  return {
1322
1462
  id: classifyMessage({
1323
1463
  api: opts.api,
1464
+ provider: opts.provider,
1465
+ model: opts.model,
1324
1466
  errorId: classify(error, opts.api),
1325
1467
  errorMessage: message,
1326
1468
  errorStatus: currentStatus
@@ -1331,27 +1473,7 @@ async function finalize(error, opts = {}) {
1331
1473
  };
1332
1474
  }
1333
1475
  //#endregion
1334
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/oauth.ts
1335
- /**
1336
- * A failure inside an interactive OAuth / device-code login flow. The `kind`
1337
- * pinpoints the stage. Timeout/polling are classified transient; everything
1338
- * else is a hard auth failure so the credential layer does not silently retry.
1339
- */
1340
- var OAuthError = class extends Error {
1341
- kind;
1342
- provider;
1343
- status;
1344
- constructor(message, options = {}) {
1345
- super(message, options.cause === void 0 ? void 0 : { cause: options.cause });
1346
- this.name = "OAuthError";
1347
- this.kind = options.kind ?? "http";
1348
- this.provider = options.provider;
1349
- this.status = options.status;
1350
- attach(this, this.kind === "timeout" || this.kind === "polling" ? create(Flag.Transient) : create(Flag.AuthFailed));
1351
- }
1352
- };
1353
- //#endregion
1354
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/provider.ts
1476
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/provider.ts
1355
1477
  /**
1356
1478
  * A non-HTTP provider failure: a truncated stream, an error stop reason, an
1357
1479
  * empty body, a malformed envelope, or a runtime fault. For non-2xx HTTP
@@ -1375,7 +1497,7 @@ var DevinApiError = class extends ProviderHttpError {
1375
1497
  name = "DevinApiError";
1376
1498
  };
1377
1499
  //#endregion
1378
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/retryable.ts
1500
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/retryable.ts
1379
1501
  /**
1380
1502
  * Whether a numeric HTTP status is in the canonical transient/retryable set:
1381
1503
  * 408 (Request Timeout), 429 (Too Many Requests), and any 5xx.
@@ -1398,12 +1520,11 @@ function isTransientTransportMessage(message) {
1398
1520
  * here — they are owned by the credential-rotation layer (auth-gateway /
1399
1521
  * `streamSimple` a/b/c policy), not this seconds-scale provider backoff.
1400
1522
  *
1401
- * Provider-specific transient cases are injected via {@link ProviderRetryableHooks}
1402
- * so this stays free of provider imports.
1523
+ * Every 4xx other than 408/429 is terminal: a request the provider rejected
1524
+ * as malformed, unauthorized, or unentitled fails identically on replay.
1403
1525
  */
1404
- function isProviderRetryableError(error, hooks = {}) {
1526
+ function isProviderRetryableError(error) {
1405
1527
  if (!(error instanceof Error)) return false;
1406
- if (hooks.isProviderTransient?.(error)) return true;
1407
1528
  if (isUsageLimit(error)) return false;
1408
1529
  const httpStatus = status(error);
1409
1530
  if (httpStatus !== void 0 && httpStatus >= 400 && httpStatus < 500 && httpStatus !== 408 && httpStatus !== 429) return false;
@@ -1412,7 +1533,7 @@ function isProviderRetryableError(error, hooks = {}) {
1412
1533
  return isRetryableError(error);
1413
1534
  }
1414
1535
  //#endregion
1415
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/error/validation.ts
1536
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/error/validation.ts
1416
1537
  /**
1417
1538
  * Caller-supplied input failed validation before/while building a provider
1418
1539
  * request: bad request body, malformed tool arguments, unsupported content
@@ -1446,4 +1567,4 @@ var StreamTimeoutError = class extends Error {
1446
1567
  }
1447
1568
  };
1448
1569
  //#endregion
1449
- export { isTransientStreamParseError as A, OpenAIHttpError as B, classifyMessage as C, isFastModeUnsupported as D, isCopilotTransientModelError as E, AnthropicStreamEnvelopeError as F, fetchWithRetry as G, AwsCredentialsError as H, BedrockApiError as I, GeminiCliApiError as L, AnthropicApiError as M, AnthropicConnectionError as N, isGrammarError as O, AnthropicConnectionTimeoutError as P, GoogleApiError as R, classify as S, is as T, EventStreamFrameError as U, ProviderHttpError as V, extractHttpStatusFromError as W, OnPromptRequiredError as _, isTransientStatus as a, LLAMA_CPP_TOOL_CALL_PARSE_PATTERN as b, OAuthError as c, callWithCopilotModelRetry as d, getHeadersFromError as f, MissingApiKeyError as g, LoginCancelledError as h, isProviderRetryableError as i, retriable as j, isStreamEnvelopeError as k, finalize as l, ApiKeyRequiredError as m, StreamTimeoutError as n, DevinApiError as o, getRetryAfterMsFromHeaders as p, ValidationError as r, ProviderResponseError as s, ConfigurationError as t, finalizeErrorMessage as u, AbortError as v, create as w, attach as x, Flag as y, OllamaApiError as z };
1570
+ export { isTransientStreamParseError as A, OpenAIHttpError as B, classify as C, isFastModeUnsupported as D, is as E, AnthropicStreamEnvelopeError as F, fetchWithRetry as G, AwsCredentialsError as H, BedrockApiError as I, GeminiCliApiError as L, AnthropicApiError as M, AnthropicConnectionError as N, isGrammarError as O, AnthropicConnectionTimeoutError as P, GoogleApiError as R, attach as S, create as T, EventStreamFrameError as U, ProviderHttpError as V, extractHttpStatusFromError as W, AbortError as _, isTransientStatus as a, PYTHON_HTTP2_STREAM_RESET_PATTERN as b, finalize as c, getRetryAfterMsFromHeaders as d, OAuthError as f, OnPromptRequiredError as g, MissingApiKeyError as h, isProviderRetryableError as i, retriable as j, isStreamEnvelopeError as k, finalizeErrorMessage as l, LoginCancelledError as m, StreamTimeoutError as n, DevinApiError as o, ApiKeyRequiredError as p, ValidationError as r, ProviderResponseError as s, ConfigurationError as t, getHeadersFromError as u, Flag as v, classifyMessage as w, PYTHON_HTTP_INCOMPLETE_CHUNK_PATTERN as x, LLAMA_CPP_TOOL_CALL_PARSE_PATTERN as y, OllamaApiError as z };