agl 40.4.0 → 40.5.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/changelog.md +27 -0
- package/dist_serve/bundle.js +2228 -2177
- package/dist_serve/bundle.js.map +2 -2
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/aglapi/aglapisurface.document.js +2 -2
- package/dist_ts/classes.accountsactions.d.ts +11 -1
- package/dist_ts/classes.accountsactions.js +59 -2
- package/dist_ts/classes.controller.js +5 -5
- package/dist_ts/classes.flexaccountaccess.js +3 -2
- package/dist_ts/classes.harnessreleases.d.ts +14 -4
- package/dist_ts/classes.harnessreleases.js +28 -4
- package/dist_ts/classes.inferencegateway.d.ts +28 -3
- package/dist_ts/classes.inferencegateway.js +177 -61
- package/dist_ts/classes.inferenceplacement.d.ts +5 -3
- package/dist_ts/classes.inferenceplacement.js +2 -2
- package/dist_ts/classes.inferencerouter.d.ts +349 -91
- package/dist_ts/classes.inferencerouter.js +804 -297
- package/dist_ts/classes.inferenceservice.d.ts +14 -2
- package/dist_ts/classes.inferenceservice.js +53 -14
- package/dist_ts/classes.inferencespend.d.ts +339 -0
- package/dist_ts/classes.inferencespend.js +815 -0
- package/dist_ts/classes.inferenceusagecache.d.ts +8 -0
- package/dist_ts/classes.inferenceusagecache.js +9 -5
- package/dist_ts/classes.inferenceusagetap.d.ts +50 -9
- package/dist_ts/classes.inferenceusagetap.js +185 -31
- package/dist_ts/classes.proxycontrol.d.ts +3 -2
- package/dist_ts/classes.proxycontrol.js +1 -2
- package/dist_ts/classes.proxydaemon.js +3 -2
- package/dist_ts/classes.proxystore.d.ts +6 -0
- package/dist_ts/classes.proxystore.js +11 -2
- package/dist_ts/fleet/classes.claudeworkers.d.ts +5 -4
- package/dist_ts/fleet/classes.claudeworkers.js +10 -9
- package/dist_ts/functions.claudecoderelease.d.ts +12 -6
- package/dist_ts/functions.claudecoderelease.js +13 -7
- package/dist_ts/functions.inferencecli.js +12 -8
- package/dist_ts/interfaces.auth.d.ts +1 -1
- package/dist_ts/interfaces.auth.js +3 -1
- package/dist_ts/plugins.d.ts +3 -1
- package/dist_ts/plugins.js +7 -2
- package/dist_ts_authswitch/authority-apikeys.d.ts +32 -0
- package/dist_ts_authswitch/authority-apikeys.js +65 -0
- package/dist_ts_authswitch/authority-contract.d.ts +142 -28
- package/dist_ts_authswitch/authority-contract.js +48 -1
- package/dist_ts_authswitch/authority-overview.js +8 -1
- package/dist_ts_authswitch/authority-placement.d.ts +7 -2
- package/dist_ts_authswitch/authority-placement.js +10 -3
- package/dist_ts_authswitch/authority-runtime-contract.d.ts +2 -2
- package/dist_ts_authswitch/authority-spend.d.ts +103 -0
- package/dist_ts_authswitch/authority-spend.js +110 -0
- package/dist_ts_authswitch/authority-subscription.d.ts +12 -1
- package/dist_ts_authswitch/authority-subscription.js +24 -1
- package/dist_ts_authswitch/authority-usagelimit.d.ts +7 -4
- package/dist_ts_authswitch/authority-usagelimit.js +89 -39
- package/dist_ts_authswitch/authority-usagewindows.d.ts +4 -1
- package/dist_ts_authswitch/authority-usagewindows.js +41 -16
- package/dist_ts_authswitch/classes.authoritybroker.d.ts +30 -19
- package/dist_ts_authswitch/classes.authoritybroker.js +152 -61
- package/dist_ts_authswitch/classes.authoritycli.d.ts +9 -4
- package/dist_ts_authswitch/classes.authoritycli.js +94 -29
- package/dist_ts_authswitch/classes.authorityclient.d.ts +24 -7
- package/dist_ts_authswitch/classes.authorityclient.js +31 -11
- package/dist_ts_authswitch/classes.authoritydaemon.js +39 -12
- package/dist_ts_authswitch/classes.authoritydatabase.d.ts +28 -5
- package/dist_ts_authswitch/classes.authoritydatabase.js +171 -9
- package/dist_ts_authswitch/classes.authorityimport.js +2 -2
- package/dist_ts_authswitch/classes.authoritymodels.d.ts +71 -3
- package/dist_ts_authswitch/classes.authoritymodels.js +249 -20
- package/dist_ts_authswitch/classes.authorityregistry.js +4 -2
- package/dist_ts_authswitch/classes.authorityusage.d.ts +69 -7
- package/dist_ts_authswitch/classes.authorityusage.js +118 -4
- package/dist_ts_authswitch/classes.claudenative.d.ts +16 -7
- package/dist_ts_authswitch/classes.claudenative.js +29 -16
- package/dist_ts_authswitch/classes.claudesignin.js +5 -2
- package/dist_ts_authswitch/testsupport.d.ts +24 -5
- package/dist_ts_authswitch/testsupport.js +56 -12
- package/dist_ts_authswitch/ts_migration/0011_account_api_key_fields.d.ts +12 -0
- package/dist_ts_authswitch/ts_migration/0011_account_api_key_fields.js +21 -0
- package/dist_ts_authswitch/ts_migration/index.js +3 -1
- package/dist_ts_interfaces/functions.authorityscope.d.ts +18 -7
- package/dist_ts_interfaces/functions.authorityscope.js +35 -8
- package/dist_ts_interfaces/interfaces.d.ts +1 -1
- package/dist_ts_interfaces/interfaces.js +1 -1
- package/dist_ts_interfaces/plugins.d.ts +2 -1
- package/dist_ts_interfaces/plugins.js +7 -4
- package/dist_ts_interfaces/requests.accounts.d.ts +56 -0
- package/dist_ts_interfaces/requests.accounts.js +11 -1
- package/dist_ts_interfaces/requests.d.ts +2 -2
- package/dist_ts_interfaces/requests.js +1 -1
- package/docs/authswitch.md +75 -12
- package/package.json +5 -5
- package/readme.md +198 -21
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/aglapi/aglapisurface.document.ts +2 -2
- package/ts/classes.accountsactions.ts +75 -1
- package/ts/classes.controller.ts +4 -4
- package/ts/classes.flexaccountaccess.ts +2 -1
- package/ts/classes.harnessreleases.ts +25 -4
- package/ts/classes.inferencegateway.ts +184 -64
- package/ts/classes.inferenceplacement.ts +6 -4
- package/ts/classes.inferencerouter.ts +1026 -314
- package/ts/classes.inferenceservice.ts +56 -13
- package/ts/classes.inferencespend.ts +870 -0
- package/ts/classes.inferenceusagecache.ts +16 -4
- package/ts/classes.inferenceusagetap.ts +159 -34
- package/ts/classes.proxycontrol.ts +3 -3
- package/ts/classes.proxydaemon.ts +2 -1
- package/ts/classes.proxystore.ts +11 -1
- package/ts/fleet/classes.claudeworkers.ts +9 -8
- package/ts/functions.claudecoderelease.ts +13 -6
- package/ts/functions.inferencecli.ts +11 -7
- package/ts/interfaces.auth.ts +2 -0
- package/ts/plugins.ts +7 -0
- package/ts_authswitch/authority-apikeys.ts +85 -0
- package/ts_authswitch/authority-contract.ts +167 -29
- package/ts_authswitch/authority-overview.ts +7 -0
- package/ts_authswitch/authority-placement.ts +12 -4
- package/ts_authswitch/authority-runtime-contract.ts +2 -2
- package/ts_authswitch/authority-spend.ts +168 -0
- package/ts_authswitch/authority-subscription.ts +28 -1
- package/ts_authswitch/authority-usagelimit.ts +95 -40
- package/ts_authswitch/authority-usagewindows.ts +42 -17
- package/ts_authswitch/classes.authoritybroker.ts +161 -68
- package/ts_authswitch/classes.authoritycli.ts +108 -32
- package/ts_authswitch/classes.authorityclient.ts +41 -10
- package/ts_authswitch/classes.authoritydaemon.ts +43 -13
- package/ts_authswitch/classes.authoritydatabase.ts +178 -8
- package/ts_authswitch/classes.authorityimport.ts +1 -1
- package/ts_authswitch/classes.authoritymodels.ts +165 -19
- package/ts_authswitch/classes.authorityregistry.ts +3 -0
- package/ts_authswitch/classes.authorityusage.ts +171 -10
- package/ts_authswitch/classes.claudenative.ts +28 -15
- package/ts_authswitch/classes.claudesignin.ts +4 -1
- package/ts_authswitch/native-contracts.md +81 -20
- package/ts_authswitch/readme.md +1 -1
- package/ts_authswitch/testsupport.ts +58 -11
- package/ts_authswitch/ts_migration/0011_account_api_key_fields.ts +20 -0
- package/ts_authswitch/ts_migration/index.ts +2 -0
- package/ts_interfaces/functions.authorityscope.ts +43 -8
- package/ts_interfaces/interfaces.ts +1 -1
- package/ts_interfaces/plugins.ts +6 -3
- package/ts_interfaces/requests.accounts.ts +48 -0
- package/ts_interfaces/requests.ts +4 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/accounts.plugins.ts +3 -1
- package/ts_web/accounts.templates.ts +20 -11
- package/ts_web/classes.accountsreadmodel.ts +322 -70
- package/ts_web/elements.accounts.ts +219 -20
- package/ts_web/elements.codexconnections.ts +3 -1
- package/ts_web/plugins.ts +4 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import type { TInferenceCredential, TInferenceProvider } from './functions.proxycontract.js';
|
|
3
3
|
import type { IGatewayAuthorityAccess } from './classes.flexaccountaccess.js';
|
|
4
|
+
import type { IInferenceSpendRecord } from './classes.inferencespend.js';
|
|
4
5
|
export type TInferenceModel = plugins.openAiProvider.IOpenAiChatGptModel;
|
|
5
6
|
/** A model a Claude account or an Anthropic API key may use, as the Anthropic API lists it. */
|
|
6
7
|
export type TInferenceClaudeModel = plugins.anthropicProvider.IAnthropicOAuthModel;
|
|
@@ -15,30 +16,49 @@ export declare const parseHttpDate: (valueArg: string, nowArg: number) => number
|
|
|
15
16
|
* counted from `nowArg` (a date already past is 0). `undefined` when the header is absent or neither form.
|
|
16
17
|
*/
|
|
17
18
|
export declare const inferenceRetryAfterSeconds: (valueArg: string | null, nowArg: number) => number | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* The credential tiers a pool is served from, best first: the one a policy names alone, or with none the provider's
|
|
21
|
+
* subscription sign-ins first and its API keys after them. A key takes a request only when no subscription can take it,
|
|
22
|
+
* for whatever reason, and a session placed on a key returns to a subscription at the next request one can take.
|
|
23
|
+
*/
|
|
24
|
+
export declare const inferenceCredentialTiers: (credentialArg: TInferenceCredential | undefined) => readonly TInferenceCredential[];
|
|
18
25
|
export interface IInferenceAccount {
|
|
19
26
|
id: string;
|
|
20
27
|
label: string;
|
|
21
28
|
revision: string;
|
|
22
29
|
providerId: TInferenceProvider;
|
|
23
|
-
/** What the account authenticates with: a subscription sign-in, or an
|
|
30
|
+
/** What the account authenticates with: a subscription sign-in, or an API key. */
|
|
24
31
|
credential: TInferenceCredential;
|
|
25
32
|
/** The account's usage threshold (`IAuthSwitchAccount.maxUsagePercent`); `null` when unset. */
|
|
26
33
|
maxUsagePercent: number | null;
|
|
27
34
|
reserveLiftUntil: string | null;
|
|
28
35
|
/** When the account's subscription ends (`IAuthSwitchAccount.lapsesAt`); `null` while it renews. */
|
|
29
36
|
lapsesAt: string | null;
|
|
37
|
+
/**
|
|
38
|
+
* An API key's monthly spend limit in micro-dollars (`IAuthSwitchAccount.spendLimitMicroUsd`); `null` without one,
|
|
39
|
+
* and for a sign-in. It decides only whether a key whose spend the proxy holds no reading of may take work: one with
|
|
40
|
+
* a limit may not (`spend_unread`). A spend reading carries the limit the key is judged against.
|
|
41
|
+
*/
|
|
42
|
+
spendLimitMicroUsd: number | null;
|
|
43
|
+
/**
|
|
44
|
+
* The login the account's requests are served on (the account service's gateway login of it), as the pool was read;
|
|
45
|
+
* `null` when the account service names none. An API key's spend is reported on it.
|
|
46
|
+
*/
|
|
47
|
+
loginId: string | null;
|
|
30
48
|
}
|
|
31
49
|
export interface IInferenceRoutingPolicy {
|
|
32
50
|
/** The pool's provider; omitted means ChatGPT accounts (`openai`). */
|
|
33
51
|
provider?: TInferenceProvider;
|
|
34
52
|
/**
|
|
35
|
-
* What the pool's accounts authenticate with
|
|
36
|
-
*
|
|
53
|
+
* What the pool's accounts authenticate with. Omitted, a Claude pool is served by its Claude accounts first and its
|
|
54
|
+
* Anthropic API keys when no Claude account can take a request (`inferenceCredentialTiers`), a ChatGPT pool by its
|
|
55
|
+
* ChatGPT accounts. `subscription` names the sign-ins alone; `api_key` is an Anthropic pool's alone: its Anthropic API
|
|
56
|
+
* keys, which Flex's Claude models run on, never a Claude account.
|
|
37
57
|
*/
|
|
38
58
|
credential?: TInferenceCredential;
|
|
39
59
|
/** Omitted means all eligible authority-owned accounts of the provider. */
|
|
40
60
|
accountIds?: readonly string[];
|
|
41
|
-
/** Exact current provider plan names; omission accepts every entitled plan. */
|
|
61
|
+
/** Exact current provider plan names; omission accepts every entitled plan. A key has no plan, so this leaves keys out. */
|
|
42
62
|
plans?: readonly string[];
|
|
43
63
|
}
|
|
44
64
|
export interface IInferenceRouterOptions {
|
|
@@ -64,18 +84,48 @@ export interface IInferenceRouterOptions {
|
|
|
64
84
|
*/
|
|
65
85
|
reportAccount?: (changeArg: IInferenceAccountChange) => void;
|
|
66
86
|
/**
|
|
67
|
-
* Tells the account service that
|
|
68
|
-
* `
|
|
69
|
-
*
|
|
87
|
+
* Tells the account service that the provider refused a request on the account for a payment problem at
|
|
88
|
+
* `observedAtArg` -- a Claude account's billing error (HTTP 402 `billing_error`), or an API key's refusal for
|
|
89
|
+
* `causeArg` (`TInferencePaymentCause`); resolves once the service holds it, so the account's usage carries it from
|
|
90
|
+
* then on (`IAuthSwitchUsageSnapshot.paymentProblem`). Unset, the router holds the account out of rotation itself.
|
|
70
91
|
*/
|
|
71
|
-
reportPaymentProblem?: (accountIdArg: string, observedAtArg: string) => Promise<void>;
|
|
92
|
+
reportPaymentProblem?: (accountIdArg: string, observedAtArg: string, causeArg: TInferencePaymentCause) => Promise<void>;
|
|
72
93
|
/**
|
|
73
94
|
* Where a payment problem the account service could not be told of is reported: once per account, never per request.
|
|
74
95
|
* One line on standard error, the proxy's journal, when unset.
|
|
75
96
|
*/
|
|
76
97
|
reportPaymentFailure?: (failureArg: IInferencePaymentReportFailure) => void;
|
|
98
|
+
/**
|
|
99
|
+
* Where the spend of the answers relayed on API keys is kept until the accounts service acknowledged it
|
|
100
|
+
* (`InferenceSpendOutbox`). A key's usage arrives judged with that spend already (`InferenceUsageCache` `view`).
|
|
101
|
+
*/
|
|
102
|
+
spend?: IInferenceSpendLedger;
|
|
77
103
|
now?: () => number;
|
|
78
104
|
}
|
|
105
|
+
/** What the router asks of the proxy's spend outbox (`InferenceSpendOutbox`). */
|
|
106
|
+
export interface IInferenceSpendLedger {
|
|
107
|
+
/**
|
|
108
|
+
* Counts a relayed answer's spend and keeps it until the accounts service acknowledged it, reported on the login the
|
|
109
|
+
* route was served on (`IInferenceClaudeRoute.loginId`); `null` when none could be named, which still counts.
|
|
110
|
+
*/
|
|
111
|
+
record(accountIdArg: string, loginIdArg: string | null, recordArg: IInferenceSpendRecord): void;
|
|
112
|
+
/**
|
|
113
|
+
* Whether spend relayed on the key is recorded nowhere yet: the accounts service refused a report the outbox still
|
|
114
|
+
* holds, an answer is in neither the outbox's store, whose write failed, nor the ledger, or no login of the key could
|
|
115
|
+
* be named for an answer, so it cannot be reported.
|
|
116
|
+
*/
|
|
117
|
+
held(accountIdArg: string): boolean;
|
|
118
|
+
/** Says that an answer relayed on the key ended before its provider stated its usage, so nothing of it is counted. */
|
|
119
|
+
uncounted(accountIdArg: string, modelArg: string): void;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* What a payment problem's report adds for the account service (`IReq_AuthSwitchReportPaymentProblem`): the cause of an
|
|
123
|
+
* API key's spend cap or quota, nothing for a billing error, whose cause a missing one means -- so a Claude account's
|
|
124
|
+
* report is the one an accounts service of 40.3.0, which refuses a cause, takes.
|
|
125
|
+
*/
|
|
126
|
+
export declare const inferencePaymentReportOptions: (causeArg: TInferencePaymentCause) => {
|
|
127
|
+
cause?: Exclude<TInferencePaymentCause, 'billing'>;
|
|
128
|
+
};
|
|
79
129
|
/** A payment problem the account service could not be told of, as the proxy reports it: the account by its id's digest. */
|
|
80
130
|
export interface IInferencePaymentReportFailure {
|
|
81
131
|
/** The first 12 hex characters of the SHA-256 digest of the account's id. */
|
|
@@ -87,16 +137,41 @@ export interface IInferencePaymentReportFailure {
|
|
|
87
137
|
* Why an account takes no request although no limit says so. `usage_unread`: the account service holds no usage reading
|
|
88
138
|
* the proxy routes on. `catalog_failed`: the account's model list could not be read and none read before is held for its
|
|
89
139
|
* revision. `needs_login`: its sign-in needs renewing. `access_failed`: the account service answered no access for it.
|
|
90
|
-
* `model_missing`: its model list lacks the requested model. `payment_problem`:
|
|
91
|
-
* account
|
|
140
|
+
* `model_missing`: its model list lacks the requested model. `payment_problem`: the provider refused a request on the
|
|
141
|
+
* account for a payment problem (`TInferencePaymentCause`); it takes none until a usage read or a re-check clears it, or
|
|
142
|
+
* a spend cap ends. `spend_unread`: an API key with a monthly spend limit whose spend the proxy holds no reading of --
|
|
143
|
+
* the account service could not read its ledger (`spend_unavailable`) or did not answer -- so it may be at its limit.
|
|
144
|
+
* `spend_unrecorded`: an API key with a monthly spend limit whose spend the proxy relayed is recorded nowhere yet --
|
|
145
|
+
* the account service refused its report, which the proxy holds to send again, an answer is held in neither the
|
|
146
|
+
* proxy's store, whose write failed, nor the account service's ledger, or no login of the key could be named for an
|
|
147
|
+
* answer to report it on (`InferenceSpendOutbox.held`). `model_unpriced`: an API key with a monthly spend limit, and a
|
|
148
|
+
* request whose model, service tier, speed, region or server tool the proxy's price table cannot price (`failure` names
|
|
149
|
+
* it), so its cost could not be counted against the limit.
|
|
150
|
+
*/
|
|
151
|
+
export type TInferenceUnavailableReason = 'usage_unread' | 'catalog_failed' | 'needs_login' | 'access_failed' | 'model_missing' | 'payment_problem' | 'spend_unread' | 'spend_unrecorded' | 'model_unpriced';
|
|
152
|
+
/**
|
|
153
|
+
* Why a provider refused a request on an account for a payment problem, as the gateway reads the provider's answer.
|
|
154
|
+
* `billing`: Anthropic's billing error (HTTP 402 `billing_error`), on a Claude account's subscription or an Anthropic API
|
|
155
|
+
* key's organization. `spend_cap`: an Anthropic API key's organization reached its usage tier's monthly spend cap (HTTP
|
|
156
|
+
* 429 `rate_limit_error` with `error.details.error_code: "enforced_spend_limit_reached"`), which holds until 00:00 UTC on
|
|
157
|
+
* the first day of the next month. `quota`: OpenAI refused an API key for its quota (HTTP 429 `insufficient_quota`): no
|
|
158
|
+
* prepaid credit left, or an organization or project spend limit or the organization's usage limit reached.
|
|
92
159
|
*/
|
|
93
|
-
export type
|
|
160
|
+
export type TInferencePaymentCause = plugins.authswitchAuthority.TAuthSwitchPaymentProblemCause;
|
|
94
161
|
export interface IInferenceAccountUnavailable {
|
|
95
162
|
reason: TInferenceUnavailableReason;
|
|
96
|
-
/**
|
|
163
|
+
/**
|
|
164
|
+
* `usage_unread`: when the account service reads the account's usage next, or `null` when it does not say.
|
|
165
|
+
* `payment_problem` of a spend cap: when the cap ends and the account takes requests again.
|
|
166
|
+
*/
|
|
97
167
|
retryAt?: string | null;
|
|
98
|
-
/**
|
|
168
|
+
/**
|
|
169
|
+
* `catalog_failed`: the HTTP status the model list answered with (`HTTP 429`), or what failed instead.
|
|
170
|
+
* `model_unpriced`: what of the request the price table cannot price.
|
|
171
|
+
*/
|
|
99
172
|
failure?: string;
|
|
173
|
+
/** `payment_problem`: what the provider refused the account for. */
|
|
174
|
+
cause?: TInferencePaymentCause;
|
|
100
175
|
}
|
|
101
176
|
/** A change of why an account is refused, as the proxy reports it: the account by its id's digest, never its id. */
|
|
102
177
|
export interface IInferenceAccountChange {
|
|
@@ -115,6 +190,17 @@ export interface IInferenceAccountChange {
|
|
|
115
190
|
* 429 (`cooling`).
|
|
116
191
|
*/
|
|
117
192
|
export type TInferenceAccountLimit = 'exhausted' | 'reserved' | 'cooling';
|
|
193
|
+
/** An API key a request found held by its monthly spend limit: the account, and its month as the account service read it. */
|
|
194
|
+
export interface IInferenceSpendLimited {
|
|
195
|
+
accountId: string;
|
|
196
|
+
label: string;
|
|
197
|
+
spend: plugins.authswitchSpend.IAuthSwitchSpendReading;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* What a refusal says of the API keys it found held by their monthly spend limit: each key with its month, and when the
|
|
201
|
+
* first of them takes requests again. Empty without any.
|
|
202
|
+
*/
|
|
203
|
+
export declare const inferenceSpendLimitText: (keysArg: readonly IInferenceSpendLimited[]) => string;
|
|
118
204
|
export declare class InferenceRoutingError extends Error {
|
|
119
205
|
readonly status: number;
|
|
120
206
|
readonly code: string;
|
|
@@ -125,8 +211,13 @@ export declare class InferenceRoutingError extends Error {
|
|
|
125
211
|
readonly accountLimit?: TInferenceAccountLimit | undefined;
|
|
126
212
|
/** The account a refusal for a reason of its own (`reason`) names. */
|
|
127
213
|
readonly accountId?: string | undefined;
|
|
128
|
-
/**
|
|
129
|
-
|
|
214
|
+
/**
|
|
215
|
+
* For `no_eligible_accounts` of a pinned account: why that account takes no request though no limit says so, in
|
|
216
|
+
* full -- a payment problem's cause, say.
|
|
217
|
+
*/
|
|
218
|
+
readonly unavailable?: IInferenceAccountUnavailable | undefined;
|
|
219
|
+
/** For `accounts_exhausted`: the API keys found held by their monthly spend limit, which its message names. */
|
|
220
|
+
readonly spendLimited: readonly IInferenceSpendLimited[];
|
|
130
221
|
constructor(status: number, code: string, messageArg: string, retryAfterSeconds?: number | undefined,
|
|
131
222
|
/** For `accounts_exhausted`: the provider plans of the accounts found at their limits. */
|
|
132
223
|
plans?: readonly string[],
|
|
@@ -134,17 +225,39 @@ export declare class InferenceRoutingError extends Error {
|
|
|
134
225
|
accountLimit?: TInferenceAccountLimit | undefined,
|
|
135
226
|
/** The account a refusal for a reason of its own (`reason`) names. */
|
|
136
227
|
accountId?: string | undefined,
|
|
137
|
-
/**
|
|
138
|
-
|
|
228
|
+
/**
|
|
229
|
+
* For `no_eligible_accounts` of a pinned account: why that account takes no request though no limit says so, in
|
|
230
|
+
* full -- a payment problem's cause, say.
|
|
231
|
+
*/
|
|
232
|
+
unavailable?: IInferenceAccountUnavailable | undefined,
|
|
233
|
+
/** For `accounts_exhausted`: the API keys found held by their monthly spend limit, which its message names. */
|
|
234
|
+
spendLimited?: readonly IInferenceSpendLimited[]);
|
|
235
|
+
/** The reason of `unavailable`: a refusal names a reason of its own only with the refusal in full. */
|
|
236
|
+
get reason(): TInferenceUnavailableReason | undefined;
|
|
139
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* A ChatGPT account or an OpenAI API key chosen for one request: a ChatGPT sign-in through the ChatGPT backend, a key
|
|
240
|
+
* through OpenAI's API (`OPENAI_API_BASE_URL`), each through `connection`.
|
|
241
|
+
*/
|
|
140
242
|
export interface IInferenceRoute {
|
|
141
243
|
provider: 'openai';
|
|
244
|
+
/** What the chosen account authenticates with: a ChatGPT sign-in, or an OpenAI API key. */
|
|
245
|
+
credential: TInferenceCredential;
|
|
142
246
|
accountId: string;
|
|
143
247
|
plan: string;
|
|
144
248
|
/** The account's placement score when it was chosen (`IAuthSwitchPlacement.score`). */
|
|
145
249
|
score: number | null;
|
|
146
250
|
model: TInferenceModel;
|
|
147
251
|
connection: plugins.openAiProvider.IOpenAiModelConnection;
|
|
252
|
+
/** The session left its account on a later credential tier for one of a better tier (`returnToBetterTier`). */
|
|
253
|
+
returned: boolean;
|
|
254
|
+
/** The login the account was served on as the pool was read (`IInferenceAccount.loginId`): an answer's spend names it. */
|
|
255
|
+
loginId: string | null;
|
|
256
|
+
/**
|
|
257
|
+
* An OpenAI API key with a monthly spend limit: the request goes out as the price check read it, on the service tier it
|
|
258
|
+
* was checked for (`inferenceOpenAiCheckedBytes`).
|
|
259
|
+
*/
|
|
260
|
+
spendLimit: boolean;
|
|
148
261
|
release: () => void;
|
|
149
262
|
}
|
|
150
263
|
/**
|
|
@@ -160,6 +273,18 @@ export interface IInferenceClaudeRoute {
|
|
|
160
273
|
score: number | null;
|
|
161
274
|
model: TInferenceClaudeModel;
|
|
162
275
|
connection: plugins.anthropicProvider.IAnthropicModelConnection;
|
|
276
|
+
/**
|
|
277
|
+
* The session's account is an Anthropic API key, and a Claude account of a better credential tier took the request
|
|
278
|
+
* instead (`returnToBetterTier`): the session returns to it.
|
|
279
|
+
*/
|
|
280
|
+
returned: boolean;
|
|
281
|
+
/** The login the account was served on as the pool was read (`IInferenceAccount.loginId`): an answer's spend names it. */
|
|
282
|
+
loginId: string | null;
|
|
283
|
+
/**
|
|
284
|
+
* An Anthropic API key with a monthly spend limit: the request goes out as the price check read it, on the standard
|
|
285
|
+
* service tier only (`inferenceAnthropicCheckedBytes`), the one the price table prices.
|
|
286
|
+
*/
|
|
287
|
+
spendLimit: boolean;
|
|
163
288
|
release: () => void;
|
|
164
289
|
}
|
|
165
290
|
/** One account of the proxy as `agl proxy status` shows it, judged on the held reading without reading again. */
|
|
@@ -219,37 +344,99 @@ export interface IInferenceAccountStatus {
|
|
|
219
344
|
export type TInferenceNativeModel = Record<string, unknown> & {
|
|
220
345
|
slug: string;
|
|
221
346
|
};
|
|
347
|
+
/** How a request is placed on a Claude pool (`InferenceRouter.acquireClaude`). */
|
|
348
|
+
export interface IInferenceClaudeAcquireOptions {
|
|
349
|
+
/** The session's account: the request is judged on it alone, unless `returnToBetterTier` finds a better one. */
|
|
350
|
+
accountId?: string;
|
|
351
|
+
/** The accounts this request left already; it never goes back to them. */
|
|
352
|
+
exclude?: ReadonlySet<string>;
|
|
353
|
+
/**
|
|
354
|
+
* The accounts of `exclude` the request left for a reason of their own, and that reason: each counts as its own
|
|
355
|
+
* judgement counts the reason, never as at its limit. An account of `exclude` it does not name counts as at its limit.
|
|
356
|
+
*/
|
|
357
|
+
excludedBecause?: ReadonlyMap<string, IInferenceAccountUnavailable>;
|
|
358
|
+
/** A request that uses no quota (`count_tokens`): an account at its limit takes it as well. */
|
|
359
|
+
ignoreLimits?: boolean;
|
|
360
|
+
/**
|
|
361
|
+
* What of the request the proxy's price table cannot price (`inferenceAnthropicUnpricedRequest`): an API key with a
|
|
362
|
+
* monthly spend limit takes no such request (`model_unpriced`). A request that uses no quota ignores it.
|
|
363
|
+
*/
|
|
364
|
+
unpriced?: string;
|
|
365
|
+
/**
|
|
366
|
+
* The session may move: when its account is of a later credential tier -- an Anthropic API key of a pool that names
|
|
367
|
+
* no credential -- a Claude account that can take the request takes it instead, and the route is `returned`.
|
|
368
|
+
*/
|
|
369
|
+
returnToBetterTier?: boolean;
|
|
370
|
+
}
|
|
371
|
+
/** How a request is placed on a ChatGPT pool (`InferenceRouter.acquire`). */
|
|
372
|
+
export interface IInferenceAcquireOptions {
|
|
373
|
+
/** The session's account: the request is judged on it alone, unless `returnToBetterTier` finds a better one. */
|
|
374
|
+
accountId?: string;
|
|
375
|
+
/** The accounts this request left already; it never goes back to them. */
|
|
376
|
+
exclude?: ReadonlySet<string>;
|
|
377
|
+
/** The accounts of `exclude` the request left for a reason of their own, as for a Claude pool (`IInferenceClaudeAcquireOptions`). */
|
|
378
|
+
excludedBecause?: ReadonlyMap<string, IInferenceAccountUnavailable>;
|
|
379
|
+
/** The request's `reasoning.effort`, which a ChatGPT account's model must accept; a key's model is OpenAI's to judge. */
|
|
380
|
+
reasoningEffort?: string;
|
|
381
|
+
/** The request's `service_tier`, which a ChatGPT account's model must offer (`auto` and `default` always). */
|
|
382
|
+
serviceTier?: string;
|
|
383
|
+
/** The Codex release the client read its catalog as: the model it names is checked against the catalog it was offered. */
|
|
384
|
+
clientVersion?: string;
|
|
385
|
+
/** A Responses request, which an OpenAI API key may take; a translated Messages request never goes to a key. */
|
|
386
|
+
apiKeys?: boolean;
|
|
387
|
+
/**
|
|
388
|
+
* What of the request the proxy's price table cannot price (`inferenceOpenAiUnpricedRequest`): an OpenAI API key with a
|
|
389
|
+
* monthly spend limit takes no such request (`model_unpriced`).
|
|
390
|
+
*/
|
|
391
|
+
unpriced?: string;
|
|
392
|
+
/**
|
|
393
|
+
* The session may move: when its account is an OpenAI API key of a pool that names no credential, a ChatGPT account
|
|
394
|
+
* that can take the request takes it instead, and the route is `returned`. The gateway asks it only of a request that
|
|
395
|
+
* carries no account state, which never leaves its account.
|
|
396
|
+
*/
|
|
397
|
+
returnToBetterTier?: boolean;
|
|
398
|
+
}
|
|
222
399
|
/** Model-preserving account selection. Refresh grants and native sign-ins remain the authority's. */
|
|
223
400
|
export declare class InferenceRouter {
|
|
224
401
|
private readonly options;
|
|
225
402
|
/** ChatGPT catalogs by account and the Codex release they were read as. */
|
|
226
403
|
private readonly catalogs;
|
|
227
404
|
private readonly nativeCatalogs;
|
|
405
|
+
/** The model lists of the Claude accounts and the Anthropic API keys (`claudeCatalog`). */
|
|
228
406
|
private readonly claudeCatalogs;
|
|
407
|
+
/** The model lists of the OpenAI API keys (`keyCatalog`). */
|
|
408
|
+
private readonly keyCatalogs;
|
|
229
409
|
/** Why each Claude account was last reported refused, or routed on its last model list (`noteAccount`). */
|
|
230
410
|
private readonly noted;
|
|
231
411
|
private readonly active;
|
|
232
412
|
private readonly cooldowns;
|
|
233
413
|
/**
|
|
234
|
-
* The
|
|
235
|
-
* holds the problem
|
|
414
|
+
* The accounts a payment problem took out of rotation (`reportPaymentProblem`): a Claude account until the account
|
|
415
|
+
* service holds the problem -- one it could not be told of stays here for the proxy's lifetime -- and an API key until
|
|
416
|
+
* its spend cap ends, or for the proxy's lifetime.
|
|
236
417
|
*/
|
|
237
418
|
private readonly paymentMarks;
|
|
238
419
|
/** The accounts whose payment problem the account service could not be told of, each reported once. */
|
|
239
420
|
private readonly paymentReportsFailed;
|
|
240
421
|
/**
|
|
241
|
-
* The
|
|
242
|
-
* so
|
|
422
|
+
* The API keys, Anthropic's and OpenAI's, among the accounts the last pool read listed: the account service reads no
|
|
423
|
+
* subscription usage for them, so no usage a request on one shows -- headers, tokens, a 429 -- is handed to it.
|
|
243
424
|
*/
|
|
244
425
|
private apiKeyAccounts;
|
|
245
426
|
private readonly now;
|
|
246
427
|
constructor(options: IInferenceRouterOptions);
|
|
247
428
|
private accounts;
|
|
248
429
|
/**
|
|
249
|
-
* The
|
|
250
|
-
*
|
|
251
|
-
|
|
252
|
-
|
|
430
|
+
* The credential tiers of the policy's pool, best first (`inferenceCredentialTiers`). A plan restriction leaves the
|
|
431
|
+
* API keys out, as a key has no plan, so a lease with `plans` never reaches a key.
|
|
432
|
+
*/
|
|
433
|
+
private tiers;
|
|
434
|
+
/**
|
|
435
|
+
* The policy's accounts of its provider and credential tiers (`tiers`), and every eligible account's id of that pool:
|
|
436
|
+
* an account absent from both left the pool. An account whose lapse date passed is in neither -- it is never routed to
|
|
437
|
+
* again -- and is named in `lapsed`. A pool that names its credential serves that kind alone: Flex's API-key pool
|
|
438
|
+
* never takes a Claude account. One that names none spans both, and a session placed on a key returns to a Claude
|
|
439
|
+
* account once one can take its request.
|
|
253
440
|
*/
|
|
254
441
|
private pool;
|
|
255
442
|
/**
|
|
@@ -262,93 +449,145 @@ export declare class InferenceRouter {
|
|
|
262
449
|
private sessionPool;
|
|
263
450
|
/** An account's ChatGPT catalog as the Codex release `clientVersionArg` is offered it, or the package's default. */
|
|
264
451
|
private catalog;
|
|
452
|
+
/** The models a Claude account or an Anthropic API key may use (`heldModels`). */
|
|
453
|
+
private claudeCatalog;
|
|
454
|
+
/** The models an OpenAI API key may use, as its `GET /v1/models` lists them (`heldModels`, `openAiKeyModel`). */
|
|
455
|
+
private keyCatalog;
|
|
265
456
|
/**
|
|
266
|
-
* The models
|
|
457
|
+
* The models an account may use, from its list in `listsArg`: the list read within the last minute, else read now.
|
|
267
458
|
* A model-list read that fails keeps the list read before for the account's revision, which the account routes on
|
|
268
459
|
* meanwhile; with none, the account is unavailable for the failure's reason. A failure of the account's access or
|
|
269
460
|
* sign-in makes it unavailable whether a list is held or not. Either way the failure is noted and its account is not
|
|
270
|
-
* read again, however many requests ask, for a minute -- or 5 s after a failed access (`
|
|
461
|
+
* read again, however many requests ask, for a minute -- or 5 s after a failed access (`holdListFailure`).
|
|
271
462
|
*/
|
|
272
|
-
private
|
|
463
|
+
private heldModels;
|
|
273
464
|
/**
|
|
274
|
-
* Records why
|
|
465
|
+
* Records why an account's model list or access failed, keeping the list held for its revision, and notes it:
|
|
275
466
|
* neither is read again for a minute after a failed model-list read or sign-in, or for 5 s after a failed access
|
|
276
467
|
* (`access_failed`). The access is then tried again by reading the list again, even one read within the minute: a
|
|
277
468
|
* single list read on recovery. Answers the held list when the account routes on it meanwhile -- only after a failed
|
|
278
|
-
* model-list read (`
|
|
469
|
+
* model-list read (`heldListRefusal`).
|
|
279
470
|
*/
|
|
280
|
-
private
|
|
471
|
+
private holdListFailure;
|
|
281
472
|
/**
|
|
282
|
-
* Reads the models
|
|
283
|
-
* renewed, while a key is ended, so the account service refuses the second read. Every failure but an abort
|
|
284
|
-
* `
|
|
473
|
+
* Reads the models an account may use through `listArg`. A rejected access (`accessRejected`) is reported once: a
|
|
474
|
+
* sign-in is renewed, while a key is ended, so the account service refuses the second read. Every failure but an abort
|
|
475
|
+
* is a `ModelListError` naming its reason.
|
|
285
476
|
*/
|
|
286
|
-
private
|
|
477
|
+
private readModelList;
|
|
287
478
|
/**
|
|
288
479
|
* Notes why a Claude account is refused, or routed on its last model list, now (`null`: neither), and reports a change
|
|
289
480
|
* of it -- never the same reason again, however many requests meet it.
|
|
290
481
|
*/
|
|
291
482
|
private noteAccount;
|
|
292
|
-
/** The model list
|
|
293
|
-
private
|
|
483
|
+
/** The model list an account's revision was last read with, without reading it: `undefined` when none is held. */
|
|
484
|
+
private heldList;
|
|
294
485
|
/**
|
|
295
|
-
* Why
|
|
296
|
-
*
|
|
486
|
+
* Why an account's model list or access keeps it from routing, as a request would find it now, before its next read is
|
|
487
|
+
* due: a failed access or sign-in, or a failed model-list read with no list held for its revision. Only the accounts
|
|
488
|
+
* whose model list the router reads have one: Claude accounts and API keys.
|
|
297
489
|
*/
|
|
298
|
-
private
|
|
490
|
+
private listRefusal;
|
|
299
491
|
/**
|
|
300
|
-
* The
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
492
|
+
* The Claude pool's models, from its best credential tier with a readable account (`inferenceCredentialTiers`): the
|
|
493
|
+
* Claude accounts' while one of them can read its model list, else the Anthropic API keys'. Within the tier, the
|
|
494
|
+
* models every readable account offers: a session may move to any of them, so a model one account lacks is not
|
|
495
|
+
* offered. Limits are the smallest any of them states; efforts are those all of them accept, and adaptive thinking is
|
|
496
|
+
* offered when all of them accept it. What one account does not state, the pool does not state.
|
|
304
497
|
*/
|
|
305
498
|
claudeModels(policyArg: IInferenceRoutingPolicy, signalArg: AbortSignal): Promise<TInferenceClaudeModel[]>;
|
|
499
|
+
/** The models every readable account of one credential tier of a Claude pool offers; `undefined` when none is readable. */
|
|
500
|
+
private tierClaudeModels;
|
|
306
501
|
/**
|
|
307
|
-
*
|
|
308
|
-
*
|
|
502
|
+
* The ChatGPT pool's models, from its best credential tier with a readable account (`inferenceCredentialTiers`): the
|
|
503
|
+
* ChatGPT sign-ins' current entitlements while one of them can read its catalog, else the OpenAI API keys' models
|
|
504
|
+
* (`keyTierModels`). A pool whose every ChatGPT account read needs a fresh sign-in -- ChatGPT rejected its access even
|
|
505
|
+
* when renewed, or the account service could not renew it -- and no key to fall back to answers
|
|
309
506
|
* `account_needs_login`, so its caller asks for a sign-in rather than for the proxy.
|
|
310
507
|
*/
|
|
311
508
|
models(policyArg: IInferenceRoutingPolicy, signalArg: AbortSignal): Promise<TInferenceModel[]>;
|
|
312
509
|
/**
|
|
313
|
-
*
|
|
314
|
-
*
|
|
510
|
+
* Current model entitlements, merged conservatively across the pool's ChatGPT sign-ins, and whether every account read
|
|
511
|
+
* needed a fresh sign-in.
|
|
512
|
+
*/
|
|
513
|
+
private signInModels;
|
|
514
|
+
/**
|
|
515
|
+
* The models every readable OpenAI API key of the pool lists and flexharness describes (`openAiKeyModel`), newest first
|
|
516
|
+
* as `OPENAI_API_MODELS` orders them, the first the default: a session may move to any of the keys, so a model one key
|
|
517
|
+
* lacks is not offered. `undefined` when no key is readable.
|
|
518
|
+
*/
|
|
519
|
+
private keyTierModels;
|
|
520
|
+
/**
|
|
521
|
+
* The pool's Codex model catalog in the Codex backend's own entry shape, read for the client's version through its
|
|
522
|
+
* ChatGPT sign-ins alone: an OpenAI API key never reaches the ChatGPT catalog connection, so a pool of keys alone has
|
|
523
|
+
* no Codex catalog here (`no_eligible_accounts`; Codex then uses its bundled one). An entry shared by several
|
|
524
|
+
* accounts keeps only what every one of them offers.
|
|
315
525
|
*/
|
|
316
526
|
nativeModels(policyArg: IInferenceRoutingPolicy, clientVersionArg: string, signalArg: AbortSignal): Promise<TInferenceNativeModel[]>;
|
|
317
527
|
private nativeCatalog;
|
|
318
528
|
/**
|
|
319
|
-
* A ChatGPT account
|
|
320
|
-
*
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
*
|
|
334
|
-
*
|
|
529
|
+
* A ChatGPT account or an OpenAI API key for one request, chosen as `acquireClaude` chooses: the pinned session account
|
|
530
|
+
* if it is still eligible, else the best credential tier's least busy account with the most headroom
|
|
531
|
+
* (`inferenceCredentialTiers`). A ChatGPT account is judged on its usage reading and the Codex catalog of the release
|
|
532
|
+
* the client read it as (`clientVersion`). An OpenAI API key takes only a Responses request (`apiKeys`), never a
|
|
533
|
+
* translated Messages request, and is judged as an Anthropic API key is (`judgeListed`): a payment problem -- OpenAI's
|
|
534
|
+
* quota refusal -- or its month's spend at its limit keeps it out, a key with a limit takes no request it cannot price
|
|
535
|
+
* (`unpriced`, `model_unpriced`), and its model list (`GET /v1/models`, held a minute) must list the model. The accounts
|
|
536
|
+
* of `exclude` count as `excludedBecause` says, as for a Claude pool. `returnToBetterTier`: a session pinned to a key
|
|
537
|
+
* goes back to a ChatGPT account as soon as one can take its request, and the route says so (`returned`).
|
|
538
|
+
*/
|
|
539
|
+
acquire(modelIdArg: string, policyArg: IInferenceRoutingPolicy, signalArg: AbortSignal, optionsArg?: IInferenceAcquireOptions): Promise<IInferenceRoute>;
|
|
540
|
+
/** `acquire` among `accountsArg`, the pool's accounts or those of its better tiers. */
|
|
541
|
+
private routeOpenAi;
|
|
542
|
+
/**
|
|
543
|
+
* Counts an account the request left already (`exclude`) as its own judgement counts the reason the request left it
|
|
544
|
+
* for (`excludedBecause`): a payment problem joins the 402 list, a key whose spend could not be read or recorded is
|
|
545
|
+
* named in the 503, one that could not price the request joins the 400 list, one without the model leads to the 404,
|
|
546
|
+
* and every other reason to the 503 for want of an account. An account left for no reason of its own counts as at its
|
|
547
|
+
* limit (429). The switch is exhaustive: a new reason must be placed here.
|
|
548
|
+
*/
|
|
549
|
+
private countLeft;
|
|
550
|
+
/**
|
|
551
|
+
* Judges an account whose model list the router reads -- a Claude account, an Anthropic or an OpenAI API key -- for one
|
|
552
|
+
* request, as placement takes it, recording on `stateArg` what keeps it out. A payment problem refuses it before anything
|
|
553
|
+
* else; without limits to route on (`limitsArg`) it is unavailable (`usage_unread`, a key's `spend_unread`); a key with
|
|
554
|
+
* a spend limit whose spend is recorded nowhere yet is refused (`spend_unrecorded`). Limits and cool-down are judged
|
|
555
|
+
* before any model list is read: an account that cannot take the request now is never read for it, its held list says
|
|
556
|
+
* whether it would serve the model, and without one it counts as at its limit, so a session on it moves rather than
|
|
557
|
+
* waiting for a list. A key's spend reading says nothing of the provider's rate limits, so only its own end ends a key's
|
|
558
|
+
* cool-down. A key with a spend limit then takes no request whose cost the price table cannot count (`unpriced`,
|
|
559
|
+
* Decision Q4), and the model list (`read`) must list the model. Answers the candidate's model and limits, or the refusal
|
|
560
|
+
* of an account that takes no request for a reason of its own -- a pinned refusal names it -- or `undefined`.
|
|
561
|
+
*/
|
|
562
|
+
private judgeListed;
|
|
563
|
+
/**
|
|
564
|
+
* A Claude account or an Anthropic API key for one of Claude Code's requests, or an Anthropic API key for one of
|
|
565
|
+
* Flex's, chosen as `acquire` chooses: the pinned session account if it is still eligible, else the least busy account
|
|
566
|
+
* with the most headroom whose current reading shows it available -- every counted window under its threshold, no
|
|
567
|
+
* provider retry ahead -- with no cooldown after a provider 429, and which lists the model. A key is judged on its
|
|
568
|
+
* month's spend (`keyLimits`): at its spend limit it takes no request until the month ends, as an account at its limit,
|
|
569
|
+
* and a session on it moves; with a limit and no readable spend it is refused (`spend_unread`). A pool that names no
|
|
570
|
+
* credential places on its Claude accounts first and on its keys only when no Claude account can take the request, for
|
|
571
|
+
* whatever reason (`inferenceCredentialTiers`).
|
|
335
572
|
* `ignoreLimits` serves a request that uses no quota (`count_tokens`) on an account at its limit as well. A pinned
|
|
336
573
|
* account that takes no request for a reason of its own -- no usage reading, no model list, no access, or no such
|
|
337
574
|
* model -- is refused naming the account and the reason (`InferenceRoutingError.reason`). An unpinned request whose
|
|
338
|
-
* chosen account's access fails goes to the next candidate.
|
|
575
|
+
* chosen account's access fails goes to the next candidate. `returnToBetterTier`: a session pinned to a key goes back
|
|
576
|
+
* to a Claude account as soon as one can take its request, and the route says so (`returned`).
|
|
339
577
|
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
578
|
+
* An account held with a payment problem -- Anthropic answered a request on it with a billing error (HTTP 402), or on
|
|
579
|
+
* a key with its organization's spend cap (HTTP 429 `enforced_spend_limit_reached`), as its usage reading says or this
|
|
580
|
+
* proxy saw (`reportPaymentProblem`) -- takes no request, `count_tokens` included, and is refused for the reason
|
|
581
|
+
* `payment_problem`. So is an account of `exclude` that `excludedBecause` names with a payment problem: the request
|
|
582
|
+
* left it for one. Neither counts as at its limit: when such accounts are all that is left the refusal is a 402
|
|
583
|
+
* `payment_problem` naming them, and while another account is merely at its limit the 429 stands. Any other account
|
|
584
|
+
* of `exclude` that `excludedBecause` names counts as its reason counts on the account's own judgement: a key whose
|
|
585
|
+
* spend could not be read is named in the 503, an account without the model leads to the 404, and every other reason
|
|
586
|
+
* to the 503 for want of an account -- never to the 429 of accounts at their limits.
|
|
587
|
+
*/
|
|
588
|
+
acquireClaude(modelIdArg: string, policyArg: IInferenceRoutingPolicy, signalArg: AbortSignal, optionsArg?: IInferenceClaudeAcquireOptions): Promise<IInferenceClaudeRoute>;
|
|
589
|
+
/** `acquireClaude` among `accountsArg`, the pool's accounts or those of its better tiers. */
|
|
590
|
+
private routeClaude;
|
|
352
591
|
/**
|
|
353
592
|
* Tells the account service that Anthropic rejected the key of `generationArg`: it marks the account for a new key,
|
|
354
593
|
* so the pool leaves it out from then on, and refuses the access the report asks for -- the answer expected here. A
|
|
@@ -357,17 +596,18 @@ export declare class InferenceRouter {
|
|
|
357
596
|
*/
|
|
358
597
|
private rejectApiKey;
|
|
359
598
|
/**
|
|
360
|
-
* The candidate a request goes to
|
|
361
|
-
* none. A pinned request has its session's
|
|
362
|
-
* An account at its reserve is refused like one at its limit, and the refusal names the reserve. A pinned account
|
|
599
|
+
* The candidate a request goes to -- of the best credential tier, then by the placement order
|
|
600
|
+
* (`authSwitchPlacementOrder`) -- or the refusal that says why there is none. A pinned request has its session's
|
|
601
|
+
* account as its one candidate, so the order only ever places new sessions. An account at its reserve is refused like one at its limit, and the refusal names the reserve. A pinned account
|
|
363
602
|
* that takes no request for a reason of its own (`refusal`) is refused with that account and reason.
|
|
364
603
|
*/
|
|
365
604
|
private select;
|
|
366
605
|
/**
|
|
367
606
|
* The accounts as `agl proxy status` shows them: each judged as placement would judge it on the reading `heldArg`
|
|
368
|
-
* answers for it, which the caller read beforehand -- an
|
|
607
|
+
* answers for it, which the caller read beforehand -- an API key on its month's spend (`keyLimits`), in dollars -- with
|
|
369
608
|
* its cooldown, the requests it serves now, its lifecycle and where a new session of an unrestricted client of its
|
|
370
|
-
*
|
|
609
|
+
* provider would go (`placementRank`): a client that names no credential, so a provider's subscriptions rank before its
|
|
610
|
+
* keys (`inferenceCredentialTiers`).
|
|
371
611
|
*/
|
|
372
612
|
accountStatus(accountsArg: readonly IInferenceAccount[], heldArg: (accountIdArg: string) => plugins.authswitchAuthority.IAuthSwitchUsageSnapshot | undefined): IInferenceAccountStatus[];
|
|
373
613
|
/** Counts one request on an account until its release, which may be called more than once. */
|
|
@@ -379,15 +619,22 @@ export declare class InferenceRouter {
|
|
|
379
619
|
*/
|
|
380
620
|
observe(accountIdArg: string, providerArg: TInferenceProvider, headersArg: Headers, statusArg: number): void;
|
|
381
621
|
/**
|
|
382
|
-
*
|
|
383
|
-
*
|
|
384
|
-
* account's usage carries it, and that decides from then on
|
|
385
|
-
*
|
|
386
|
-
*
|
|
622
|
+
* A provider refused a request on the account for a payment problem (`TInferencePaymentCause`): the account is out of
|
|
623
|
+
* rotation at once, and the refusal it now carries is answered. The problem is reported to the account service
|
|
624
|
+
* (`reportPaymentProblem`); once it holds the problem the account's usage carries it, and that decides from then on --
|
|
625
|
+
* until a re-check clears it, or a spend cap's month ends -- so the router's own mark is dropped. When the service
|
|
626
|
+
* cannot be told -- it is not running, or an older release that does not know the report or the account's kind --
|
|
627
|
+
* the mark holds, a spend cap until 00:00 UTC on the first day of the next month (`authSwitchSpendPeriod`), anything
|
|
628
|
+
* else for as long as the proxy runs, and the failure is reported once.
|
|
629
|
+
*/
|
|
630
|
+
reportPaymentProblem(accountIdArg: string, causeArg: TInferencePaymentCause): IInferenceAccountUnavailable;
|
|
631
|
+
/**
|
|
632
|
+
* The payment problem an account is held with, as a refusal: by this proxy's own mark while it holds -- a spend cap's
|
|
633
|
+
* ends at its time -- or by the account's usage reading, which carries it once the account service holds it, with its
|
|
634
|
+
* cause (absent: `billing`) and, for a spend cap, when it ends; one whose spend cap ended holds nothing
|
|
635
|
+
* (`authSwitchPaymentProblemHeld`, the rule the account service holds it by).
|
|
387
636
|
*/
|
|
388
|
-
|
|
389
|
-
/** Whether a Claude account is held with a payment problem: by its usage reading, or by this proxy's own mark. */
|
|
390
|
-
private paymentRefused;
|
|
637
|
+
private paymentProblem;
|
|
391
638
|
/** A provider answer's `Retry-After`, in seconds from now, in either of its forms. */
|
|
392
639
|
retryAfterSeconds(headersArg: Headers): number | undefined;
|
|
393
640
|
/**
|
|
@@ -395,11 +642,22 @@ export declare class InferenceRouter {
|
|
|
395
642
|
* windows. An API key has no windows to estimate.
|
|
396
643
|
*/
|
|
397
644
|
countTokens(accountIdArg: string, usageArg: plugins.authswitchUsageTokens.IAuthSwitchTokenUsage): void;
|
|
645
|
+
/**
|
|
646
|
+
* Takes the spend of an answer an API key served on the login `loginIdArg` (`inferenceAnthropicSpend`): it counts
|
|
647
|
+
* against the key's limit from now on and is reported to the account service (`spend`).
|
|
648
|
+
*/
|
|
649
|
+
recordSpend(accountIdArg: string, loginIdArg: string | null, recordArg: IInferenceSpendRecord): void;
|
|
650
|
+
/**
|
|
651
|
+
* Says that an answer an API key served ended before its provider stated its usage, so nothing of it counts against
|
|
652
|
+
* the key's limit (`IInferenceSpendLedger.uncounted`).
|
|
653
|
+
*/
|
|
654
|
+
uncountedSpend(accountIdArg: string, modelArg: string): void;
|
|
398
655
|
/**
|
|
399
656
|
* A provider 429 on the account. Only a definitive pre-stream refusal permits another account to be tried. The
|
|
400
657
|
* account cools down for the provider's `Retry-After`, at most a day; without one, or with one already due, for 60
|
|
401
658
|
* seconds or until the account service holds a usage read made after the 429 (see `cooldownUntil`), which the 429
|
|
402
|
-
* asks it to make at once. An API key, whose
|
|
659
|
+
* asks it to make at once. An API key, whose spend reading says nothing of the provider's rate limits, cools down
|
|
660
|
+
* the 60 seconds.
|
|
403
661
|
*/
|
|
404
662
|
reportQuota(accountIdArg: string, retryAfterSecondsArg?: number): void;
|
|
405
663
|
}
|