@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.
- package/THIRD_PARTY_NOTICES.md +9 -3
- package/lib/{abort-Cwwm4Err.mjs → abort-Caqff3M6.mjs} +2 -2
- package/lib/alibaba-coding-plan-DTupMiAi.mjs +73 -0
- package/lib/alibaba-token-plan-CHGyWOfX.mjs +46 -0
- package/lib/alibaba-token-plan-Dj3OZhEE.mjs +82 -0
- package/lib/{amazon-bedrock-TVMpUTRG.mjs → amazon-bedrock-DbFSYXfJ.mjs} +117 -38
- package/lib/{anthropic-BL6LFDQS.mjs → anthropic-CTJ3IQVa.mjs} +675 -166
- package/lib/anthropic-CXfWlp-x.mjs +105 -0
- package/lib/{aws-credentials-B20dliS7.mjs → anthropic-wire-CKuhDwZ1.mjs} +74 -14
- package/lib/{api-key-login-CIDnXeYd.mjs → api-key-validation-CGCJFbFr.mjs} +27 -68
- package/lib/{azure-openai-responses-BkhsLmN3.mjs → azure-openai-responses-ChFbWaGj.mjs} +27 -16
- package/lib/{browser-render-CmgvSNte.mjs → browser-render-9o0Rknop.mjs} +4 -4
- package/lib/bun-shim.mjs +71 -2
- package/lib/{bundled-references-ChZSPDFw.mjs → bundled-references-DY3EJxZV.mjs} +6 -5
- package/lib/cline-pass-Bwg3esu9.mjs +44 -0
- package/lib/cloudflare-ai-gateway-BupNXyKK.mjs +35 -0
- package/lib/cloudflare-ai-gateway-EWo0VkP5.mjs +44 -0
- package/lib/collapse-DOR8sOGf.mjs +2304 -0
- package/lib/coreweave-C82HrLpb.mjs +31 -0
- package/lib/coreweave-Ct8cF-da.mjs +14 -0
- package/lib/{cursor-B6HcmplF.mjs → cursor-B95LzVWV.mjs} +11 -3
- package/lib/{cursor-CRpLpaZ3.mjs → cursor-DJV_dcgB.mjs} +887 -1784
- package/lib/{cursor-B8m6SqAH.mjs → cursor-LKGjucn2.mjs} +48 -38
- package/lib/cursor-proto-B8Wj8bv9.mjs +10513 -0
- package/lib/{deterministic-id-D-yIV_eI.mjs → deterministic-id-CUEIMSqR.mjs} +1 -1
- package/lib/devin-BMTdx_hx.mjs +316 -0
- package/lib/{devin-DUAfvBsW.mjs → devin-DSp0Rw_E.mjs} +172 -86
- package/lib/devin-ExGIghmx.mjs +69 -0
- package/lib/devin-proto-Br8fdyNl.mjs +2888 -0
- package/lib/{dom-CawWi8fa.mjs → dom-DG3sPESc.mjs} +8 -8
- package/lib/effort-BdtQMN-_.mjs +23 -0
- package/lib/{error-C-f_Wnw4.mjs → error-CORgGg5a.mjs} +275 -154
- package/lib/{event-stream-Dh2guZxS.mjs → event-stream-ulcDenZD.mjs} +20 -4
- package/lib/{gemini-headers-DKUShltF.mjs → gemini-headers-Co9cVvex.mjs} +2 -2
- package/lib/{github-copilot-suDymKrx.mjs → github-copilot-Dstq1D3s.mjs} +69 -29
- package/lib/github-copilot-headers-DOh1gt_w.mjs +312 -0
- package/lib/gitlab-duo-DSCMrU0m.mjs +11 -0
- package/lib/google-CtsKkOQK.mjs +38 -0
- package/lib/google-antigravity-z-5KsEci.mjs +252 -0
- package/lib/{google-auth-DYJLM792.mjs → google-auth-ieLBaneO.mjs} +4 -4
- package/lib/{google-gemini-cli-8BT513Ul.mjs → google-gemini-cli-C6NE5mWz.mjs} +28 -54
- package/lib/{google-gemini-cli-D6cSmfvB.mjs → google-gemini-cli-CAIPSl7e.mjs} +23 -29
- package/lib/google-oauth-shared-DhMllAkt.mjs +53 -0
- package/lib/{google-shared-CVbHK5vZ.mjs → google-shared-B0aNCYEH.mjs} +140 -44
- package/lib/{google-validation-Cgbn3tWJ.mjs → google-validation-BEkNs-Bx.mjs} +1 -1
- package/lib/{google-vertex-Bui-ypAe.mjs → google-vertex-Bbd1tYNc.mjs} +8 -8
- package/lib/hosts-00rjRzUD.mjs +203 -0
- package/lib/id-AL5obQzR.mjs +71 -0
- package/lib/{idle-iterator-CYAxUkSD.mjs → idle-iterator-DlUkEfzW.mjs} +3 -3
- package/lib/index.mjs +587 -5266
- package/lib/kilo-ChJL54wq.mjs +81 -0
- package/lib/kimi-C2c_Zq8A.mjs +67 -0
- package/lib/{launch-BmgEUycu.mjs → launch-DKDH71En.mjs} +1 -1
- package/lib/markit-CmRfm4E2.mjs +9885 -0
- package/lib/models-DnXMYGcJ.mjs +381604 -0
- package/lib/muse-code-Di1VZmB1.mjs +143 -0
- package/lib/{ollama-Df9ce-Cp.mjs → ollama-B8ic3sEp.mjs} +15 -30
- package/lib/{openai-codex-CAVI3Me-.mjs → openai-codex-DuJNC99x.mjs} +29 -99
- package/lib/{openai-codex-responses-BcnOotRB.mjs → openai-codex-responses-BL29nh9K.mjs} +204 -116
- package/lib/{openai-completions-Bq4WT47M.mjs → openai-completions-BK2f2dBv.mjs} +152 -82
- package/lib/openai-configuration-update-xMYUjaK_.mjs +150 -0
- package/lib/{openai-reasoning-fallback-DXsfiSXO.mjs → openai-reasoning-fallback-BdB3RCbj.mjs} +106 -12
- package/lib/{openai-responses-Mq_-PjvE.mjs → openai-responses-CGQPlIIy.mjs} +76 -82
- package/lib/{perplexity-XgLF73E7.mjs → perplexity-TBjz3VMB.mjs} +52 -9
- package/lib/{pkce-BlQikGPu.mjs → pkce-BYjmugmw.mjs} +1 -1
- package/lib/protobuf-aab1UGVn.mjs +717 -0
- package/lib/{provider-response-C6vcbQyO.mjs → provider-response-SqKSkkUc.mjs} +1 -1
- package/lib/{proxy-D9lm7ONA.mjs → proxy-5nWqRL1f.mjs} +45 -5
- package/lib/{readability-Cpm-ocau.mjs → readability-uGhqb4GC.mjs} +2 -2
- package/lib/reference-CtvM4zLU.mjs +114 -0
- package/lib/{request-debug-HJMoJncL.mjs → request-debug-NQN0BjHH.mjs} +1 -1
- package/lib/{sanitize-text-CfcXzw5X.mjs → sanitize-text-BCf5KmCf.mjs} +1 -1
- package/lib/{scrapers-Cg5w77td.mjs → scrapers-D8oWspgW.mjs} +12 -12
- package/lib/{src-BcD0_rQR.mjs → src-BwW51vA5.mjs} +979 -388
- package/lib/{sse-debug-CYdjOC96.mjs → sse-debug-B-tkLCPW.mjs} +1 -1
- package/lib/{stream-Bjq8wjfr.mjs → stream-B_7qN-bA.mjs} +3802 -2623
- package/lib/stream-markup-healing-DKT1lnkW.mjs +267 -0
- package/lib/{strict-tool-validation-imVLUcbI.mjs → strict-tool-validation-CBTz1dAA.mjs} +2 -2
- package/lib/taxonomy-DSIM99rS.mjs +15392 -0
- package/lib/{stream-markup-healing-DZ6bVDxH.mjs → thinking-CiLa2LFB.mjs} +31 -186
- package/lib/{turndown-DN7ByzEI.mjs → turndown-DrX1M4WG.mjs} +4 -4
- package/lib/{type-guards-B9VVjRDK.mjs → type-guards-CttAANEx.mjs} +1 -1
- package/lib/{types-DX_bvuus.mjs → types-PVueGi9S.mjs} +2 -2
- package/lib/{utils-C-dSORPa.mjs → utils-CCfhUQen.mjs} +2364 -2676
- package/lib/{utils-Cp2Mxf_U.mjs → utils-CUPhpw9A.mjs} +413 -134
- package/lib/{utils-CQHPEQ3W.mjs → utils-DeWqNWV8.mjs} +2 -2
- package/lib/{vision-guard-mBmtAHx0.mjs → vision-guard-_XwsL1DF.mjs} +14 -29
- package/lib/xai-oauth-CXhnz0gO.mjs +210 -0
- package/lib/{xiaomi-7mE345KX.mjs → xiaomi-psoUItal.mjs} +8 -37
- package/lib/{zai-CeNpMV3W.mjs → zai-ApJ8HBgT.mjs} +8 -71
- package/lib/{zip-BK7UHCwX.mjs → zip-Kd602XNe.mjs} +1 -1
- package/package.json +11 -11
- package/presets/package.json +1 -1
- package/presets/tool-plus-ptc/agent.cordis.yml +1 -1
- package/presets/tool-plus-standard/agent.cordis.yml +1 -1
- package/lib/agent_pb-Rizyt9Zg.mjs +0 -805
- package/lib/anthropic-CDmj476p.mjs +0 -262
- package/lib/api_server_pb-CDZgLMta.mjs +0 -252
- package/lib/callback-server-CFJK-jvK.mjs +0 -398
- package/lib/codex-P1dGpX7G.mjs +0 -54
- package/lib/device-code-CuXTWYwY.mjs +0 -51
- package/lib/devin-BcQwht1W.mjs +0 -114
- package/lib/devin-BvMfGevz.mjs +0 -95
- package/lib/github-copilot-B3kQl0g0.mjs +0 -104
- package/lib/gitlab-duo-BriUTP8k.mjs +0 -155
- package/lib/gitlab-duo-workflow-wK5Ljzmc.mjs +0 -91
- package/lib/google-CE5tFDod.mjs +0 -30
- package/lib/google-antigravity-C1jgNljz.mjs +0 -198
- package/lib/google-oauth-shared-BLVTvokk.mjs +0 -147
- package/lib/grammar-D-NqNUxQ.mjs +0 -49
- package/lib/identity-HNO1Oe9B.mjs +0 -219
- package/lib/kimi-DgcUpPtK.mjs +0 -236
- package/lib/markit-DtGoRE6M.mjs +0 -1417
- package/lib/minimax-code-Y3h5li9N.mjs +0 -53
- package/lib/models-DRA2c_8U.mjs +0 -104660
- package/lib/opencode-BsVw9rCD.mjs +0 -38
- package/lib/to-binary-B1BEBIPC.mjs +0 -6002
- package/lib/wafer-BlhWLweO.mjs +0 -17
- 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,
|
|
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@
|
|
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
|
-
|
|
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)
|
|
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@
|
|
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@
|
|
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
|
-
|
|
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@
|
|
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
|
|
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)
|
|
578
|
-
*
|
|
579
|
-
*
|
|
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@
|
|
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
|
|
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
|
-
/
|
|
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
|
|
789
|
+
const TRANSIENT_ENVELOPE_TRUNCATION_PATTERN = /before message_(?:start|stop)/i;
|
|
678
790
|
const STREAM_READ_ERROR_PATTERN = /stream[_ -]?read[_ -]?error/i;
|
|
679
|
-
|
|
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
|
|
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) &&
|
|
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
|
|
825
|
-
if (!(reason === "CONCURRENT_LIMIT" &&
|
|
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 &&
|
|
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
|
-
*
|
|
902
|
-
*
|
|
903
|
-
*
|
|
904
|
-
*
|
|
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
|
|
907
|
-
|
|
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
|
|
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 (
|
|
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@
|
|
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@
|
|
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@
|
|
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@
|
|
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$
|
|
1178
|
-
return status$
|
|
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$
|
|
1216
|
-
if (status$
|
|
1217
|
-
if (status$
|
|
1218
|
-
|
|
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@
|
|
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@
|
|
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@
|
|
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@
|
|
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
|
-
*
|
|
1402
|
-
*
|
|
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
|
|
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@
|
|
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,
|
|
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 };
|