@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,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DSH adapter for the `claude-subscription` route.
|
|
3
|
+
*
|
|
4
|
+
* This file is the only place the harness talks to. It owns: the model catalog
|
|
5
|
+
* the picker sees, the per-model resolution DSH asks for before a call, the one
|
|
6
|
+
* request loop, and the mapping of a failed response onto a DSH failure. It owns
|
|
7
|
+
* NO credential lifecycle of its own — refreshing is oauth.ts's job, storage is
|
|
8
|
+
* token-store.ts's job, the wire is client.ts's, the body and the SSE parse are
|
|
9
|
+
* mapper.ts's — and it re-implements none of them.
|
|
10
|
+
*
|
|
11
|
+
* ---------------------------------------------------------------------------
|
|
12
|
+
* 1. THE TWO LIMITS ON ACCOUNT ROTATION (the part that is easy to get wrong)
|
|
13
|
+
* ---------------------------------------------------------------------------
|
|
14
|
+
*
|
|
15
|
+
* With a pool installed, one failed response may be retried on a DIFFERENT
|
|
16
|
+
* account. Two rules bound that, and both are load-bearing:
|
|
17
|
+
*
|
|
18
|
+
* (a) WHAT may rotate. Only two conditions are attributable to one account:
|
|
19
|
+
* a credential verdict (that account's token is dead) and an
|
|
20
|
+
* ACCOUNT-SCOPED rate limit (that account's own usage window is spent).
|
|
21
|
+
* Everything else — a global rate limit, an `overloaded_error`, a generic
|
|
22
|
+
* 5xx — is shared by every account behind the same gateway, so rotating
|
|
23
|
+
* against it burns the pool and can loop. client.ts's classifyFailure
|
|
24
|
+
* already draws exactly this line (its `accountScoped` field), so the
|
|
25
|
+
* decision reads that rather than re-deriving it from headers here.
|
|
26
|
+
*
|
|
27
|
+
* (b) HOW FAR. At most {@link MAX_ATTEMPTS} requests per stream, ever. The loop
|
|
28
|
+
* is additionally driven by the pool's `hasAnotherAvailableAccount`, but
|
|
29
|
+
* that is a pool property, not a bound: a pool that keeps answering "yes"
|
|
30
|
+
* would otherwise be retried forever.
|
|
31
|
+
*
|
|
32
|
+
* And one hard rule that outranks both: NO ROTATION ONCE ANYTHING HAS REACHED
|
|
33
|
+
* THE CALLER. A retried request would repeat text the user has already read and
|
|
34
|
+
* re-issue a tool call that may already have executed. Rotation happens only
|
|
35
|
+
* before the response body is touched, which is where a fresh request is still
|
|
36
|
+
* free; once the first chunk has been yielded, a failure is SURFACED instead of
|
|
37
|
+
* retried. That rule is stated once in {@link shouldRotateAccount} so it cannot
|
|
38
|
+
* be quietly lost by a later reordering of this file.
|
|
39
|
+
*
|
|
40
|
+
* ---------------------------------------------------------------------------
|
|
41
|
+
* 2. ONE TOOL-NAME TABLE FOR BOTH DIRECTIONS
|
|
42
|
+
* ---------------------------------------------------------------------------
|
|
43
|
+
*
|
|
44
|
+
* The body renames every offered tool to its canonical wire spelling
|
|
45
|
+
* ('read' -> 'Read'), and the response side maps that spelling back to what the
|
|
46
|
+
* caller declared. Two independent calls to yaml's translation builder would
|
|
47
|
+
* produce two DIFFERENT tables — a collision that disables normalization on one
|
|
48
|
+
* side only, or a set that changed between build and parse — and the visible
|
|
49
|
+
* failure is a tool call dispatched to a tool the caller never offered. So the
|
|
50
|
+
* table is built once, per request, and handed to BOTH the body builder and
|
|
51
|
+
* `createStreamState`.
|
|
52
|
+
*
|
|
53
|
+
* ---------------------------------------------------------------------------
|
|
54
|
+
* 3. THE PRE-EXISTING SINGLE-CREDENTIAL PATH, AND THE THIN STORE ADAPTER
|
|
55
|
+
* ---------------------------------------------------------------------------
|
|
56
|
+
*
|
|
57
|
+
* Without a pool this route serves the account the credential document offers
|
|
58
|
+
* first — or the one the user pinned in `selectedAccountId`, which the pool
|
|
59
|
+
* mirrors as its primary. oauth.ts's `ensureAccessToken` was written against a
|
|
60
|
+
* two-method `{ read, write }` store because it must not learn the document
|
|
61
|
+
* layout, while FileCredentialStore is a multi-account document keyed by an
|
|
62
|
+
* immutable `internalId`. {@link ClaudeAccountTokenStore} is that seam: it
|
|
63
|
+
* presents exactly one account's credentials as the two methods, and records
|
|
64
|
+
* WHICH record it handed out so a rotated refresh token is written back into
|
|
65
|
+
* that record and not into whichever account happens to be first by the time
|
|
66
|
+
* the refresh lands.
|
|
67
|
+
*
|
|
68
|
+
* ---------------------------------------------------------------------------
|
|
69
|
+
* 4. FAILURE CLASSIFICATION
|
|
70
|
+
* ---------------------------------------------------------------------------
|
|
71
|
+
*
|
|
72
|
+
* client.ts classifies; this file only decides which DSH code that verdict
|
|
73
|
+
* becomes, and what the user is told:
|
|
74
|
+
*
|
|
75
|
+
* - `credential` -> INVALID_CREDENTIAL (sign in again);
|
|
76
|
+
* - an account-scoped or global limit -> RATE_LIMIT;
|
|
77
|
+
* - `overloaded` and `server` -> SERVER;
|
|
78
|
+
* - `request` -> PROVIDER_ERROR;
|
|
79
|
+
* - `network` -> TRANSPORT.
|
|
80
|
+
*
|
|
81
|
+
* A reported-client-version rejection is a REQUEST problem even though it
|
|
82
|
+
* arrives as a 400 that mentions the client: it must NOT sign the user out, and
|
|
83
|
+
* it has a real remedy (raise the reported version), so it is handled
|
|
84
|
+
* explicitly with that remedy in the message.
|
|
85
|
+
*
|
|
86
|
+
* ---------------------------------------------------------------------------
|
|
87
|
+
* 5. ASSUMPTIONS AND JUDGEMENT CALLS
|
|
88
|
+
* ---------------------------------------------------------------------------
|
|
89
|
+
*
|
|
90
|
+
* - A1. The pool seam is typed STRUCTURALLY here rather than against
|
|
91
|
+
* './account-pool.ts'. That file is written by a sibling chunk of this line;
|
|
92
|
+
* importing it before it exists would make this adapter uncompilable, and
|
|
93
|
+
* importing it afterwards changes nothing, because the only methods used are
|
|
94
|
+
* the five in {@link ClaudeAccountPoolLike}.
|
|
95
|
+
* - A2. The live `GET /v1/models` listing is NOT read on the request path. It
|
|
96
|
+
* is authoritative for the context window alone (see client.ts), and the only
|
|
97
|
+
* model fact the body depends on — the thinking form — comes from the frozen
|
|
98
|
+
* catalog. Loading it per request would add a cached round trip that cannot
|
|
99
|
+
* change a byte of the body.
|
|
100
|
+
* - A3. A 429 with no `retry-after` and no reset instant cools the account for
|
|
101
|
+
* {@link POOL_COOLDOWN_MS}. That is deliberately shorter than the 5-hour
|
|
102
|
+
* window: an account parked for hours after a burst limit recovers would cost
|
|
103
|
+
* the user the pool, while a too-short cooldown costs one rotation.
|
|
104
|
+
* - A4. Adoption (adopt.ts) is not handled here. An adopted Claude Code
|
|
105
|
+
* credential is a pool concern — the pool is what must refuse to refresh it —
|
|
106
|
+
* and this adapter only ever sees the credential the pool or the document
|
|
107
|
+
* hands it.
|
|
108
|
+
* - A5. The enabled-model rule is stated locally in
|
|
109
|
+
* {@link resolveEnabledModelIds} because './routes.ts' (the sibling chunk that
|
|
110
|
+
* owns the settings card for this line) does not exist yet. It mirrors the
|
|
111
|
+
* sibling providers' rule exactly; once routes.ts lands it is the natural home
|
|
112
|
+
* for this function and the two should be one.
|
|
113
|
+
*/
|
|
114
|
+
import { LlmAdapter, LlmError, ReasoningEffortId, type GenerateOptions, type LlmModelInfo, type LlmProviderInfo, type LlmResolvedModelInfo, type PreparedAdapterCall, type ResolvedRetryPolicy, type StreamChunk } from '@deepseek-ai/dsh-llm';
|
|
115
|
+
import { PROVIDER_ID, PROVIDER_NAME } from './types.ts';
|
|
116
|
+
import { FileCredentialStore, FileModelSettingsStore, type ClaudeCredentials, type ClaudePreferenceStore } from './token-store.ts';
|
|
117
|
+
import { type ClaudeModelEntry } from './model-catalog.ts';
|
|
118
|
+
import { type ClaudeFailure } from './client.ts';
|
|
119
|
+
import { type AttachmentImageReader } from './mapper.ts';
|
|
120
|
+
/**
|
|
121
|
+
* Cooldown a 429 imposes when the service names no reset instant.
|
|
122
|
+
*
|
|
123
|
+
* Deliberately far shorter than the 5-hour window it may be reporting: the
|
|
124
|
+
* accurate wait arrives as `retry-after` or as the ISO instant in the error
|
|
125
|
+
* message, and this is only the fallback for a response that states neither.
|
|
126
|
+
*/
|
|
127
|
+
export declare const POOL_COOLDOWN_MS: number;
|
|
128
|
+
/**
|
|
129
|
+
* The pool surface this adapter uses, stated structurally.
|
|
130
|
+
*
|
|
131
|
+
* See module note A1: './account-pool.ts' is a sibling chunk's file, and typing
|
|
132
|
+
* against the five methods actually called keeps this adapter compilable
|
|
133
|
+
* whether or not that file has landed.
|
|
134
|
+
*/
|
|
135
|
+
export interface ClaudeAccountPoolLike {
|
|
136
|
+
getEffectiveAccount(excludeIds?: ReadonlySet<string>, fetchFn?: typeof fetch): Promise<{
|
|
137
|
+
account: {
|
|
138
|
+
id: string;
|
|
139
|
+
};
|
|
140
|
+
credentials: ClaudeCredentials;
|
|
141
|
+
}>;
|
|
142
|
+
hasAnotherAvailableAccount(triedAccountIds: ReadonlySet<string>): Promise<boolean>;
|
|
143
|
+
markCooldown(accountId: string, durationMs: number, reason: string): Promise<void>;
|
|
144
|
+
markAuthFailed(accountId: string, reason: string): Promise<void>;
|
|
145
|
+
}
|
|
146
|
+
export interface ClaudeAdapterOptions {
|
|
147
|
+
fetchFn?: typeof fetch;
|
|
148
|
+
/** Attachment seam: durable images become inline bytes for one request. */
|
|
149
|
+
attachments?: AttachmentImageReader;
|
|
150
|
+
/** Live catalog loader seam; defaults to this account's managed listing. */
|
|
151
|
+
loadCatalog?: (credentials: ClaudeCredentials) => Promise<readonly ClaudeModelEntry[]>;
|
|
152
|
+
/**
|
|
153
|
+
* Multi-account pool this adapter rotates through.
|
|
154
|
+
*
|
|
155
|
+
* Absent leaves the line on its single-credential path, which is what a
|
|
156
|
+
* headless test and any caller that predates the pool use.
|
|
157
|
+
*/
|
|
158
|
+
accountPool?: ClaudeAccountPoolLike;
|
|
159
|
+
}
|
|
160
|
+
export declare class ClaudeAdapter extends LlmAdapter {
|
|
161
|
+
private readonly store;
|
|
162
|
+
private readonly modelSettings;
|
|
163
|
+
private readonly preferences?;
|
|
164
|
+
private readonly options;
|
|
165
|
+
/** Null keeps the pre-pool single-credential path. */
|
|
166
|
+
private readonly accountPool;
|
|
167
|
+
constructor(store?: FileCredentialStore, modelSettings?: FileModelSettingsStore, preferences?: ClaudePreferenceStore | undefined, options?: ClaudeAdapterOptions);
|
|
168
|
+
providerInfo(provider: string): LlmProviderInfo;
|
|
169
|
+
providerRetryPolicy(): ResolvedRetryPolicy;
|
|
170
|
+
/**
|
|
171
|
+
* This route prices no visual tokens.
|
|
172
|
+
*
|
|
173
|
+
* The subscription bills in subscription windows rather than per image, so
|
|
174
|
+
* there is no per-image price to state and the harness's neutral estimate is
|
|
175
|
+
* the honest answer. Stated explicitly, as every sibling line does, so the
|
|
176
|
+
* absence is a decision rather than an unimplemented method.
|
|
177
|
+
*/
|
|
178
|
+
imageRequestPricing(): undefined;
|
|
179
|
+
private settings;
|
|
180
|
+
/**
|
|
181
|
+
* The account record the single-credential path serves.
|
|
182
|
+
*
|
|
183
|
+
* The pinned account wins while it exists in the document — that is the
|
|
184
|
+
* account the user chose on the card, and honouring it here keeps the
|
|
185
|
+
* single-credential path agreeing with what the card shows. Otherwise the
|
|
186
|
+
* document is in insertion order and the first record is the primary one,
|
|
187
|
+
* which is also what the pool mirrors into this store.
|
|
188
|
+
*/
|
|
189
|
+
private primaryAccount;
|
|
190
|
+
/**
|
|
191
|
+
* Catalog for one credential: the account's live listing, or the shipped table.
|
|
192
|
+
*
|
|
193
|
+
* client.ts's loader never rejects and never returns empty — it answers with
|
|
194
|
+
* the shipped table when the call fails, precisely so a failed listing cannot
|
|
195
|
+
* become the hard "model must be in the catalog" gate. The guard here is for a
|
|
196
|
+
* caller-supplied seam that does neither.
|
|
197
|
+
*/
|
|
198
|
+
private catalog;
|
|
199
|
+
listModels(provider?: string): Promise<readonly LlmModelInfo[]>;
|
|
200
|
+
resolveModel(provider: string, modelId: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo>;
|
|
201
|
+
prepareCall(provider: string, model: string, signal?: AbortSignal): Promise<PreparedAdapterCall>;
|
|
202
|
+
stream(options: GenerateOptions): AsyncIterable<StreamChunk>;
|
|
203
|
+
/**
|
|
204
|
+
* Read one credential for this attempt.
|
|
205
|
+
*
|
|
206
|
+
* Pooled and pre-pool are two different questions. With a pool this is a
|
|
207
|
+
* ROUTING decision — which account should serve this request — answered
|
|
208
|
+
* through cooldowns, auth status and the rotation strategy; the pool also owns
|
|
209
|
+
* refreshing the credential it hands back. Without one there is exactly one
|
|
210
|
+
* account, so the question is whether its token is still usable, and
|
|
211
|
+
* ensureAccessToken answers it single-flightedly (the refresh token rotates,
|
|
212
|
+
* so two callers must not each spend it).
|
|
213
|
+
*/
|
|
214
|
+
private resolveCredential;
|
|
215
|
+
/**
|
|
216
|
+
* One request attempt, after the credential for it has been chosen.
|
|
217
|
+
*
|
|
218
|
+
* A SEPARATE function from the rotation loop on purpose: importing
|
|
219
|
+
* './account-pool.ts' would make this adapter uncompilable while that sibling
|
|
220
|
+
* file is still being written (see the module note), so the rotation loop is
|
|
221
|
+
* driven by {@link shouldRotateAccount}, which bypasses the pool ENTIRELY when
|
|
222
|
+
* no credentials were resolved for it.
|
|
223
|
+
*/
|
|
224
|
+
private attemptRequest;
|
|
225
|
+
private requestStream;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Effort to materialize as this route's default, or nothing.
|
|
229
|
+
*
|
|
230
|
+
* Membership, not convergence: the catalog's ladder IS the wire vocabulary, and
|
|
231
|
+
* a configured level outside it is dropped rather than moved onto a neighbour.
|
|
232
|
+
* Moving it would silently change how hard the model thinks, and the four
|
|
233
|
+
* thinking forms each carry the effort differently, so there is no single
|
|
234
|
+
* correct neighbour to pick. 'xhigh' and 'max' are real rungs on this route and
|
|
235
|
+
* pass through untouched.
|
|
236
|
+
*/
|
|
237
|
+
export declare function resolveDefaultReasoningEffort(efforts: readonly string[], configuredEffort?: string | null): ReasoningEffortId | undefined;
|
|
238
|
+
/**
|
|
239
|
+
* Whether one failed response may be retried on another account.
|
|
240
|
+
*
|
|
241
|
+
* Only two conditions qualify, and the reason is the same for both: they are
|
|
242
|
+
* properties of ONE account. A credential verdict means that account's token is
|
|
243
|
+
* finished; an ACCOUNT-SCOPED rate limit means that account's own window is
|
|
244
|
+
* spent. A global rate limit, an overload and a generic 5xx are shared by every
|
|
245
|
+
* account behind the same gateway — rotating against them burns the pool and can
|
|
246
|
+
* loop, because the next account fails identically.
|
|
247
|
+
*
|
|
248
|
+
* The one absolute refusal is `outputStarted`: after the first chunk has
|
|
249
|
+
* reached the caller, a retry would repeat text and re-issue a tool call, so the
|
|
250
|
+
* failure is surfaced instead.
|
|
251
|
+
*/
|
|
252
|
+
export declare function shouldRotateAccount(failure: ClaudeFailure, outputStarted: boolean): boolean;
|
|
253
|
+
/** How long a rate-limited account stays out of rotation. */
|
|
254
|
+
export declare function cooldownMsFor(failure: ClaudeFailure, now?: number): number;
|
|
255
|
+
/** The DSH failure code one classified failure becomes. */
|
|
256
|
+
export declare function codeForFailure(failure: ClaudeFailure): string;
|
|
257
|
+
/**
|
|
258
|
+
* Turn one classified failure into the DSH error the caller sees.
|
|
259
|
+
*
|
|
260
|
+
* The facts the harness needs ride along: the HTTP status, and the delay the
|
|
261
|
+
* provider asked for, which is where the retry policy reads its backoff from.
|
|
262
|
+
* An unreadable status (0 from a transport failure) is omitted rather than
|
|
263
|
+
* passed on, because LlmError validates it as a real HTTP status.
|
|
264
|
+
*/
|
|
265
|
+
export declare function toLlmError(failure: ClaudeFailure): LlmError;
|
|
266
|
+
export { PROVIDER_ID, PROVIDER_NAME };
|
|
267
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/host/claude/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OPT-IN adoption of a pre-existing Claude Code sign-in.
|
|
3
|
+
*
|
|
4
|
+
* WHAT THIS IS FOR. A user who already runs the unmodified Claude Code client is
|
|
5
|
+
* already signed in to the very subscription this provider serves. Asking them
|
|
6
|
+
* to sign in a second time is pure friction, so this module offers the one thing
|
|
7
|
+
* that removes it: reading back the credential Claude Code itself stored. It is
|
|
8
|
+
* opt-in — nothing here runs until the user asks for it.
|
|
9
|
+
*
|
|
10
|
+
* ---------------------------------------------------------------------------
|
|
11
|
+
* RULE 1 — THIS MODULE NEVER WRITES. IT IS A READER, AND ONLY A READER.
|
|
12
|
+
* ---------------------------------------------------------------------------
|
|
13
|
+
* It must not create, modify, move or delete any file belonging to Claude Code.
|
|
14
|
+
* No file this module touches is ever opened for writing, no directory is
|
|
15
|
+
* created, nothing is renamed and nothing is unlinked. The guarantee is
|
|
16
|
+
* structural rather than a promise in prose: the module imports exactly two
|
|
17
|
+
* functions BY NAME from 'node:fs/promises' — readFile and stat — instead of the
|
|
18
|
+
* whole namespace, so introducing a write would require a visible change to the
|
|
19
|
+
* import list, which is the line a reviewer reads first. Nothing exported here
|
|
20
|
+
* writes. The tests assert the stronger, observable form of the rule: a
|
|
21
|
+
* credential file's bytes, size and mtime are identical before and after both
|
|
22
|
+
* entry points run, and its directory gains no entries.
|
|
23
|
+
*
|
|
24
|
+
* ---------------------------------------------------------------------------
|
|
25
|
+
* RULE 2 — PRESENCE AND CONTENT ARE TWO SEPARATE FUNCTIONS
|
|
26
|
+
* ---------------------------------------------------------------------------
|
|
27
|
+
* claudeCodeCredentialPresence() is cheap enough to call on plugin startup and
|
|
28
|
+
* answers only yes/no: it stats candidates and never opens one for reading. It
|
|
29
|
+
* exists so the settings card can offer the import before the user has agreed to
|
|
30
|
+
* it, and so a user who never opts in never has their token read at all.
|
|
31
|
+
*
|
|
32
|
+
* readClaudeCodeCredentials() is the full read, and it is called only AFTER the
|
|
33
|
+
* user explicitly opts in. Keeping the two apart is the whole point: a startup
|
|
34
|
+
* path that slurped the file "just in case" would make the opt-in decorative.
|
|
35
|
+
*
|
|
36
|
+
* ---------------------------------------------------------------------------
|
|
37
|
+
* RULE 3 — AN ADOPTED CREDENTIAL IS A SNAPSHOT, AND THIS PLUGIN NEVER REFRESHES IT
|
|
38
|
+
* ---------------------------------------------------------------------------
|
|
39
|
+
* An adopted credential is used only while its own accessToken is still valid.
|
|
40
|
+
* Once it is expired we report it as expired and tell the user to sign in again
|
|
41
|
+
* in Claude Code and re-adopt. That is deliberate, not a gap:
|
|
42
|
+
*
|
|
43
|
+
* Claude Code's refresh token is ROTATING — every refresh both consumes the
|
|
44
|
+
* stored refresh token and issues a new one. Two processes refreshing the same
|
|
45
|
+
* grant therefore invalidate each other: whoever loses the race holds a token
|
|
46
|
+
* the server has already retired, and the user ends up signed OUT of Claude
|
|
47
|
+
* Code by this plugin's good intentions. An in-process single-flight cannot fix
|
|
48
|
+
* that, because the race is across PROCESSES: this plugin and Claude Code are
|
|
49
|
+
* separate programs with separate memories, and the only shared state between
|
|
50
|
+
* them is the file — which this module must not write back into (Rule 1).
|
|
51
|
+
*
|
|
52
|
+
* So the honest contract is: borrow the access token for as long as Claude Code
|
|
53
|
+
* itself vouched for it, and never touch the refresh token. Expiry is therefore
|
|
54
|
+
* part of the adoption decision rather than a detail — see
|
|
55
|
+
* {@link isAdoptedCredentialExpired}.
|
|
56
|
+
*
|
|
57
|
+
* The marker the pool chunk must honour is the literal 'adopted: true' on every
|
|
58
|
+
* returned snapshot, plus {@link isAdoptedClaudeCredential}; an account carrying
|
|
59
|
+
* it must be treated as read-only, non-refreshable and disposable. There is
|
|
60
|
+
* deliberately no refresh function in this module to find in the first place.
|
|
61
|
+
*
|
|
62
|
+
* ---------------------------------------------------------------------------
|
|
63
|
+
* RULE 4 — AN UNRECOGNISED SHAPE YIELDS undefined, NEVER AN EXCEPTION
|
|
64
|
+
* ---------------------------------------------------------------------------
|
|
65
|
+
* The card shows 'unrecognised local sign-in format' for undefined, which is a
|
|
66
|
+
* far better outcome than a thrown error escaping into the settings route.
|
|
67
|
+
* Nothing is guessed: a document missing either token, a claudeAiOauth that is
|
|
68
|
+
* not an object, an unreadable or unparsable file — all of them are undefined.
|
|
69
|
+
* Extra and unknown fields are ignored rather than rejected, so a future Claude
|
|
70
|
+
* Code that adds one does not break adoption.
|
|
71
|
+
*
|
|
72
|
+
* THE TRAP THIS PARSER EXISTS TO AVOID. The credential document is NOT a flat bag
|
|
73
|
+
* of tokens. The same file also carries MCP server sign-ins under
|
|
74
|
+
* mcpOAuth.*.accessToken, and those are DIFFERENT tokens for DIFFERENT services.
|
|
75
|
+
* A "find the first accessToken anywhere in the JSON" scan silently picks
|
|
76
|
+
* whichever one the serializer happened to emit first, which is how an MCP token
|
|
77
|
+
* ends up presented to the Messages API as the user's subscription credential.
|
|
78
|
+
* The read is therefore a direct, specific lookup of claudeAiOauth.accessToken —
|
|
79
|
+
* never a tree walk — and the test suite holds a fixture containing BOTH tokens
|
|
80
|
+
* and asserts which one comes back.
|
|
81
|
+
*
|
|
82
|
+
* ---------------------------------------------------------------------------
|
|
83
|
+
* WHAT COULD NOT BE VERIFIED, AND IS THEREFORE NOT CLAIMED
|
|
84
|
+
* ---------------------------------------------------------------------------
|
|
85
|
+
* The file layout below (a credential file named .credentials.json inside the
|
|
86
|
+
* config home, JSON of the shape { "claudeAiOauth": { accessToken, refreshToken,
|
|
87
|
+
* expiresAt, scopes, subscriptionType } } with expiresAt in EPOCH MILLISECONDS)
|
|
88
|
+
* is assembled from secondary sources. This machine has NO Claude Code
|
|
89
|
+
* installation and NO such file — all candidate paths were checked and every one
|
|
90
|
+
* is absent — so this reader is proven by CONSTRUCTION against fixtures and NOT
|
|
91
|
+
* by a live read of a real client's file. A layout difference in a future Claude
|
|
92
|
+
* Code would surface as 'unrecognised local sign-in format' rather than as a
|
|
93
|
+
* wrong token, because the parser is written to refuse rather than to improvise.
|
|
94
|
+
*
|
|
95
|
+
* A KNOWN NON-GOAL: on macOS Claude Code also keeps an entry in the login
|
|
96
|
+
* Keychain (reported as service 'Claude Code-credentials'). This module does NOT
|
|
97
|
+
* read it. The service name is unverified — a third-party guide and the real
|
|
98
|
+
* client disagree about it — and asking the Keychain for a name that is not the
|
|
99
|
+
* real one either finds nothing or, worse, finds somebody else's item. A file
|
|
100
|
+
* path that can be printed in the UI and inspected by the user beats a guessed
|
|
101
|
+
* Keychain query, so the Keychain is left strictly alone.
|
|
102
|
+
*/
|
|
103
|
+
import type { ClaudeCredentials } from './token-store.ts';
|
|
104
|
+
/**
|
|
105
|
+
* Environment variable that relocates Claude Code's config directory.
|
|
106
|
+
*
|
|
107
|
+
* Highest precedence, and honoured exactly as the client honours it: when it is
|
|
108
|
+
* set to a non-blank value it names the config home, whatever the platform's
|
|
109
|
+
* conventional location happens to be. This is also what makes the whole module
|
|
110
|
+
* testable without touching a developer's real profile.
|
|
111
|
+
*/
|
|
112
|
+
export declare const CLAUDE_CONFIG_DIR_ENV = "CLAUDE_CONFIG_DIR";
|
|
113
|
+
/** File name of the credential document inside the config home. */
|
|
114
|
+
export declare const CLAUDE_CODE_CREDENTIAL_FILE = ".credentials.json";
|
|
115
|
+
/**
|
|
116
|
+
* Top-level key holding the subscription sign-in.
|
|
117
|
+
*
|
|
118
|
+
* Named as a constant because the specificity of this key IS the defence
|
|
119
|
+
* described in the module comment: the read addresses this key, not the first
|
|
120
|
+
* token it can find anywhere in the document.
|
|
121
|
+
*/
|
|
122
|
+
export declare const CLAUDE_CODE_CREDENTIAL_KEY = "claudeAiOauth";
|
|
123
|
+
/** Where an adopted snapshot came from, for the card and for the pool record. */
|
|
124
|
+
export declare const CLAUDE_CODE_CREDENTIAL_SOURCE = "claude-code";
|
|
125
|
+
/**
|
|
126
|
+
* Expiry value stamped on a credential that states no usable one.
|
|
127
|
+
*
|
|
128
|
+
* Epoch zero, and it is a deliberate choice over "now" or "Infinity". Infinity
|
|
129
|
+
* would turn a missing field into a credential that never expires — the exact
|
|
130
|
+
* inversion of the safe reading, because a credential whose validity cannot be
|
|
131
|
+
* established must not be used. Epoch zero is unambiguous, survives a JSON round
|
|
132
|
+
* trip, and compares as expired against any clock a user's machine can hold, so
|
|
133
|
+
* a damaged document degrades into "expired, sign in again" instead of into a
|
|
134
|
+
* request carrying a token nobody vouched for.
|
|
135
|
+
*/
|
|
136
|
+
export declare const UNKNOWN_CREDENTIAL_EXPIRY = 0;
|
|
137
|
+
/**
|
|
138
|
+
* What the user is told when an adopted credential has aged out.
|
|
139
|
+
*
|
|
140
|
+
* Exported so the settings card and the pool report the same sentence, and so the
|
|
141
|
+
* instruction is stated once: re-sign-in happens in CLAUDE CODE, not here, and
|
|
142
|
+
* the import has to be repeated afterwards.
|
|
143
|
+
*/
|
|
144
|
+
export declare const ADOPTED_CREDENTIAL_EXPIRED_HINT: string;
|
|
145
|
+
/** One adopted credential: the store's own credential shape plus its provenance. */
|
|
146
|
+
export interface ClaudeCodeAdoptedCredential {
|
|
147
|
+
/**
|
|
148
|
+
* The pool marker. Literal true on every snapshot this module returns.
|
|
149
|
+
*
|
|
150
|
+
* A discriminant rather than a description: a pool chunk that stores this
|
|
151
|
+
* record must refuse to refresh it, and a boolean it can test is harder to
|
|
152
|
+
* overlook than a comment it can read past.
|
|
153
|
+
*/
|
|
154
|
+
readonly adopted: true;
|
|
155
|
+
/** Which local sign-in this was taken from. */
|
|
156
|
+
readonly source: typeof CLAUDE_CODE_CREDENTIAL_SOURCE;
|
|
157
|
+
/** The exact file it was read from, so the card can name it. */
|
|
158
|
+
readonly sourcePath: string;
|
|
159
|
+
/** The credential in the store's own shape, ready to be persisted by the caller. */
|
|
160
|
+
readonly credentials: ClaudeCredentials;
|
|
161
|
+
}
|
|
162
|
+
/** Answer to the startup question: is there anything to adopt? */
|
|
163
|
+
export interface ClaudeCodeCredentialPresence {
|
|
164
|
+
/** Whether a candidate exists. Says nothing about whether it is usable. */
|
|
165
|
+
present: boolean;
|
|
166
|
+
/** The first candidate that exists, or null when none does. */
|
|
167
|
+
path: string | null;
|
|
168
|
+
/**
|
|
169
|
+
* Every candidate consulted, in precedence order, whether or not it existed.
|
|
170
|
+
*
|
|
171
|
+
* Returned so the card can print the exact list it looked at — the difference
|
|
172
|
+
* between "not found" and "your client stores it somewhere else" is invisible
|
|
173
|
+
* to a user who is only told the first path.
|
|
174
|
+
*/
|
|
175
|
+
searched: string[];
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Claude Code's config home.
|
|
179
|
+
*
|
|
180
|
+
* The environment override wins whenever it is set to a non-blank value — a blank
|
|
181
|
+
* or whitespace-only variable is treated as unset rather than as "the directory
|
|
182
|
+
* whose name is empty", which on Windows would resolve to a drive-relative path.
|
|
183
|
+
* Otherwise the conventional home/.claude directory is used, os.homedir() being
|
|
184
|
+
* the same %USERPROFILE% on Windows and ~ on POSIX that the client itself uses.
|
|
185
|
+
*
|
|
186
|
+
* Read at CALL time rather than captured in a module constant: a test (or an
|
|
187
|
+
* embedder) that sets the variable after import must see the change.
|
|
188
|
+
*/
|
|
189
|
+
export declare function claudeConfigDir(): string;
|
|
190
|
+
/**
|
|
191
|
+
* Every path this module will look at, most authoritative first.
|
|
192
|
+
*
|
|
193
|
+
* The FIRST entry is always the config home from {@link claudeConfigDir} — the
|
|
194
|
+
* location the client is documented to use — so the card can print it as "the"
|
|
195
|
+
* path.
|
|
196
|
+
*
|
|
197
|
+
* The conventional home/.claude/.credentials.json follows as a FALLBACK whenever
|
|
198
|
+
* it is not already the first entry. Judgement call, stated plainly: treating the
|
|
199
|
+
* environment override as absolutely exclusive would make a stale or
|
|
200
|
+
* freshly-created override directory — a user who once pointed the variable at a
|
|
201
|
+
* scratch profile and forgot — report "no sign-in found" while a perfectly good
|
|
202
|
+
* one sits in the conventional location. The fallback costs one stat, is
|
|
203
|
+
* consulted only when the earlier candidate yields nothing usable, and the file
|
|
204
|
+
* actually used is always reported back in
|
|
205
|
+
* {@link ClaudeCodeAdoptedCredential.sourcePath}. The residual risk is adopting a
|
|
206
|
+
* snapshot belonging to a different profile than the one Claude Code is currently
|
|
207
|
+
* using; it is bounded by the fact that such a snapshot is only ever used while
|
|
208
|
+
* its own access token is unexpired, and it is visible to the user because the
|
|
209
|
+
* source path is shown.
|
|
210
|
+
*
|
|
211
|
+
* A pure function — no filesystem access at all — so it is safe to call just to
|
|
212
|
+
* render the card, and so its precedence is testable without touching a disk.
|
|
213
|
+
*/
|
|
214
|
+
export declare function claudeCodeCredentialPaths(): string[];
|
|
215
|
+
/**
|
|
216
|
+
* Is there a local Claude Code sign-in to offer?
|
|
217
|
+
*
|
|
218
|
+
* Safe on plugin startup: this NEVER opens a candidate for reading, so a user who
|
|
219
|
+
* never opts in never has the credential's contents touched — not by this
|
|
220
|
+
* function, not by the route that renders the card. Only stat runs, which reveals
|
|
221
|
+
* existence and timestamps and nothing else.
|
|
222
|
+
*
|
|
223
|
+
* Deliberately NOT reported here: whether the file is valid, expired, or even
|
|
224
|
+
* JSON. Answering that would require the read this function exists to avoid, and
|
|
225
|
+
* the card does not need it — validity is answered by the read, after opt-in, and
|
|
226
|
+
* lands on the card as either a credential or 'unrecognised local sign-in
|
|
227
|
+
* format'.
|
|
228
|
+
*
|
|
229
|
+
* paths is injectable so tests drive it against fixtures instead of a real
|
|
230
|
+
* profile; production callers take the default.
|
|
231
|
+
*/
|
|
232
|
+
export declare function claudeCodeCredentialPresence(paths?: readonly string[]): Promise<ClaudeCodeCredentialPresence>;
|
|
233
|
+
/**
|
|
234
|
+
* Map one parsed credential document onto the store's credential shape.
|
|
235
|
+
*
|
|
236
|
+
* Pure and exported so the format rules can be tested without a filesystem, and
|
|
237
|
+
* so a later chunk that reads the document from somewhere else (a backup, a
|
|
238
|
+
* pasted blob) reuses the one set of rules instead of growing a second, drifting
|
|
239
|
+
* copy.
|
|
240
|
+
*
|
|
241
|
+
* Returns undefined for every shape it does not recognise, and never throws — see
|
|
242
|
+
* Rule 4 in the module comment. The gate is deliberately narrow: the document must
|
|
243
|
+
* be a JSON object, claudeAiOauth must be an object, and it must carry BOTH a
|
|
244
|
+
* non-empty accessToken and a non-empty refreshToken. An access token alone is not
|
|
245
|
+
* adopted because the store's record is a sign-in, not a bare token: its identity
|
|
246
|
+
* aliases are derived from the refresh token, and a record with an empty one would
|
|
247
|
+
* mint an identity that matches nothing and can never be re-recognised.
|
|
248
|
+
*
|
|
249
|
+
* The MCP trap is handled by construction here: value.claudeAiOauth is addressed
|
|
250
|
+
* directly and no other key of the document is ever traversed, so whatever
|
|
251
|
+
* mcpOAuth holds cannot reach the result.
|
|
252
|
+
*/
|
|
253
|
+
export declare function parseAdoptedClaudeCredential(value: unknown, sourcePath: string): ClaudeCodeAdoptedCredential | undefined;
|
|
254
|
+
/**
|
|
255
|
+
* Read the local Claude Code sign-in; the first usable candidate wins.
|
|
256
|
+
*
|
|
257
|
+
* ONLY call this after the user has explicitly opted in — see the module comment.
|
|
258
|
+
*
|
|
259
|
+
* Never throws and never rejects: an absent file, an unreadable file, a file that
|
|
260
|
+
* is not JSON, and a JSON document of an unrecognised shape all produce
|
|
261
|
+
* undefined, which the card renders as 'unrecognised local sign-in format'. A
|
|
262
|
+
* settings route must not be able to fail because a user's file was mid-write.
|
|
263
|
+
*
|
|
264
|
+
* A candidate that EXISTS but cannot be parsed does not stop the search; the next
|
|
265
|
+
* candidate is tried. That trade-off is stated in {@link claudeCodeCredentialPaths}
|
|
266
|
+
* and the file actually used is reported in the result, so a fallback is always
|
|
267
|
+
* visible rather than silent.
|
|
268
|
+
*/
|
|
269
|
+
export declare function readClaudeCodeCredentials(paths?: readonly string[]): Promise<ClaudeCodeAdoptedCredential | undefined>;
|
|
270
|
+
/**
|
|
271
|
+
* Whether a value carries the adopted marker.
|
|
272
|
+
*
|
|
273
|
+
* The predicate the pool chunk tests a stored account with before deciding whether
|
|
274
|
+
* it may ever be refreshed. It recognises this module's snapshot and nothing else:
|
|
275
|
+
* a plain store credential has no 'adopted' field and must NOT be mistaken for
|
|
276
|
+
* one, because treating a plugin-owned account as a disposable snapshot would
|
|
277
|
+
* discard an account the user added here.
|
|
278
|
+
*/
|
|
279
|
+
export declare function isAdoptedClaudeCredential(value: unknown): value is ClaudeCodeAdoptedCredential;
|
|
280
|
+
/**
|
|
281
|
+
* Whether an adopted credential's access token is already unusable.
|
|
282
|
+
*
|
|
283
|
+
* A structural mirror of the expiry test the OAuth module applies to its own
|
|
284
|
+
* credentials (expiresAt - Date.now() > 0), asked of an adopted snapshot so the
|
|
285
|
+
* pool can refuse it WITHOUT ever reaching for a refresh this module deliberately
|
|
286
|
+
* does not perform. A non-finite expiresAt counts as expired, matching
|
|
287
|
+
* {@link finiteEpochMs}: no field, no validity.
|
|
288
|
+
*
|
|
289
|
+
* now is injectable so a test can reason about a fixed clock.
|
|
290
|
+
*/
|
|
291
|
+
export declare function isAdoptedCredentialExpired(credential: Pick<ClaudeCodeAdoptedCredential, 'credentials'>, now?: number): boolean;
|
|
292
|
+
//# sourceMappingURL=adopt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../../../src/host/claude/adopt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqGG;AAUH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,sBAAsB,CAAA;AAExD,mEAAmE;AACnE,eAAO,MAAM,2BAA2B,sBAAsB,CAAA;AAE9D;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,kBAAkB,CAAA;AAEzD,iFAAiF;AACjF,eAAO,MAAM,6BAA6B,gBAAgB,CAAA;AAE1D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAE1C;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,QAEa,CAAA;AAEzD,oFAAoF;AACpF,MAAM,WAAW,2BAA2B;IAC1C;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;IACtB,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,OAAO,6BAA6B,CAAA;IACrD,gEAAgE;IAChE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,oFAAoF;IACpF,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAA;CACxC;AAED,kEAAkE;AAClE,MAAM,WAAW,4BAA4B;IAC3C,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAA;IAChB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAaD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAIxC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CAKpD;AAqBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,4BAA4B,CAChD,KAAK,GAAE,SAAS,MAAM,EAAgC,GACrD,OAAO,CAAC,4BAA4B,CAAC,CAMvC;AA4CD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,MAAM,GACjB,2BAA2B,GAAG,SAAS,CA+BzC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,GAAE,SAAS,MAAM,EAAgC,GACrD,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAclD;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,2BAA2B,CAG9F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,IAAI,CAAC,2BAA2B,EAAE,aAAa,CAAC,EAC5D,GAAG,GAAE,MAAmB,GACvB,OAAO,CAGT"}
|