@eddyskywalker/dsh-chatgpt-subscription 0.8.4 → 0.9.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 +45 -0
- package/README.md +93 -38
- package/lib/client.js +2126 -1693
- package/lib/client.js.map +1 -1
- package/lib/index.js +7597 -2781
- package/lib/types/client/claude/ClaudeComposerQuota.d.ts +33 -0
- package/lib/types/client/claude/ClaudeComposerQuota.d.ts.map +1 -0
- package/lib/types/client/{zhipu/ZhipuSection.d.ts → claude/ClaudeSection.d.ts} +2 -2
- package/lib/types/client/claude/ClaudeSection.d.ts.map +1 -0
- package/lib/types/client/claude/locales.d.ts +444 -0
- package/lib/types/client/claude/locales.d.ts.map +1 -0
- package/lib/types/client/claude/styles.d.ts +15 -0
- package/lib/types/client/claude/styles.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/host/claude/__probe-assert.d.ts +2 -0
- package/lib/types/host/claude/__probe-assert.d.ts.map +1 -0
- package/lib/types/host/claude/account-pool.d.ts +580 -0
- package/lib/types/host/claude/account-pool.d.ts.map +1 -0
- package/lib/types/host/claude/adapter.d.ts +267 -0
- package/lib/types/host/claude/adapter.d.ts.map +1 -0
- package/lib/types/host/claude/adopt.d.ts +292 -0
- package/lib/types/host/claude/adopt.d.ts.map +1 -0
- package/lib/types/host/claude/client.d.ts +513 -0
- package/lib/types/host/claude/client.d.ts.map +1 -0
- package/lib/types/host/claude/mapper.d.ts +510 -0
- package/lib/types/host/claude/mapper.d.ts.map +1 -0
- package/lib/types/host/claude/model-catalog.d.ts +365 -0
- package/lib/types/host/claude/model-catalog.d.ts.map +1 -0
- package/lib/types/host/claude/oauth.d.ts +393 -0
- package/lib/types/host/claude/oauth.d.ts.map +1 -0
- package/lib/types/host/claude/routes.d.ts +128 -0
- package/lib/types/host/claude/routes.d.ts.map +1 -0
- package/lib/types/host/claude/token-store.d.ts +312 -0
- package/lib/types/host/claude/token-store.d.ts.map +1 -0
- package/lib/types/host/claude/types.d.ts +237 -0
- package/lib/types/host/claude/types.d.ts.map +1 -0
- package/lib/types/index.d.ts +10 -7
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/shared/__probe-claude-import.d.ts +2 -0
- package/lib/types/shared/__probe-claude-import.d.ts.map +1 -0
- package/lib/types/shared/claude-contracts.d.ts +337 -0
- package/lib/types/shared/claude-contracts.d.ts.map +1 -0
- package/package.json +1 -1
- package/lib/types/client/zhipu/ZhipuComposerQuota.d.ts +0 -26
- package/lib/types/client/zhipu/ZhipuComposerQuota.d.ts.map +0 -1
- package/lib/types/client/zhipu/ZhipuSection.d.ts.map +0 -1
- package/lib/types/client/zhipu/locales.d.ts +0 -275
- package/lib/types/client/zhipu/locales.d.ts.map +0 -1
- package/lib/types/client/zhipu/styles.d.ts +0 -12
- package/lib/types/client/zhipu/styles.d.ts.map +0 -1
- package/lib/types/host/zhipu/account-pool.d.ts +0 -43
- package/lib/types/host/zhipu/account-pool.d.ts.map +0 -1
- package/lib/types/host/zhipu/adapter.d.ts +0 -93
- package/lib/types/host/zhipu/adapter.d.ts.map +0 -1
- package/lib/types/host/zhipu/client.d.ts +0 -153
- package/lib/types/host/zhipu/client.d.ts.map +0 -1
- package/lib/types/host/zhipu/mapper.d.ts +0 -111
- package/lib/types/host/zhipu/mapper.d.ts.map +0 -1
- package/lib/types/host/zhipu/model-catalog.d.ts +0 -73
- package/lib/types/host/zhipu/model-catalog.d.ts.map +0 -1
- package/lib/types/host/zhipu/routes.d.ts +0 -33
- package/lib/types/host/zhipu/routes.d.ts.map +0 -1
- package/lib/types/host/zhipu/token-store.d.ts +0 -112
- package/lib/types/host/zhipu/token-store.d.ts.map +0 -1
- package/lib/types/host/zhipu/types.d.ts +0 -125
- package/lib/types/host/zhipu/types.d.ts.map +0 -1
- package/lib/types/shared/zhipu-contracts.d.ts +0 -164
- package/lib/types/shared/zhipu-contracts.d.ts.map +0 -1
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Claude subscription line's account pool.
|
|
3
|
+
*
|
|
4
|
+
* ---------------------------------------------------------------------------
|
|
5
|
+
* TWO KINDS OF ACCOUNT, AND ONLY ONE OF THEM MAY BE REFRESHED
|
|
6
|
+
* ---------------------------------------------------------------------------
|
|
7
|
+
*
|
|
8
|
+
* A row in this pool is one of:
|
|
9
|
+
*
|
|
10
|
+
* - **managed** — signed in through this plugin. Its credential lives in the
|
|
11
|
+
* pool's encrypted storage AND in the pre-pool credential document beside it,
|
|
12
|
+
* it is refreshable, and deleting it is this plugin's business.
|
|
13
|
+
* - **adopted** — a SNAPSHOT read out of a local Claude Code sign-in by
|
|
14
|
+
* 'adopt.ts' (marker 'adopted: true', source 'claude-code'). It is used only
|
|
15
|
+
* while its own access token is still valid.
|
|
16
|
+
*
|
|
17
|
+
* An adopted snapshot is NEVER refreshed, and the reason is not an optimisation:
|
|
18
|
+
* Claude Code's refresh token ROTATES. Every refresh consumes the stored token
|
|
19
|
+
* and issues a new one, so two processes refreshing the same grant invalidate
|
|
20
|
+
* each other — whoever loses the race holds a token the server has already
|
|
21
|
+
* retired, and the user ends up signed OUT of Claude Code by this plugin's good
|
|
22
|
+
* intentions. An in-process single-flight cannot fix that, because the race is
|
|
23
|
+
* across PROCESSES: this plugin and Claude Code are separate programs, and the
|
|
24
|
+
* only shared state between them is a file that 'adopt.ts' must never write.
|
|
25
|
+
* Once such a snapshot is expired the pool takes it out of rotation and
|
|
26
|
+
* surfaces ADOPTED_CREDENTIAL_EXPIRED_HINT — sign in again in CLAUDE CODE and
|
|
27
|
+
* re-import, not here.
|
|
28
|
+
*
|
|
29
|
+
* The rule is enforced twice on purpose:
|
|
30
|
+
*
|
|
31
|
+
* 1. {@link claudeNeedsRefresh} returns false for an adopted credential no
|
|
32
|
+
* matter what its expiry says, so neither the routing path nor the auxiliary
|
|
33
|
+
* credential path ever reaches for a refresh.
|
|
34
|
+
* 2. the refresh hook itself refuses one ({@link ClaudeAdoptedCredentialError}),
|
|
35
|
+
* so a future caller that forgets rule 1 fails loudly instead of silently
|
|
36
|
+
* spending a grant that is not ours to spend.
|
|
37
|
+
*
|
|
38
|
+
* ---------------------------------------------------------------------------
|
|
39
|
+
* ONE ACCOUNT, ONE KEY
|
|
40
|
+
* ---------------------------------------------------------------------------
|
|
41
|
+
*
|
|
42
|
+
* 'token-store.ts' keys a stored account by an immutable internalId
|
|
43
|
+
* ('cl_' + 20 hex) and keeps identity aliases ('uuid:..', 'email:..',
|
|
44
|
+
* 'seed:<sha256(refreshToken)>') as an APPEND-ONLY set hanging off it. This pool
|
|
45
|
+
* adopts that same id rather than minting its own, and it resolves every
|
|
46
|
+
* identity question THROUGH it:
|
|
47
|
+
*
|
|
48
|
+
* - {@link ClaudeAccountPool.recordIdFor} turns a credential's strongest alias
|
|
49
|
+
* into the owning record's internalId, never into an alias string and never
|
|
50
|
+
* into a token digest. Both the dedupeKey and the accountId hook return that
|
|
51
|
+
* id, so the pool and the credential document cannot drift into two key
|
|
52
|
+
* spaces — which is how ghost accounts appear: one account, two rows, one of
|
|
53
|
+
* them stale forever.
|
|
54
|
+
* - 'seed:' aliases are LOOKUP keys only. A seed is a digest of a rotating
|
|
55
|
+
* token, so it is never returned, never stored as an account id, and never
|
|
56
|
+
* compared for equality between two credentials.
|
|
57
|
+
*
|
|
58
|
+
* The single accepted limitation is inherited from the store and restated here
|
|
59
|
+
* so nobody has to rediscover it: a credential that states NEITHER a uuid NOR an
|
|
60
|
+
* address has only its token seed as identity, so a re-login produces a
|
|
61
|
+
* different seed and a second record. {@link ClaudeAccountPool.mergeAccounts} is
|
|
62
|
+
* the remedy, and it is a deliberate user action rather than a guess.
|
|
63
|
+
*
|
|
64
|
+
* ---------------------------------------------------------------------------
|
|
65
|
+
* THE DOCUMENT SEAM (why an adapter class exists here)
|
|
66
|
+
* ---------------------------------------------------------------------------
|
|
67
|
+
*
|
|
68
|
+
* 'oauth.ts' signs in and refreshes against a minimal two-method store (read /
|
|
69
|
+
* write of ONE credential), because that module deliberately knows nothing about
|
|
70
|
+
* how accounts are laid out on disk. This line's store is
|
|
71
|
+
* {@link FileCredentialStore} — a MULTI-account document. The bridge is
|
|
72
|
+
* {@link ClaudeCredentialStoreAdapter}: it addresses exactly one record by
|
|
73
|
+
* internalId on read and writes back into that record's own entry (through
|
|
74
|
+
* saveAccount(credentials, { internalId }), which MERGES identity aliases
|
|
75
|
+
* instead of replacing them). Every caller that needs the two-method surface —
|
|
76
|
+
* the sign-in flow, and a later route that acts on one account — gets it from
|
|
77
|
+
* {@link ClaudeAccountPool.credentialStoreFor}.
|
|
78
|
+
*
|
|
79
|
+
* The pool's own refresh deliberately calls 'oauth.ts''s refreshAccessToken
|
|
80
|
+
* rather than its higher-level ensureAccessToken. That is not a shortcut: the
|
|
81
|
+
* single-flight in ensureAccessToken is ONE MODULE-LEVEL PROMISE shared by every
|
|
82
|
+
* caller in the process, so with a pool it would hand the second account the
|
|
83
|
+
* first account's freshly rotated credential — and, through the adapter above,
|
|
84
|
+
* write it into the second account's record. The pool therefore keeps its OWN
|
|
85
|
+
* single-flight, per account (see the inFlight map), which preserves the property
|
|
86
|
+
* the frozen module wanted (one rotation per expiry, no two callers spending the
|
|
87
|
+
* same rotating token) without the cross-account contamination.
|
|
88
|
+
*
|
|
89
|
+
* ---------------------------------------------------------------------------
|
|
90
|
+
* MANAGED WINS A CONFLICT
|
|
91
|
+
* ---------------------------------------------------------------------------
|
|
92
|
+
*
|
|
93
|
+
* The same Claude account can reach the pool twice: as a plugin sign-in and as
|
|
94
|
+
* an adopted snapshot. The two rows merge into one, and the MANAGED one wins the
|
|
95
|
+
* refresh right — it is the only one that is allowed to refresh at all. When
|
|
96
|
+
* they merge the adopted marker must NOT survive, because a surviving
|
|
97
|
+
* 'adopted: true' would silently freeze the merged record out of refreshing
|
|
98
|
+
* forever. That is why this class writes the marker (including its false case)
|
|
99
|
+
* on EVERY account it creates, rather than only on the adopted ones: the core
|
|
100
|
+
* merges a re-authorization as { ...existing, ...created }, so an omitted key
|
|
101
|
+
* would leave the stored marker in place.
|
|
102
|
+
*/
|
|
103
|
+
import { AccountPoolCore, type PoolAccountShape, type PoolData } from '../common/account-pool.ts';
|
|
104
|
+
import type { CredentialStore } from '../token-store.ts';
|
|
105
|
+
import type { AccountAuthStatus, PoolAccountSummaryDto } from '../../shared/account-pool-contracts.ts';
|
|
106
|
+
import { FileCredentialStore, type ClaudeCredentials } from './token-store.ts';
|
|
107
|
+
import { ClaudeUnauthorizedError, type ClaudeTokenStore } from './oauth.ts';
|
|
108
|
+
import { CLAUDE_CODE_CREDENTIAL_SOURCE } from './adopt.ts';
|
|
109
|
+
import type { ClaudeFailure } from './client.ts';
|
|
110
|
+
/**
|
|
111
|
+
* How early this pool refreshes, mirroring 'oauth.ts''s own REFRESH_MARGIN_MS.
|
|
112
|
+
*
|
|
113
|
+
* A mirror rather than an import because the frozen module keeps that constant
|
|
114
|
+
* private, and this chunk's rule is to mirror the five-minute margin rather than
|
|
115
|
+
* invent one. The consequence is stated rather than hidden: 'oauth.ts' ALREADY
|
|
116
|
+
* subtracts the same five minutes when it stamps expiresAt, so a credential this
|
|
117
|
+
* pool refreshes is refreshed roughly ten minutes ahead of the real expiry. That
|
|
118
|
+
* direction is the safe one for this line — a refresh that arrives early costs
|
|
119
|
+
* one rotation, while one that arrives late costs a 401 in the middle of a turn.
|
|
120
|
+
*/
|
|
121
|
+
export declare const CLAUDE_REFRESH_MARGIN_MS = 300000;
|
|
122
|
+
/**
|
|
123
|
+
* Message raised when the pool holds no account at all.
|
|
124
|
+
*
|
|
125
|
+
* Word for word the string 'oauth.ts' raises when its store is empty, so a user
|
|
126
|
+
* who reads either one is sent to the same place.
|
|
127
|
+
*/
|
|
128
|
+
export declare const CLAUDE_EMPTY_POOL_MESSAGE = "Not signed in to Claude. Sign in from Settings > Claude.";
|
|
129
|
+
/**
|
|
130
|
+
* Message for a credential that cannot reach /v1/messages at all.
|
|
131
|
+
*
|
|
132
|
+
* 'user:inference' is the scope that makes a token a SUBSCRIPTION credential;
|
|
133
|
+
* without it the credential authenticates but is not entitled to the routes this
|
|
134
|
+
* provider exists to serve, so the account is listed and refused rather than
|
|
135
|
+
* retried.
|
|
136
|
+
*/
|
|
137
|
+
export declare function claudeNonSubscriptionReason(): string;
|
|
138
|
+
/**
|
|
139
|
+
* Message raised if a refresh of a still-valid adopted snapshot were ever
|
|
140
|
+
* attempted.
|
|
141
|
+
*
|
|
142
|
+
* Unreachable through this pool's own paths (see the module comment); it exists
|
|
143
|
+
* because 'unreachable' is a claim the guard has to be able to make good on.
|
|
144
|
+
*/
|
|
145
|
+
export declare const ADOPTED_NEVER_REFRESHED_MESSAGE: string;
|
|
146
|
+
/**
|
|
147
|
+
* The adoption markers, as they hang off a credential stored by this pool.
|
|
148
|
+
*
|
|
149
|
+
* FLATTENED onto the credential, unlike the snapshot 'adopt.ts' returns, which
|
|
150
|
+
* nests the token under 'credentials'. Two reasons, both structural:
|
|
151
|
+
*
|
|
152
|
+
* - the pool's hooks (needsRefresh, refresh, authRejectedReason) receive the
|
|
153
|
+
* CREDENTIAL and never the account record, so the marker has to be reachable
|
|
154
|
+
* from there;
|
|
155
|
+
* - every other field this line reads (expiresAt, accessToken) sits at the top
|
|
156
|
+
* level, and a second nesting level would mean two shapes for one account.
|
|
157
|
+
*
|
|
158
|
+
* The predicate is therefore {@link isAdoptedPoolCredential} rather than
|
|
159
|
+
* 'adopt.ts''s own isAdoptedClaudeCredential, which additionally requires that
|
|
160
|
+
* nested 'credentials' record and so answers false for this spelling. The FIELDS
|
|
161
|
+
* it tests — adopted === true and source === 'claude-code' — are the same two,
|
|
162
|
+
* and the source constant is imported from that module rather than re-typed.
|
|
163
|
+
*/
|
|
164
|
+
export interface ClaudeAdoptedCredentialMarkers {
|
|
165
|
+
adopted?: true;
|
|
166
|
+
source?: string;
|
|
167
|
+
sourcePath?: string;
|
|
168
|
+
}
|
|
169
|
+
/** One pooled credential: the stored credential, plus the markers above. */
|
|
170
|
+
export type ClaudePoolCredentials = ClaudeCredentials & ClaudeAdoptedCredentialMarkers;
|
|
171
|
+
/** Where a pooled account's credential came from. */
|
|
172
|
+
export type ClaudePoolAccountSource = 'managed' | typeof CLAUDE_CODE_CREDENTIAL_SOURCE;
|
|
173
|
+
/** One pooled Claude account: the credential plus the facts the card renders. */
|
|
174
|
+
export interface ClaudePoolAccount extends PoolAccountShape<ClaudeCredentials> {
|
|
175
|
+
/**
|
|
176
|
+
* Append-only alias set, mirroring the credential document's own.
|
|
177
|
+
*
|
|
178
|
+
* Kept on the row so a merge (or the explicit
|
|
179
|
+
* {@link ClaudeAccountPool.mergeAccounts}) can carry an alias across instead of
|
|
180
|
+
* losing the only handle a seed-only snapshot has.
|
|
181
|
+
*/
|
|
182
|
+
identityKeys: string[];
|
|
183
|
+
/** Which store owns the credential. Only managed rows may be refreshed. */
|
|
184
|
+
source: ClaudePoolAccountSource;
|
|
185
|
+
/**
|
|
186
|
+
* Whether this row is a borrowed snapshot.
|
|
187
|
+
*
|
|
188
|
+
* Required rather than optional: every construction site has to state it, which
|
|
189
|
+
* is what keeps a stale true from surviving an in-place re-authorization.
|
|
190
|
+
*/
|
|
191
|
+
adopted: boolean;
|
|
192
|
+
/** Claude Code file an adopted snapshot was read from; absent for managed rows. */
|
|
193
|
+
sourcePath?: string;
|
|
194
|
+
/** Address the sign-in reported, when it reported one. */
|
|
195
|
+
email?: string;
|
|
196
|
+
/** Subscription tier the exchange reported, verbatim ('max', 'pro', ...). */
|
|
197
|
+
subscriptionType?: string;
|
|
198
|
+
/** Display form of {@link subscriptionType}; the card's plan badge. */
|
|
199
|
+
planLabel?: string;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* One account as the Claude settings card renders it.
|
|
203
|
+
*
|
|
204
|
+
* Declared here rather than under 'src/shared/': this slice is the pool's own
|
|
205
|
+
* vocabulary, and a later chunk imports it from this module instead of growing a
|
|
206
|
+
* second copy that drifts.
|
|
207
|
+
*/
|
|
208
|
+
export interface ClaudeAccountSummaryDto extends PoolAccountSummaryDto {
|
|
209
|
+
/** Where the credential came from; a card offers different actions per source. */
|
|
210
|
+
source?: ClaudePoolAccountSource;
|
|
211
|
+
/** Whether this row is a snapshot borrowed from a local Claude Code sign-in. */
|
|
212
|
+
adopted?: boolean;
|
|
213
|
+
/** The Claude Code file an adopted snapshot was read from. */
|
|
214
|
+
sourcePath?: string;
|
|
215
|
+
/** Subscription tier, from the credential itself. */
|
|
216
|
+
subscriptionType?: string;
|
|
217
|
+
}
|
|
218
|
+
/** Encrypted pool file this line owns; the credential document stays the mirror. */
|
|
219
|
+
export declare function claudePoolPath(): string;
|
|
220
|
+
/**
|
|
221
|
+
* Parse one stored credential TOLERANTLY; null when the row cannot serve.
|
|
222
|
+
*
|
|
223
|
+
* Deliberately not 'token-store.ts''s parseClaudeCredentials, and the difference
|
|
224
|
+
* is the point:
|
|
225
|
+
*
|
|
226
|
+
* - that parser is STRICT and refuses a credential with no 'user:inference'
|
|
227
|
+
* scope, which is right for the document it guards but would DELETE the row
|
|
228
|
+
* here. This pool has to be able to LIST a credential it refuses, so the
|
|
229
|
+
* refusal can be reported with a reason (see {@link claudeAuthRejectedReason})
|
|
230
|
+
* instead of the account silently vanishing from the card.
|
|
231
|
+
* - an adopted snapshot states no scopes at all when Claude Code's document did
|
|
232
|
+
* not, and 'adopt.ts' refuses to invent them.
|
|
233
|
+
*
|
|
234
|
+
* What is still refused, because such a row could never serve a request: a
|
|
235
|
+
* missing token, or an expiry that is not a finite number.
|
|
236
|
+
*/
|
|
237
|
+
export declare function parseClaudePoolCredentials(value: unknown): ClaudePoolCredentials | null;
|
|
238
|
+
/**
|
|
239
|
+
* Prefix of the id this pool gives a borrowed snapshot.
|
|
240
|
+
*
|
|
241
|
+
* A snapshot has no credential-document record, so there is no internalId to
|
|
242
|
+
* adopt; the pool has to name it. The name is WHERE IT CAME FROM rather than a
|
|
243
|
+
* digest of its tokens, and that choice is load-bearing: Claude Code refreshes
|
|
244
|
+
* its own file, so a re-import of an unchanged sign-in carries a DIFFERENT
|
|
245
|
+
* refresh token and therefore a different 'seed:' alias. Keying on the source
|
|
246
|
+
* file is what makes "import it again after signing in again in Claude Code" an
|
|
247
|
+
* UPDATE of the row the user already has, instead of a new row every time.
|
|
248
|
+
*
|
|
249
|
+
* The residual, stated rather than hidden: two accounts imported one after the
|
|
250
|
+
* other from the SAME path are one row, because the row means 'the sign-in that
|
|
251
|
+
* file currently holds' — which is exactly what a borrowed snapshot is. And a
|
|
252
|
+
* snapshot whose route did not record a path at all shares the 'unstated' name
|
|
253
|
+
* with any other such snapshot, so those collapse into one row too.
|
|
254
|
+
*/
|
|
255
|
+
export declare const ADOPTED_ACCOUNT_KEY_PREFIX = "adopted:";
|
|
256
|
+
/** The pool's own name for a borrowed snapshot. Never a token digest. */
|
|
257
|
+
export declare function adoptedPoolAccountKey(credentials: ClaudeCredentials): string;
|
|
258
|
+
/**
|
|
259
|
+
* Whether a pooled credential is an adopted snapshot.
|
|
260
|
+
*
|
|
261
|
+
* The two fields, and only those two: a plain credential has no 'adopted' field
|
|
262
|
+
* and must never be mistaken for a snapshot, because treating a plugin-owned
|
|
263
|
+
* account as disposable would refuse to refresh an account the user added here.
|
|
264
|
+
*/
|
|
265
|
+
export declare function isAdoptedPoolCredential(credentials: ClaudeCredentials): boolean;
|
|
266
|
+
/**
|
|
267
|
+
* Whether a credential must be refreshed before the next request.
|
|
268
|
+
*
|
|
269
|
+
* FALSE for every adopted snapshot, valid or expired. That is this chunk's core
|
|
270
|
+
* rule: an adopted credential is borrowed for exactly as long as Claude Code
|
|
271
|
+
* vouched for it, and this pool has no business rotating a token another process
|
|
272
|
+
* is rotating too. See the module comment.
|
|
273
|
+
*/
|
|
274
|
+
export declare function claudeNeedsRefresh(credentials: ClaudeCredentials, now: number): boolean;
|
|
275
|
+
/**
|
|
276
|
+
* Why a stored credential is already known to be unusable, or nothing.
|
|
277
|
+
*
|
|
278
|
+
* Reported purely — nothing is written here — and consulted by the core for both
|
|
279
|
+
* routing eligibility and credential usability, which is what makes an expired
|
|
280
|
+
* snapshot non-routable without a write on every read.
|
|
281
|
+
*
|
|
282
|
+
* Order matters: the expired-snapshot hint comes first because it is the
|
|
283
|
+
* actionable one (the remedy is in Claude Code, not here).
|
|
284
|
+
*/
|
|
285
|
+
export declare function claudeAuthRejectedReason(credentials: ClaudeCredentials): string | undefined;
|
|
286
|
+
/** Validate and normalize one whole pool document. */
|
|
287
|
+
export declare function parseClaudePoolData(value: unknown): PoolData<ClaudePoolAccount>;
|
|
288
|
+
/**
|
|
289
|
+
* The two-method credential store 'oauth.ts' wants, addressed at ONE account.
|
|
290
|
+
*
|
|
291
|
+
* See the module comment for why this bridge exists at all. The id is the
|
|
292
|
+
* document's own immutable internalId, which is also the pool row's id, so a
|
|
293
|
+
* refresh driven through here lands in the very record the pool lists — no
|
|
294
|
+
* second key space.
|
|
295
|
+
*
|
|
296
|
+
* write goes through saveAccount(credentials, { internalId }) rather than
|
|
297
|
+
* replacing the document, so the record keeps its append-only alias set and
|
|
298
|
+
* whatever a later chunk hung on it. It does NOT special-case an adopted
|
|
299
|
+
* snapshot: nothing in the pool ever asks this adapter to write one (the refresh
|
|
300
|
+
* guard refuses first), and silently discarding a caller's write would be a
|
|
301
|
+
* worse failure than the store's own strict validation.
|
|
302
|
+
*/
|
|
303
|
+
export declare class ClaudeCredentialStoreAdapter implements ClaudeTokenStore {
|
|
304
|
+
private readonly store;
|
|
305
|
+
private readonly internalId;
|
|
306
|
+
constructor(store: FileCredentialStore, internalId: string);
|
|
307
|
+
read(): Promise<ClaudeCredentials | null>;
|
|
308
|
+
write(credentials: ClaudeCredentials): Promise<void>;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* What the adapter must do with the account that produced a failed request.
|
|
312
|
+
*
|
|
313
|
+
* THE CONTRACT, and it is the adapter's to honour rather than this module's to
|
|
314
|
+
* enforce:
|
|
315
|
+
*
|
|
316
|
+
* - switch accounts, or cool one down, ONLY for a CREDENTIAL failure or an
|
|
317
|
+
* ACCOUNT-SCOPED rate limit. Both are attributable to one account, so another
|
|
318
|
+
* account can plausibly serve the same request.
|
|
319
|
+
* - NEVER rotate on a global rate limit, an overload (529), a server error, a
|
|
320
|
+
* transport failure, or a malformed request. None of them is any account's
|
|
321
|
+
* fault, and rotating would spend the whole pool against a wall every account
|
|
322
|
+
* is behind — while cooling accounts down would take the line offline with a
|
|
323
|
+
* cooldown nobody earned.
|
|
324
|
+
*
|
|
325
|
+
* The rule is NOT re-derived here: 'client.ts' classifyFailure already answers
|
|
326
|
+
* it, and ClaudeFailure.accountScoped is precisely 'this is THIS account's own
|
|
327
|
+
* spent window' (true only for rate_limit_account, and a 429 carrying no unified
|
|
328
|
+
* rate-limit header is deliberately classified GLOBAL). The helper below is that
|
|
329
|
+
* flag applied to a decision, so the adapter has one place to ask.
|
|
330
|
+
*/
|
|
331
|
+
export type ClaudeAccountRotationAction = {
|
|
332
|
+
action: 'mark-auth-failed';
|
|
333
|
+
status: AccountAuthStatus;
|
|
334
|
+
} | {
|
|
335
|
+
action: 'cool-down';
|
|
336
|
+
durationMs: number;
|
|
337
|
+
} | {
|
|
338
|
+
action: 'none';
|
|
339
|
+
};
|
|
340
|
+
/**
|
|
341
|
+
* Fallback cooldown for an account-scoped 429 that named no retry-after.
|
|
342
|
+
*
|
|
343
|
+
* Fifteen minutes mirrors the core's own assumption in its all-unavailable
|
|
344
|
+
* message, so a pool that falls back computes the wait a user would have been
|
|
345
|
+
* shown anyway.
|
|
346
|
+
*/
|
|
347
|
+
export declare const CLAUDE_DEFAULT_COOLDOWN_MS = 900000;
|
|
348
|
+
/**
|
|
349
|
+
* The rotation decision for one classified failure.
|
|
350
|
+
*
|
|
351
|
+
* @param failure - a 'client.ts' ClaudeFailure, or the three fields of one.
|
|
352
|
+
*/
|
|
353
|
+
export declare function claudeAccountRotationAction(failure: Pick<ClaudeFailure, 'kind' | 'accountScoped' | 'retryAfterMs'>, options?: {
|
|
354
|
+
fallbackCooldownMs?: number;
|
|
355
|
+
}): ClaudeAccountRotationAction;
|
|
356
|
+
/** Raised when a refresh of an adopted snapshot is attempted. Never a 401. */
|
|
357
|
+
export declare class ClaudeAdoptedCredentialError extends ClaudeUnauthorizedError {
|
|
358
|
+
constructor(message: string);
|
|
359
|
+
}
|
|
360
|
+
export interface ClaudeAccountPoolOptions {
|
|
361
|
+
/** Pre-pool credential document the pool mirrors its accounts into. */
|
|
362
|
+
store?: FileCredentialStore;
|
|
363
|
+
/** Test seam; production builds the platform backend from the pool path. */
|
|
364
|
+
backend?: CredentialStore<PoolData<ClaudePoolAccount>>;
|
|
365
|
+
/** Accounts this pool accepts; defaults to the core's limit. */
|
|
366
|
+
maxAccounts?: number;
|
|
367
|
+
/** The account the card pinned, or null for automatic selection. */
|
|
368
|
+
preferAccountId?: () => string | null;
|
|
369
|
+
/**
|
|
370
|
+
* Test seam for the token exchange itself.
|
|
371
|
+
*
|
|
372
|
+
* Replacing it does NOT bypass the adopted guard or the per-account
|
|
373
|
+
* single-flight above it, and the document write-back still happens: the seam
|
|
374
|
+
* is the network call, not the policy.
|
|
375
|
+
*/
|
|
376
|
+
refreshCredentials?: (credentials: ClaudeCredentials, fetchFn: typeof fetch) => Promise<ClaudeCredentials>;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* The Claude subscription account pool.
|
|
380
|
+
*
|
|
381
|
+
* Read the module comment first: it carries the two rules this class exists to
|
|
382
|
+
* enforce — an adopted snapshot is never refreshed, and one account has one key
|
|
383
|
+
* — together with the reasoning behind both.
|
|
384
|
+
*/
|
|
385
|
+
export declare class ClaudeAccountPool extends AccountPoolCore<ClaudeCredentials, ClaudePoolAccount, ClaudeAccountSummaryDto> {
|
|
386
|
+
private readonly store;
|
|
387
|
+
private readonly refreshSeam;
|
|
388
|
+
/**
|
|
389
|
+
* Identity alias -> internalId of the record that owns it.
|
|
390
|
+
*
|
|
391
|
+
* Rebuilt from the pool's own rows on every {@link read}, and additionally fed
|
|
392
|
+
* by {@link addAccount} from the credential document, which is what lets an
|
|
393
|
+
* incoming credential be resolved to an existing record BEFORE the core has to
|
|
394
|
+
* decide whether this is a new account.
|
|
395
|
+
*
|
|
396
|
+
* Entries are never pruned, deliberately. Dropping a live row's alias would
|
|
397
|
+
* make the very next credential for that account look new, which is the ghost
|
|
398
|
+
* row this index exists to prevent; a stale entry is overwritten by the next
|
|
399
|
+
* {@link read}, because a live row always re-indexes its own aliases.
|
|
400
|
+
*/
|
|
401
|
+
private readonly recordIds;
|
|
402
|
+
/**
|
|
403
|
+
* One in-flight refresh per account.
|
|
404
|
+
*
|
|
405
|
+
* The refresh token rotates, so two concurrent callers refreshing one account
|
|
406
|
+
* would spend it twice: the second exchange carries a token the first already
|
|
407
|
+
* rotated away, the endpoint answers with a final verdict, and the account is
|
|
408
|
+
* marked expired immediately after a refresh that in fact succeeded. Keyed by
|
|
409
|
+
* the record's id — never by a token — so it cannot mix two accounts up.
|
|
410
|
+
*/
|
|
411
|
+
private readonly inFlight;
|
|
412
|
+
constructor(options?: ClaudeAccountPoolOptions);
|
|
413
|
+
/** The credential document this pool mirrors into. */
|
|
414
|
+
mirrorStore(): FileCredentialStore;
|
|
415
|
+
/**
|
|
416
|
+
* The two-method store 'oauth.ts' needs, addressed at one account.
|
|
417
|
+
*
|
|
418
|
+
* The seam in one place: the sign-in flow (and any later route that acts on a
|
|
419
|
+
* single account) never has to know the document layout.
|
|
420
|
+
*/
|
|
421
|
+
credentialStoreFor(accountId: string): ClaudeTokenStore;
|
|
422
|
+
/**
|
|
423
|
+
* Read the pool, re-indexing the identity aliases on the way.
|
|
424
|
+
*
|
|
425
|
+
* Every routing decision goes through this method, so this is where the index
|
|
426
|
+
* {@link recordIdsFor} reads is kept in step with the rows that actually exist.
|
|
427
|
+
* See the recordIds field for why entries are not pruned.
|
|
428
|
+
*/
|
|
429
|
+
read(): Promise<PoolData<ClaudePoolAccount>>;
|
|
430
|
+
/**
|
|
431
|
+
* Add or re-authorize one account.
|
|
432
|
+
*
|
|
433
|
+
* The override exists for ONE reason: the account's id must be the credential
|
|
434
|
+
* document's internalId, and only this method can look that value up before
|
|
435
|
+
* the core has decided whether the account is new. See the module comment's
|
|
436
|
+
* 'one account, one key' section.
|
|
437
|
+
*/
|
|
438
|
+
addAccount(credentials: ClaudeCredentials, alias?: string): Promise<ClaudePoolAccount>;
|
|
439
|
+
/**
|
|
440
|
+
* Add, or re-import, one borrowed Claude Code snapshot.
|
|
441
|
+
*
|
|
442
|
+
* A snapshot is never written into this plugin's credential document — it is
|
|
443
|
+
* not this line's sign-in to keep — so its row is named by WHERE IT CAME FROM
|
|
444
|
+
* (see {@link adoptedPoolAccountKey}) and there is nothing to reconcile with
|
|
445
|
+
* the document.
|
|
446
|
+
*
|
|
447
|
+
* MANAGED BEATS ADOPTED, and this is where the two actually meet. A snapshot
|
|
448
|
+
* resolves to an existing row through its token seed, which is how an account
|
|
449
|
+
* imported here and then signed in through THIS plugin is recognized as one
|
|
450
|
+
* account: the row it lands on is already plugin-owned, and overwriting it with
|
|
451
|
+
* a borrowed credential would freeze that account until the snapshot expired —
|
|
452
|
+
* silently, and for no reason the user could see. So the snapshot contributes
|
|
453
|
+
* only what is new evidence (its aliases) and refuses to touch anything else.
|
|
454
|
+
*
|
|
455
|
+
* The id is resolved BEFORE the core is asked whether the account is already
|
|
456
|
+
* pooled, because the core computes the dedupe key at the TOP of its own
|
|
457
|
+
* addAccount: a key that only becomes known afterwards misses its one chance to
|
|
458
|
+
* answer, and every repeated import would add a row.
|
|
459
|
+
*/
|
|
460
|
+
private addAdoptedAccount;
|
|
461
|
+
/**
|
|
462
|
+
* Merge two rows that are one account.
|
|
463
|
+
*
|
|
464
|
+
* This is the user's remedy for the identity limitation 'token-store.ts'
|
|
465
|
+
* documents: a credential stating neither a uuid nor an address has only a
|
|
466
|
+
* token digest to go on, so a re-login produces a second record, and nothing
|
|
467
|
+
* can tell that apart from a genuinely different account. The same applies to
|
|
468
|
+
* an imported snapshot, which Claude Code's document gives no identity to.
|
|
469
|
+
*
|
|
470
|
+
* THE MANAGED ROW WINS THE CREDENTIAL — by construction, not by argument
|
|
471
|
+
* order. Only a plugin-owned credential may ever be refreshed, so a merge that
|
|
472
|
+
* kept a snapshot's tokens would leave the account frozen until it expired, for
|
|
473
|
+
* no reason the user could see. When BOTH rows are snapshots there is nothing
|
|
474
|
+
* to promote and the marker survives; otherwise the merged record is
|
|
475
|
+
* plugin-owned and refreshable again.
|
|
476
|
+
*
|
|
477
|
+
* The keeper's id, alias and ordering are kept, since those are what the
|
|
478
|
+
* settings document pins and what the user recognizes.
|
|
479
|
+
*/
|
|
480
|
+
mergeAccounts(keepAccountId: string, dropAccountId: string): Promise<ClaudePoolAccount>;
|
|
481
|
+
/**
|
|
482
|
+
* Fold two document records into the one the merged pool row points at.
|
|
483
|
+
*
|
|
484
|
+
* The alias sets are unioned rather than replaced, mirroring the document's own
|
|
485
|
+
* append-only rule: the discarded record's aliases are the only handles a
|
|
486
|
+
* seed-only credential has, and losing them would make the merged account
|
|
487
|
+
* unrecognizable to its own next refresh.
|
|
488
|
+
*/
|
|
489
|
+
private reconcileMergedDocument;
|
|
490
|
+
/**
|
|
491
|
+
* Drop an imported snapshot from the pool.
|
|
492
|
+
*
|
|
493
|
+
* A separate action because {@link deleteAccount} refuses one: the row is a
|
|
494
|
+
* borrowed snapshot, and a card must not destroy an account this plugin did
|
|
495
|
+
* not create with the same button that deletes its own. This is what an
|
|
496
|
+
* import card's 'remove import' calls; Claude Code's own file is touched by
|
|
497
|
+
* neither path.
|
|
498
|
+
*/
|
|
499
|
+
removeImportedAccount(accountId: string): Promise<void>;
|
|
500
|
+
/**
|
|
501
|
+
* Delete one plugin-owned account.
|
|
502
|
+
*
|
|
503
|
+
* Refused for an imported snapshot, following the WorkBuddy pool's precedent
|
|
504
|
+
* for accounts it did not sign in: the card offers
|
|
505
|
+
* {@link removeImportedAccount} there instead. A managed account is removed
|
|
506
|
+
* from the credential document as well, so the two stores cannot disagree
|
|
507
|
+
* about which accounts exist — the pre-pool projection would otherwise hand
|
|
508
|
+
* back a credential the user just deleted.
|
|
509
|
+
*/
|
|
510
|
+
deleteAccount(accountId: string): Promise<void>;
|
|
511
|
+
/**
|
|
512
|
+
* The immutable id of the record that owns a credential, or nothing.
|
|
513
|
+
*
|
|
514
|
+
* Resolution order mirrors 'token-store.ts''s own identity rules, minus the
|
|
515
|
+
* part that must never be a key: a strong alias ('uuid:..', 'email:..') is
|
|
516
|
+
* looked up first, and the 'seed:' digest is consulted ONLY as a lookup, so a
|
|
517
|
+
* credential stating no real identity still finds its record without the pool
|
|
518
|
+
* ever keying an account on a rotating token.
|
|
519
|
+
*/
|
|
520
|
+
private recordIdFor;
|
|
521
|
+
/**
|
|
522
|
+
* The key the pool files a credential under, or nothing.
|
|
523
|
+
*
|
|
524
|
+
* A MANAGED credential is named by the credential document's immutable
|
|
525
|
+
* internalId, so the pool and the document agree on one key — and that value is
|
|
526
|
+
* already known here, because a managed credential reaches this point only
|
|
527
|
+
* after the document has stored it and handed its id back.
|
|
528
|
+
*
|
|
529
|
+
* A BORROWED SNAPSHOT has no document record, so it cannot be named by one. It
|
|
530
|
+
* is named by its source file instead ({@link adoptedPoolAccountKey}), which is
|
|
531
|
+
* a fact the credential always carries. Answering `undefined` here for a
|
|
532
|
+
* snapshot would be fatal rather than cautious: the core treats `undefined` as
|
|
533
|
+
* `no dedupe key`, so every import would land as a brand new row — including
|
|
534
|
+
* the re-import this line's own instructions tell the user to perform after
|
|
535
|
+
* signing in again in Claude Code.
|
|
536
|
+
*/
|
|
537
|
+
private poolKeyFor;
|
|
538
|
+
/**
|
|
539
|
+
* The id this process already knows for a credential, or nothing.
|
|
540
|
+
*
|
|
541
|
+
* Resolution order mirrors 'token-store.ts''s own identity rules, minus the
|
|
542
|
+
* part that must never be a key: a strong alias ('uuid:..', 'email:..') is
|
|
543
|
+
* looked up first, and the 'seed:' digest is consulted ONLY as a lookup, so a
|
|
544
|
+
* credential stating no real identity still finds its record without the pool
|
|
545
|
+
* ever keying an account on a rotating token.
|
|
546
|
+
*/
|
|
547
|
+
private recordIdsFor;
|
|
548
|
+
private indexCredential;
|
|
549
|
+
private indexRecord;
|
|
550
|
+
private indexAccount;
|
|
551
|
+
/**
|
|
552
|
+
* Refresh one account's credential, and nothing else.
|
|
553
|
+
*
|
|
554
|
+
* Two guards live here and both are load-bearing:
|
|
555
|
+
*
|
|
556
|
+
* 1. an adopted snapshot is refused outright (see the module comment);
|
|
557
|
+
* 2. a second caller for the SAME account joins the first one's rotation
|
|
558
|
+
* instead of spending the rotating token twice.
|
|
559
|
+
*/
|
|
560
|
+
private refreshCredentials;
|
|
561
|
+
/**
|
|
562
|
+
* The per-account single-flight, resolving the account's id first.
|
|
563
|
+
*
|
|
564
|
+
* Separated from the hook above only because resolving the id consults the
|
|
565
|
+
* credential document, and a hook cannot await: the guard stays synchronous so
|
|
566
|
+
* it can never be skipped by a caller that forgets to wait.
|
|
567
|
+
*/
|
|
568
|
+
private singleFlightRefresh;
|
|
569
|
+
/**
|
|
570
|
+
* Rotate one managed credential and keep the credential document in step.
|
|
571
|
+
*
|
|
572
|
+
* The document write is what stops the pre-pool projection from handing out a
|
|
573
|
+
* token the rotation has already spent. Its failure is swallowed on purpose:
|
|
574
|
+
* the credential WAS refreshed, the pool's own record holds it, and a mirror
|
|
575
|
+
* that could not be written must not fail a request that can still be served —
|
|
576
|
+
* the same rule the core applies to its own bookkeeping writes.
|
|
577
|
+
*/
|
|
578
|
+
private performRefresh;
|
|
579
|
+
}
|
|
580
|
+
//# sourceMappingURL=account-pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-pool.d.ts","sourceRoot":"","sources":["../../../../src/host/claude/account-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqGG;AAIH,OAAO,EACL,eAAe,EAGf,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACd,MAAM,2BAA2B,CAAA;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAA;AACtG,OAAO,EACL,mBAAmB,EAQnB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,uBAAuB,EAEvB,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EAEL,6BAA6B,EAE9B,MAAM,YAAY,CAAA;AAEnB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAQhD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,SAAU,CAAA;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,6DAA6D,CAAA;AAEnG;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,CAGpD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,QAGmD,CAAA;AAM/F;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,8BAA8B;IAC7C,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,4EAA4E;AAC5E,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,GAAG,8BAA8B,CAAA;AAEtF,qDAAqD;AACrD,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,OAAO,6BAA6B,CAAA;AAEtF,iFAAiF;AACjF,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB,CAAC,iBAAiB,CAAC;IAC5E;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,2EAA2E;IAC3E,MAAM,EAAE,uBAAuB,CAAA;IAC/B;;;;;OAKG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB,mFAAmF;IACnF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,uBAAwB,SAAQ,qBAAqB;IACpE,kFAAkF;IAClF,MAAM,CAAC,EAAE,uBAAuB,CAAA;IAChC,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,oFAAoF;AACpF,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AA8BD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,qBAAqB,GAAG,IAAI,CAgDvF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,0BAA0B,aAAa,CAAA;AAEpD,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,iBAAiB,GAAG,MAAM,CAG5E;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,iBAAiB,GAAG,OAAO,CAG/E;AAcD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAGvF;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAc3F;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAoD/E;AA+BD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,4BAA6B,YAAW,gBAAgB;IAEjE,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;gBADV,KAAK,EAAE,mBAAmB,EAC1B,UAAU,EAAE,MAAM;IAG/B,IAAI,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAOzC,KAAK,CAAC,WAAW,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;CAG3D;AAMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,2BAA2B,GACnC;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAA;CAAE,GACzD;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtB;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,SAAU,CAAA;AAEjD;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,eAAe,GAAG,cAAc,CAAC,EACvE,OAAO,GAAE;IAAE,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5C,2BAA2B,CAc7B;AAMD,8EAA8E;AAC9E,qBAAa,4BAA6B,SAAQ,uBAAuB;gBAC3D,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,KAAK,CAAC,EAAE,mBAAmB,CAAA;IAC3B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAA;IACtD,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAA;IACrC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,CAAC,WAAW,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,KAAK,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAA;CAC3G;AA0CD;;;;;;GAMG;AACH,qBAAa,iBAAkB,SAAQ,eAAe,CACpD,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,CACxB;IACC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuF;IACnH;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4B;IACtD;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgD;gBAE7D,OAAO,GAAE,wBAA6B;IAoJlD,sDAAsD;IACtD,WAAW,IAAI,mBAAmB;IAIlC;;;;;OAKG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB;IAIvD;;;;;;OAMG;IACY,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;IAM3D;;;;;;;OAOG;IACY,UAAU,CAAC,WAAW,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAqDrG;;;;;;;;;;;;;;;;;;;;OAoBG;YACW,iBAAiB;IAmD/B;;;;;;;;;;;;;;;;;;OAkBG;IACG,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA8E7F;;;;;;;OAOG;YACW,uBAAuB;IAiCrC;;;;;;;;OAQG;IACG,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7D;;;;;;;;;OASG;IACY,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9D;;;;;;;;OAQG;YACW,WAAW;IAazB;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,UAAU;IAYlB;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,YAAY;IAapB;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;;;;;OAMG;YACW,mBAAmB;IAqBjC;;;;;;;;OAQG;YACW,cAAc;CAQ7B"}
|