@eddyskywalker/dsh-chatgpt-subscription 0.12.3 → 0.12.4
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/lib/index.js
CHANGED
|
@@ -21610,8 +21610,10 @@ function assertStreamComplete$3(state) {
|
|
|
21610
21610
|
* - `INVALID_CREDENTIAL` — a rejected access token fails identically on every
|
|
21611
21611
|
* attempt;
|
|
21612
21612
|
* - `PROVIDER_ERROR` — a 400, a 401 that is really a plan-entitlement refusal,
|
|
21613
|
-
* or a 403 quota limit. Retrying a quota that resets in hours
|
|
21614
|
-
* requests and delays the message the user needs to
|
|
21613
|
+
* or a 403 quota limit. Retrying a quota that resets in hours against the
|
|
21614
|
+
* SAME account only burns requests and delays the message the user needs to
|
|
21615
|
+
* see, so none of it is retried; a 403 limit still rotates to another account
|
|
21616
|
+
* when the pool holds one, which is a routing decision rather than a retry;
|
|
21615
21617
|
* - `ABORTED` — the caller already cancelled.
|
|
21616
21618
|
*
|
|
21617
21619
|
* The DSH normal defaults would apply anyway; stating the values here pins them
|
|
@@ -21695,17 +21697,20 @@ function classifyKimiFailure(status, bodyText) {
|
|
|
21695
21697
|
if (isHttpContextOverflow(status, bodyText)) return {
|
|
21696
21698
|
code: CONTEXT_OVERFLOW_CODE,
|
|
21697
21699
|
retryable: false,
|
|
21700
|
+
accountScoped: false,
|
|
21698
21701
|
message: `${PROVIDER_NAME$3} context window exceeded: ${detail}`
|
|
21699
21702
|
};
|
|
21700
21703
|
if (status === 402) return {
|
|
21701
21704
|
code: "SERVER",
|
|
21702
21705
|
retryable: true,
|
|
21706
|
+
accountScoped: false,
|
|
21703
21707
|
message: `${PROVIDER_NAME$3} could not verify the subscription tier (402). Retrying; if it persists, confirm the membership is active.${detail ? ` ${detail}` : ""}`
|
|
21704
21708
|
};
|
|
21705
21709
|
if (status === 401 || status === 403) {
|
|
21706
21710
|
if (matchesAny$1(detail, ENTITLEMENT_PATTERNS)) return {
|
|
21707
21711
|
code: "PROVIDER_ERROR",
|
|
21708
21712
|
retryable: false,
|
|
21713
|
+
accountScoped: false,
|
|
21709
21714
|
message: `${PROVIDER_NAME$3} refused this request for the current plan: ${detail || "the requested model or context is not included"}. Switch to a model the plan includes, lower the context-window override, or upgrade the subscription.`
|
|
21710
21715
|
};
|
|
21711
21716
|
if (status === 403) {
|
|
@@ -21713,12 +21718,14 @@ function classifyKimiFailure(status, bodyText) {
|
|
|
21713
21718
|
return {
|
|
21714
21719
|
code: "PROVIDER_ERROR",
|
|
21715
21720
|
retryable: false,
|
|
21721
|
+
accountScoped: true,
|
|
21716
21722
|
message: `${PROVIDER_NAME$3} blocked the request on an account limit (403): ${detail || (limitReached ? "the account limit was reached" : "the account refused the request")}. The quota refreshes on its own schedule — check the Kimi Code card in Settings for the reset time.`
|
|
21717
21723
|
};
|
|
21718
21724
|
}
|
|
21719
21725
|
return {
|
|
21720
21726
|
code: "INVALID_CREDENTIAL",
|
|
21721
21727
|
retryable: false,
|
|
21728
|
+
accountScoped: false,
|
|
21722
21729
|
message: `${PROVIDER_NAME$3} rejected the stored credential (401). Sign in again from Settings > Kimi Code.${detail ? ` ${detail}` : ""}`
|
|
21723
21730
|
};
|
|
21724
21731
|
}
|
|
@@ -21726,32 +21733,81 @@ function classifyKimiFailure(status, bodyText) {
|
|
|
21726
21733
|
if (matchesAny$1(detail, QUOTA_EXHAUSTED_PATTERNS$1)) return {
|
|
21727
21734
|
code: "PROVIDER_ERROR",
|
|
21728
21735
|
retryable: false,
|
|
21736
|
+
accountScoped: true,
|
|
21729
21737
|
message: `${PROVIDER_NAME$3} reports the account quota is exhausted: ${detail || "no remaining quota"}. Top up or wait for the window to reset.`
|
|
21730
21738
|
};
|
|
21731
21739
|
return {
|
|
21732
21740
|
code: "RATE_LIMIT",
|
|
21733
21741
|
retryable: true,
|
|
21742
|
+
accountScoped: false,
|
|
21734
21743
|
message: `${PROVIDER_NAME$3} is rate limited or overloaded (429): ${detail || "too many requests"}. Retrying with backoff.`
|
|
21735
21744
|
};
|
|
21736
21745
|
}
|
|
21737
21746
|
if (status >= 500) return {
|
|
21738
21747
|
code: "SERVER",
|
|
21739
21748
|
retryable: true,
|
|
21749
|
+
accountScoped: false,
|
|
21740
21750
|
message: `${PROVIDER_NAME$3} upstream server error (${status}): ${detail || "the model provider is temporarily unavailable"}. Retrying with backoff.`
|
|
21741
21751
|
};
|
|
21742
21752
|
if (status === 400) return {
|
|
21743
21753
|
code: "PROVIDER_ERROR",
|
|
21744
21754
|
retryable: false,
|
|
21755
|
+
accountScoped: false,
|
|
21745
21756
|
message: `${PROVIDER_NAME$3} rejected the request (400): ${detail || "the request was not accepted"}`
|
|
21746
21757
|
};
|
|
21747
21758
|
return {
|
|
21748
21759
|
code: "PROVIDER_ERROR",
|
|
21749
21760
|
retryable: false,
|
|
21761
|
+
accountScoped: false,
|
|
21750
21762
|
message: `${PROVIDER_NAME$3} API error (${status}): ${detail || "No response"}`
|
|
21751
21763
|
};
|
|
21752
21764
|
}
|
|
21765
|
+
/** Numeric reset the service may ship as a field rather than in prose. */
|
|
21766
|
+
const RESET_FIELD_PATTERN = /"?reset[A-Za-z_]*"?\s*[:=]\s*"?(\d{9,16})"?/i;
|
|
21767
|
+
/** ISO instant quoted in prose, trusted only when it names its own zone. */
|
|
21768
|
+
const RESET_INSTANT_PATTERN = /\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(?::\d{2})?(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})/;
|
|
21769
|
+
/** The window a billing-cycle refusal names; nothing shorter describes it. */
|
|
21770
|
+
const BILLING_CYCLE_PATTERN = /usage limit for this billing cycle/i;
|
|
21771
|
+
/**
|
|
21772
|
+
* How long one account stays out of rotation after it reports a spent limit.
|
|
21773
|
+
*
|
|
21774
|
+
* The reset instant is read from the body whenever the service states one — as a
|
|
21775
|
+
* numeric field, or as an instant carrying its own zone — and the length of the
|
|
21776
|
+
* window the service names is used otherwise. The zone is required for that
|
|
21777
|
+
* instant because an unqualified one is ambiguous, and a cooldown computed from
|
|
21778
|
+
* the wrong zone is either hours too long or already over; where the body is
|
|
21779
|
+
* ambiguous the window length is the honest answer.
|
|
21780
|
+
*
|
|
21781
|
+
* Both ends of the range are load-bearing. A reset instant barely in the future
|
|
21782
|
+
* would otherwise read as no cooldown at all and put the account straight back
|
|
21783
|
+
* into rotation to be refused again; and a reset instant already in the past
|
|
21784
|
+
* (a stale cache, a clock skew) falls back to the window length above rather
|
|
21785
|
+
* than to no cooldown at all.
|
|
21786
|
+
*/
|
|
21787
|
+
function accountLimitCooldownMs(bodyText, now = Date.now()) {
|
|
21788
|
+
const field = bodyText.match(RESET_FIELD_PATTERN);
|
|
21789
|
+
const instant = bodyText.match(RESET_INSTANT_PATTERN);
|
|
21790
|
+
const resetsAt = field !== null ? parseTimestamp(Number(field[1])) : instant !== null ? Date.parse(instant[0].replace(" ", "T")) : null;
|
|
21791
|
+
if (resetsAt !== null && Number.isFinite(resetsAt) && resetsAt > now) return Math.min(Math.max(resetsAt - now, POOL_COOLDOWN_MS$2), MAX_ACCOUNT_LIMIT_COOLDOWN_MS);
|
|
21792
|
+
return BILLING_CYCLE_PATTERN.test(bodyText) ? BILLING_CYCLE_COOLDOWN_MS : ACCOUNT_LIMIT_COOLDOWN_MS;
|
|
21793
|
+
}
|
|
21753
21794
|
/** Cooldown one rate-limited account takes when the provider states no delay. */
|
|
21754
21795
|
const POOL_COOLDOWN_MS$2 = 15 * 6e4;
|
|
21796
|
+
/**
|
|
21797
|
+
* Fallback cooldown for an account whose usage window is spent.
|
|
21798
|
+
*
|
|
21799
|
+
* The service states the reset time only sometimes, so the fallback is the
|
|
21800
|
+
* window's own length. The 15 minutes a 429 gets would put the account back
|
|
21801
|
+
* into rotation four times inside the very window that just refused it.
|
|
21802
|
+
*/
|
|
21803
|
+
const ACCOUNT_LIMIT_COOLDOWN_MS = 300 * 6e4;
|
|
21804
|
+
/**
|
|
21805
|
+
* A billing cycle is not a window: a 5-hour cooldown would spend a request every
|
|
21806
|
+
* five hours to learn an answer that changes at most once a month.
|
|
21807
|
+
*/
|
|
21808
|
+
const BILLING_CYCLE_COOLDOWN_MS = 720 * 60 * 6e4;
|
|
21809
|
+
/** Ceiling, so a malformed reset time cannot park an account for years. */
|
|
21810
|
+
const MAX_ACCOUNT_LIMIT_COOLDOWN_MS = BILLING_CYCLE_COOLDOWN_MS;
|
|
21755
21811
|
var KimiCodeAdapter = class extends LlmAdapter {
|
|
21756
21812
|
store;
|
|
21757
21813
|
modelSettings;
|
|
@@ -21936,11 +21992,15 @@ var KimiCodeAdapter = class extends LlmAdapter {
|
|
|
21936
21992
|
if (pool !== null && accountId !== void 0) {
|
|
21937
21993
|
const planScoped = response.status === 429 && matchesAny$1(detail, ENTITLEMENT_PATTERNS);
|
|
21938
21994
|
if (response.status === 429 && !planScoped) {
|
|
21939
|
-
|
|
21995
|
+
const cooldownMs = failure.accountScoped ? accountLimitCooldownMs(detail) : after ?? POOL_COOLDOWN_MS$2;
|
|
21996
|
+
await pool.markCooldown(accountId, cooldownMs, `${PROVIDER_NAME$3} 429`).catch(() => void 0);
|
|
21940
21997
|
if (await pool.hasAnotherAvailableAccount(tried)) continue;
|
|
21941
21998
|
} else if (failure.code === "INVALID_CREDENTIAL") {
|
|
21942
21999
|
await pool.markAuthFailed(accountId, failure.message).catch(() => void 0);
|
|
21943
22000
|
if (await pool.hasAnotherAvailableAccount(tried)) continue;
|
|
22001
|
+
} else if (failure.accountScoped) {
|
|
22002
|
+
await pool.markCooldown(accountId, accountLimitCooldownMs(detail), `${PROVIDER_NAME$3} 403`).catch(() => void 0);
|
|
22003
|
+
if (await pool.hasAnotherAvailableAccount(tried)) continue;
|
|
21944
22004
|
}
|
|
21945
22005
|
}
|
|
21946
22006
|
throw new LlmError(failure.message, failure.code, {
|
|
@@ -28,8 +28,10 @@ import { KimiCodeAccountPool } from './account-pool.ts';
|
|
|
28
28
|
* - `INVALID_CREDENTIAL` — a rejected access token fails identically on every
|
|
29
29
|
* attempt;
|
|
30
30
|
* - `PROVIDER_ERROR` — a 400, a 401 that is really a plan-entitlement refusal,
|
|
31
|
-
* or a 403 quota limit. Retrying a quota that resets in hours
|
|
32
|
-
* requests and delays the message the user needs to
|
|
31
|
+
* or a 403 quota limit. Retrying a quota that resets in hours against the
|
|
32
|
+
* SAME account only burns requests and delays the message the user needs to
|
|
33
|
+
* see, so none of it is retried; a 403 limit still rotates to another account
|
|
34
|
+
* when the pool holds one, which is a routing decision rather than a retry;
|
|
33
35
|
* - `ABORTED` — the caller already cancelled.
|
|
34
36
|
*
|
|
35
37
|
* The DSH normal defaults would apply anyway; stating the values here pins them
|
|
@@ -63,6 +65,22 @@ export interface KimiFailureClassification {
|
|
|
63
65
|
message: string;
|
|
64
66
|
/** True only when the failure is worth retrying. */
|
|
65
67
|
retryable: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* True when the refusal belongs to THIS account alone, so another pooled
|
|
70
|
+
* account may still serve the same request.
|
|
71
|
+
*
|
|
72
|
+
* A spent usage window is the case that matters, and this service reports it
|
|
73
|
+
* as a 403 — neither a bad credential nor retryable back-pressure, so nothing
|
|
74
|
+
* in the code or the message says "rotate". Asking the same account again
|
|
75
|
+
* cannot help; taking it out of rotation until its window resets lets the next
|
|
76
|
+
* account answer, and each account in the pool carries its own quota.
|
|
77
|
+
*
|
|
78
|
+
* False for every verdict that belongs to the request or to the plan: an
|
|
79
|
+
* entitlement refusal, a malformed body, ordinary overload. Rotating on one of
|
|
80
|
+
* those would spend every account in the pool to learn the same answer from
|
|
81
|
+
* each of them.
|
|
82
|
+
*/
|
|
83
|
+
accountScoped: boolean;
|
|
66
84
|
}
|
|
67
85
|
/** Short, single-line excerpt of one error body, safe to show a user. */
|
|
68
86
|
export declare function summarizeFailureBody(raw: string): string;
|
|
@@ -73,6 +91,23 @@ export declare function summarizeFailureBody(raw: string): string;
|
|
|
73
91
|
* @param bodyText - raw response body, used to separate overloaded statuses.
|
|
74
92
|
*/
|
|
75
93
|
export declare function classifyKimiFailure(status: number, bodyText: string): KimiFailureClassification;
|
|
94
|
+
/**
|
|
95
|
+
* How long one account stays out of rotation after it reports a spent limit.
|
|
96
|
+
*
|
|
97
|
+
* The reset instant is read from the body whenever the service states one — as a
|
|
98
|
+
* numeric field, or as an instant carrying its own zone — and the length of the
|
|
99
|
+
* window the service names is used otherwise. The zone is required for that
|
|
100
|
+
* instant because an unqualified one is ambiguous, and a cooldown computed from
|
|
101
|
+
* the wrong zone is either hours too long or already over; where the body is
|
|
102
|
+
* ambiguous the window length is the honest answer.
|
|
103
|
+
*
|
|
104
|
+
* Both ends of the range are load-bearing. A reset instant barely in the future
|
|
105
|
+
* would otherwise read as no cooldown at all and put the account straight back
|
|
106
|
+
* into rotation to be refused again; and a reset instant already in the past
|
|
107
|
+
* (a stale cache, a clock skew) falls back to the window length above rather
|
|
108
|
+
* than to no cooldown at all.
|
|
109
|
+
*/
|
|
110
|
+
export declare function accountLimitCooldownMs(bodyText: string, now?: number): number;
|
|
76
111
|
export interface KimiCodeAdapterOptions {
|
|
77
112
|
fetchFn?: typeof fetch;
|
|
78
113
|
attachments?: AttachmentImageReader;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/host/kimi-code/adapter.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,UAAU,EAEV,iBAAiB,EAEjB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAGL,WAAW,EAOX,mBAAmB,EACpB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EAEtB,KAAK,oBAAoB,EAEzB,KAAK,uBAAuB,EAC7B,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/host/kimi-code/adapter.ts"],"names":[],"mappings":"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"}
|