@modelprofile.com/authswitch 5.2.0 → 6.1.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/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/accounts.js +3 -2
- package/dist_ts/classes.claudecodeharness.d.ts +13 -4
- package/dist_ts/classes.claudecodeharness.js +36 -11
- package/dist_ts/classes.claudestatus.d.ts +25 -5
- package/dist_ts/classes.claudestatus.js +25 -20
- package/dist_ts/classes.claudetokenrefresh.d.ts +38 -3
- package/dist_ts/classes.claudetokenrefresh.js +80 -21
- package/dist_ts/classes.cli.js +3 -3
- package/dist_ts/classes.credentialstore.d.ts +3 -1
- package/dist_ts/classes.credentialstore.js +2 -2
- package/dist_ts/classes.fileharness.d.ts +16 -5
- package/dist_ts/classes.fileharness.js +31 -9
- package/dist_ts/classes.opencodeanthropicrefresh.d.ts +29 -0
- package/dist_ts/classes.opencodeanthropicrefresh.js +59 -0
- package/dist_ts/classes.opencodeharness.d.ts +40 -0
- package/dist_ts/classes.opencodeharness.js +100 -3
- package/dist_ts/claudehttp.d.ts +14 -0
- package/dist_ts/claudehttp.js +21 -1
- package/dist_ts/interfaces.harness.d.ts +7 -3
- package/package.json +1 -1
- package/readme.md +89 -23
- package/ts/00_commitinfo_data.ts +3 -3
- package/ts/accounts.ts +2 -1
- package/ts/classes.claudecodeharness.ts +37 -12
- package/ts/classes.claudestatus.ts +39 -19
- package/ts/classes.claudetokenrefresh.ts +96 -20
- package/ts/classes.cli.ts +3 -3
- package/ts/classes.credentialstore.ts +2 -2
- package/ts/classes.fileharness.ts +28 -8
- package/ts/classes.opencodeanthropicrefresh.ts +64 -0
- package/ts/classes.opencodeharness.ts +97 -2
- package/ts/claudehttp.ts +22 -0
- package/ts/interfaces.harness.ts +7 -3
|
@@ -2,10 +2,18 @@ import * as plugins from './plugins.js';
|
|
|
2
2
|
import { FileHarness } from './classes.fileharness.js';
|
|
3
3
|
import { CredentialStore, credentialHash, credentialRecord, credentialText, readCredentialDocument, readCredentialRaw } from './classes.credentialstore.js';
|
|
4
4
|
import { HarnessProcesses } from './classes.harnessprocesses.js';
|
|
5
|
+
import { ClaudeAccountStatus } from './classes.claudestatus.js';
|
|
6
|
+
import { CLAUDE_REFRESH_MARGIN_MS } from './classes.claudetokenrefresh.js';
|
|
7
|
+
import { ClaudeLoginRejectedError, ClaudeRateLimitError } from './claudehttp.js';
|
|
5
8
|
import { CodexAccountStatus } from './classes.codexstatus.js';
|
|
9
|
+
import { OpenCodeAnthropicRefresh } from './classes.opencodeanthropicrefresh.js';
|
|
6
10
|
import { writeSecretFileAtomically } from './helpers.js';
|
|
7
11
|
import { beginSavedOpenAiLogin, openCodeCredentialFromLogin } from './classes.login.js';
|
|
8
12
|
import { plainText } from './formatting.js';
|
|
13
|
+
/** Anthropic refused the grant OpenCode's entry holds; no retry and no other account changes that answer. */
|
|
14
|
+
const ANTHROPIC_LOGIN_REJECTED = 'Login expired or was rejected. Log in again with opencode auth login.';
|
|
15
|
+
/** A saved copy is not the login OpenCode uses, so renewing it would rotate a token OpenCode's own entry still holds. */
|
|
16
|
+
const SAVED_ANTHROPIC_EXPIRED = 'This saved Anthropic login\'s access token has expired. authswitch renews the Anthropic login OpenCode has active; activate this one to have it renewed, or log in again with opencode auth login.';
|
|
9
17
|
/** OpenCode owns one login per provider. Replacing a slot never replaces the whole provider set. */
|
|
10
18
|
export class OpenCodeHarness extends FileHarness {
|
|
11
19
|
id = 'opencode';
|
|
@@ -15,20 +23,30 @@ export class OpenCodeHarness extends FileHarness {
|
|
|
15
23
|
liveSwap = false;
|
|
16
24
|
/** Only its OpenAI login reports usage, and a supervisor (AGL) restarts it around a switch, so a watch leaves it alone. */
|
|
17
25
|
autoSwitch = false;
|
|
26
|
+
/** OpenCode re-reads its credential file on every request; only a request already in flight still holds the previous login. */
|
|
27
|
+
runningRetention() {
|
|
28
|
+
return 'They re-read the credential file on every request, but a request already in flight still holds the previous login, and its token refresh can ';
|
|
29
|
+
}
|
|
18
30
|
loginProviders = [{ providerId: 'openai', label: 'OpenAI', flows: ['device'] }];
|
|
19
31
|
store;
|
|
20
32
|
file;
|
|
21
33
|
env;
|
|
22
34
|
status;
|
|
35
|
+
claudeStatus;
|
|
36
|
+
anthropicRefresh;
|
|
23
37
|
processes;
|
|
24
38
|
fetcher;
|
|
39
|
+
now;
|
|
25
40
|
constructor(options = {}) {
|
|
26
41
|
super();
|
|
27
42
|
this.env = options.env ?? process.env;
|
|
28
43
|
this.file = plugins.path.join(options.dataHome ?? (this.env.XDG_DATA_HOME || plugins.path.join(plugins.os.homedir(), '.local', 'share')), 'opencode', 'auth.json');
|
|
29
44
|
this.store = new CredentialStore(this.id, options.stashRoot);
|
|
30
45
|
this.status = new CodexAccountStatus(options.fetch);
|
|
46
|
+
this.claudeStatus = new ClaudeAccountStatus(options.fetch, options.now);
|
|
47
|
+
this.anthropicRefresh = new OpenCodeAnthropicRefresh(options.fetch, options.now);
|
|
31
48
|
this.fetcher = options.fetch;
|
|
49
|
+
this.now = options.now ?? Date.now;
|
|
32
50
|
this.processes = options.processes ?? new HarnessProcesses('opencode');
|
|
33
51
|
}
|
|
34
52
|
/** Every provider entry lives in one file, so its bytes are the whole stability proof. */
|
|
@@ -113,14 +131,93 @@ export class OpenCodeHarness extends FileHarness {
|
|
|
113
131
|
if (readCredentialDocument(this.file).raw !== raw)
|
|
114
132
|
throw new Error('Active login verification failed. The outgoing login remains saved.');
|
|
115
133
|
}
|
|
116
|
-
|
|
117
|
-
|
|
134
|
+
/** The login OpenCode has in a provider slot, read from its file; undefined where the file holds none it can read. */
|
|
135
|
+
activeSlot(slotIdArg) {
|
|
136
|
+
return this.snapshot().accounts.find(account => account.slotId === slotIdArg);
|
|
137
|
+
}
|
|
138
|
+
/** Whether this login's access token is inside Claude Code's five-minute margin, the margin Claude's own logins use. */
|
|
139
|
+
renewalDue(credentialArg) {
|
|
140
|
+
const expires = credentialArg.expires;
|
|
141
|
+
return typeof expires === 'number' && Number.isFinite(expires) && this.now() + CLAUDE_REFRESH_MARGIN_MS >= expires;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Renews OpenCode's active Anthropic login and writes the rotated pair back into OpenCode's own credential file.
|
|
145
|
+
*
|
|
146
|
+
* Nothing is stranded by that write. OpenCode's auth service reads `auth.json` on every `Auth.all()`, `Auth.get()`
|
|
147
|
+
* is that read (1.18.15 @99100961, 1.18.31 @103733929), and its Anthropic provider -- `opencode-anthropic-auth`
|
|
148
|
+
* 0.0.13, since the binary carries no Anthropic OAuth code -- calls the `getAuth()` it was initialised with
|
|
149
|
+
* (@98017331) inside the `fetch` wrapper of every single request. A running OpenCode therefore holds no refresh
|
|
150
|
+
* token in memory and picks up this rotation on its next request, exactly as it picks up its own.
|
|
151
|
+
*
|
|
152
|
+
* The renewal is the only authswitch operation on the store while it runs, and the rotated pair replaces the
|
|
153
|
+
* entry only while OpenCode still holds the refresh token that was sent: a login OpenCode renewed meanwhile is
|
|
154
|
+
* returned as it now stands. The write itself is `apply`'s verified compare-and-swap, which preserves every other
|
|
155
|
+
* provider and replaces the file atomically -- OpenCode writes the same file in place. The slot's switch record
|
|
156
|
+
* follows that write, because an `anthropic` login's identity is its refresh token and this rotation is
|
|
157
|
+
* authswitch's own: without that, the next read would report this write as a different account.
|
|
158
|
+
*/
|
|
159
|
+
renewAnthropic(accountArg, signalArg) {
|
|
160
|
+
return this.store.locked(async () => {
|
|
161
|
+
const current = this.activeSlot(accountArg.slotId) ?? accountArg;
|
|
162
|
+
if (!this.renewalDue(current.credential))
|
|
163
|
+
return current;
|
|
164
|
+
const refreshToken = credentialText(current.credential.refresh);
|
|
165
|
+
if (refreshToken === undefined)
|
|
166
|
+
throw new Error('This Anthropic login holds no refresh token; log in again with opencode auth login.');
|
|
167
|
+
signalArg?.throwIfAborted();
|
|
168
|
+
const tokens = await this.anthropicRefresh.refresh(refreshToken);
|
|
169
|
+
const latest = this.activeSlot(accountArg.slotId);
|
|
170
|
+
if (!latest || credentialText(latest.credential.refresh) !== refreshToken)
|
|
171
|
+
return latest ?? current;
|
|
172
|
+
const renewed = this.inspect({ ...latest.credential, access: tokens.access, refresh: tokens.refresh, expires: tokens.expires }, latest.slotId);
|
|
173
|
+
this.apply(latest.slotId, latest, renewed);
|
|
174
|
+
this.recordRenewal(latest.slotId);
|
|
175
|
+
return renewed;
|
|
176
|
+
}, { signal: signalArg });
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* The subscription and usage of an OpenCode `anthropic` OAuth login.
|
|
180
|
+
*
|
|
181
|
+
* That entry holds the same Claude subscriber grant Claude Code stores, so Claude's own account endpoints answer
|
|
182
|
+
* for it and the account reports real windows instead of no quota API at all. OpenCode keeps no scopes and no
|
|
183
|
+
* account identity with it, so the service decides both. A due access token is renewed first, with OpenCode's own
|
|
184
|
+
* request; a refusal is reported and nothing is written, so the entry OpenCode owns is left exactly as it was.
|
|
185
|
+
*
|
|
186
|
+
* A saved copy is never renewed: OpenCode's entry holds the same refresh token, and rotating it here would leave
|
|
187
|
+
* the login OpenCode actually uses holding a token the service has replaced.
|
|
188
|
+
*/
|
|
189
|
+
async anthropicStatus(accountArg, isActiveArg, optionsArg) {
|
|
190
|
+
let account = accountArg;
|
|
191
|
+
if (this.renewalDue(account.credential)) {
|
|
192
|
+
if (!isActiveArg)
|
|
193
|
+
return this.claudeStatus.unavailable({}, SAVED_ANTHROPIC_EXPIRED);
|
|
194
|
+
try {
|
|
195
|
+
account = await this.renewAnthropic(account, optionsArg.signal);
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
if (optionsArg.signal?.aborted)
|
|
199
|
+
throw error;
|
|
200
|
+
const problem = error instanceof ClaudeLoginRejectedError ? ANTHROPIC_LOGIN_REJECTED
|
|
201
|
+
: error instanceof Error ? error.message : 'the login could not be renewed.';
|
|
202
|
+
return this.claudeStatus.unavailable({}, `Login refresh: ${problem}`, error instanceof ClaudeRateLimitError ? { retryAt: error.retryAt } : undefined);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const accessToken = credentialText(account.credential.access);
|
|
206
|
+
if (accessToken === undefined)
|
|
207
|
+
return this.claudeStatus.unavailable({}, 'This Anthropic login holds no usable access token; log in again with opencode auth login.');
|
|
208
|
+
return this.claudeStatus.read({ accessToken, scopes: [] }, optionsArg);
|
|
209
|
+
}
|
|
210
|
+
async readAccountStatus(id, optionsArg = {}) {
|
|
211
|
+
const active = this.activeCredential(id);
|
|
212
|
+
const account = active ?? this.savedCredential(id);
|
|
118
213
|
if (account.slotId === 'openai' && account.credential.type === 'oauth') {
|
|
119
214
|
const info = this.openAiInfo(account.credential);
|
|
120
215
|
if (!info.accountId)
|
|
121
216
|
return { facts: [], problems: ['The OpenAI login has no account ID for a status lookup.'] };
|
|
122
217
|
return this.status.readCredential(credentialText(account.credential.access), info.accountId, info.plan, optionsArg);
|
|
123
218
|
}
|
|
219
|
+
if (account.slotId === 'anthropic' && account.credential.type === 'oauth')
|
|
220
|
+
return this.anthropicStatus(account, active !== undefined, optionsArg);
|
|
124
221
|
return { facts: [
|
|
125
222
|
{ section: 'Authentication', label: 'Provider', value: account.slotId },
|
|
126
223
|
{ section: 'Authentication', label: 'Login type', value: String(account.credential.type) },
|
|
@@ -128,4 +225,4 @@ export class OpenCodeHarness extends FileHarness {
|
|
|
128
225
|
], problems: [] };
|
|
129
226
|
}
|
|
130
227
|
}
|
|
131
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5vcGVuY29kZWhhcm5lc3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLm9wZW5jb2RlaGFybmVzcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQUUsV0FBVyxFQUFnRCxNQUFNLDBCQUEwQixDQUFDO0FBQ3JHLE9BQU8sRUFBRSxlQUFlLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxzQkFBc0IsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzVKLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzlELE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUV6RCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFXNUMsb0dBQW9HO0FBQ3BHLE1BQU0sT0FBTyxlQUFnQixTQUFRLFdBQVc7SUFDOUIsRUFBRSxHQUFHLFVBQVUsQ0FBQztJQUNoQixLQUFLLEdBQUcsVUFBVSxDQUFDO0lBQ25CLFNBQVMsR0FBRyx3RkFBd0YsQ0FBQztJQUNySCx1SEFBdUg7SUFDdkcsUUFBUSxHQUFHLEtBQUssQ0FBQztJQUNqQywySEFBMkg7SUFDM0csVUFBVSxHQUFHLEtBQUssQ0FBQztJQUNuQixjQUFjLEdBQTRCLENBQUMsRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3RHLEtBQUssQ0FBa0I7SUFDekIsSUFBSSxDQUFTO0lBQ2IsR0FBRyxD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
|
|
228
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5vcGVuY29kZWhhcm5lc3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLm9wZW5jb2RlaGFybmVzcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQUUsV0FBVyxFQUFnRCxNQUFNLDBCQUEwQixDQUFDO0FBQ3JHLE9BQU8sRUFBRSxlQUFlLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxzQkFBc0IsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzVKLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzNFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2pGLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzlELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQ2pGLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUV6RCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFhNUMsNkdBQTZHO0FBQzdHLE1BQU0sd0JBQXdCLEdBQUcsdUVBQXVFLENBQUM7QUFDekcseUhBQXlIO0FBQ3pILE1BQU0sdUJBQXVCLEdBQUcsb01BQW9NLENBQUM7QUFFck8sb0dBQW9HO0FBQ3BHLE1BQU0sT0FBTyxlQUFnQixTQUFRLFdBQVc7SUFDOUIsRUFBRSxHQUFHLFVBQVUs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
|
package/dist_ts/claudehttp.d.ts
CHANGED
|
@@ -7,6 +7,20 @@ export declare const CLAUDE_LOGIN_REJECTED = "Login expired or was rejected. Log
|
|
|
7
7
|
export declare class ClaudeLoginRejectedError extends ClaudeRequestError {
|
|
8
8
|
constructor();
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Where Claude Code 2.1.273 sends an account the service put on hold (`T5e`, bundle offset @190070402). A hold is
|
|
12
|
+
* not a dead login: the service refuses the grant while it lasts and accepts it again once it is lifted.
|
|
13
|
+
*/
|
|
14
|
+
export declare const CLAUDE_ACCOUNT_ON_HOLD_URL = "https://claude.ai/restricted";
|
|
15
|
+
/** The service put this account on hold. The login itself is intact, so it is never remembered as refused. */
|
|
16
|
+
export declare class ClaudeAccountOnHoldError extends ClaudeRequestError {
|
|
17
|
+
constructor();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The OAuth error code a response names, read as Claude Code 2.1.273 reads it (`xc`, @191165290): the `error` field
|
|
21
|
+
* as a string, or the `type` of the object some Anthropic endpoints send it as.
|
|
22
|
+
*/
|
|
23
|
+
export declare const oauthErrorCode: (bodyArg: Record<string, unknown> | null) => string | undefined;
|
|
10
24
|
/** The service refused a request for too many requests. That says nothing about the account's usage or login. */
|
|
11
25
|
export declare class ClaudeRateLimitError extends ClaudeRequestError {
|
|
12
26
|
readonly retryAt: string | null;
|
package/dist_ts/claudehttp.js
CHANGED
|
@@ -10,6 +10,26 @@ export const CLAUDE_LOGIN_REJECTED = 'Login expired or was rejected. Log in agai
|
|
|
10
10
|
export class ClaudeLoginRejectedError extends ClaudeRequestError {
|
|
11
11
|
constructor() { super(CLAUDE_LOGIN_REJECTED); }
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Where Claude Code 2.1.273 sends an account the service put on hold (`T5e`, bundle offset @190070402). A hold is
|
|
15
|
+
* not a dead login: the service refuses the grant while it lasts and accepts it again once it is lifted.
|
|
16
|
+
*/
|
|
17
|
+
export const CLAUDE_ACCOUNT_ON_HOLD_URL = 'https://claude.ai/restricted';
|
|
18
|
+
/** The service put this account on hold. The login itself is intact, so it is never remembered as refused. */
|
|
19
|
+
export class ClaudeAccountOnHoldError extends ClaudeRequestError {
|
|
20
|
+
constructor() { super(`This Claude account is on hold and cannot sign in. View details or appeal: ${CLAUDE_ACCOUNT_ON_HOLD_URL}`); }
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The OAuth error code a response names, read as Claude Code 2.1.273 reads it (`xc`, @191165290): the `error` field
|
|
24
|
+
* as a string, or the `type` of the object some Anthropic endpoints send it as.
|
|
25
|
+
*/
|
|
26
|
+
export const oauthErrorCode = (bodyArg) => {
|
|
27
|
+
const error = bodyArg?.error;
|
|
28
|
+
if (typeof error === 'string')
|
|
29
|
+
return error;
|
|
30
|
+
const type = typeof error === 'object' && error !== null ? error.type : undefined;
|
|
31
|
+
return typeof type === 'string' ? type : undefined;
|
|
32
|
+
};
|
|
13
33
|
/** The service refused a request for too many requests. That says nothing about the account's usage or login. */
|
|
14
34
|
export class ClaudeRateLimitError extends ClaudeRequestError {
|
|
15
35
|
retryAt;
|
|
@@ -80,4 +100,4 @@ export const claudeRequest = async (fetcherArg, requestArg) => {
|
|
|
80
100
|
throw new ClaudeRequestError(`The ${requestArg.subject} service could not be reached.`);
|
|
81
101
|
}
|
|
82
102
|
};
|
|
83
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
103
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhdWRlaHR0cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXVkZWh0dHAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUU3QyxtSEFBbUg7QUFDbkgsTUFBTSxPQUFPLGtCQUFtQixTQUFRLEtBQUs7Q0FBRztBQUVoRCxzSEFBc0g7QUFDdEgsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsMkVBQTJFLENBQUM7QUFFakgsNENBQTRDO0FBQzVDLE1BQU0sT0FBTyx3QkFBeUIsU0FBUSxrQkFBa0I7SUFDOUQsZ0JBQWdCLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztDQUNoRDtBQUVEOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLDBCQUEwQixHQUFHLDhCQUE4QixDQUFDO0FBRXpFLDhHQUE4RztBQUM5RyxNQUFNLE9BQU8sd0JBQXlCLFNBQVEsa0JBQWtCO0lBQzlELGdCQUFnQixLQUFLLENBQUMsOEVBQThFLDBCQUEwQixFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7Q0FDckk7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxPQUF1QyxFQUFzQixFQUFFO0lBQzVGLE1BQU0sS0FBSyxHQUFHLE9BQU8sRUFBRSxLQUFLLENBQUM7SUFDN0IsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDNUMsTUFBTSxJQUFJLEdBQUcsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFFLEtBQWlDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFD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
|
|
@@ -236,9 +236,13 @@ export interface IAuthHarness {
|
|
|
236
236
|
*/
|
|
237
237
|
readonly autoSwitch?: boolean;
|
|
238
238
|
/**
|
|
239
|
-
* The account's live status. It must never activate, switch or clear a login.
|
|
240
|
-
*
|
|
241
|
-
*
|
|
239
|
+
* The account's live status. It must never activate, switch or clear a login.
|
|
240
|
+
*
|
|
241
|
+
* It may renew the tokens of the credential it reads when the provider leaves it no other way to answer, under
|
|
242
|
+
* its store's lock and with a compare-and-swap on the refresh token it sent. A saved copy is always its own to
|
|
243
|
+
* renew -- the Claude Code adapter renews one, because Claude Code's active login is Claude Code's. The active
|
|
244
|
+
* login may only be renewed where the owning harness re-reads its credential file on every request, so that the
|
|
245
|
+
* rotation strands nothing: OpenCode's Anthropic provider does, and authswitch renews that entry.
|
|
242
246
|
*/
|
|
243
247
|
readAccountStatus(accountIdArg: string, optionsArg?: IHarnessStatusOptions): Promise<IHarnessAccountStatus>;
|
|
244
248
|
readonly loginProviders?: IHarnessLoginProvider[];
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -109,8 +109,11 @@ never blocked by a waiting switch; after that the operation fails with nothing
|
|
|
109
109
|
changed. A lock left behind by a Claude Code that died goes stale after its own
|
|
110
110
|
threshold and is taken over, as Claude Code itself would.
|
|
111
111
|
|
|
112
|
-
**
|
|
113
|
-
|
|
112
|
+
**A running OpenCode can still overwrite a switch.** Not by holding the previous login:
|
|
113
|
+
its auth service caches nothing and re-reads `auth.json` on every lookup. The window is a
|
|
114
|
+
request already in flight, which read the previous login before the switch and can write
|
|
115
|
+
that login's own rotation back afterwards -- and OpenCode replaces the whole provider map
|
|
116
|
+
in place rather than atomically. So before `use` and
|
|
114
117
|
before `stash` without `--keep`, authswitch lists OpenCode's own running instances --
|
|
115
118
|
pid, start time and command line -- and offers to stop them:
|
|
116
119
|
|
|
@@ -214,8 +217,20 @@ every other provider, and `stash openai` without `--keep` clears only OpenAI.
|
|
|
214
217
|
When several logins are active, the guide asks which to save; scripts must name
|
|
215
218
|
the provider or account. In the TUI, select an active row before pressing `a` or `c`.
|
|
216
219
|
ChatGPT OAuth accounts display their email and use the same direct status APIs as
|
|
217
|
-
Codex.
|
|
218
|
-
|
|
220
|
+
Codex. An `anthropic` OAuth login holds the same Claude subscriber grant Claude Code
|
|
221
|
+
stores, so it reports Claude's own plan, organization and usage windows through the
|
|
222
|
+
account endpoints described under **Claude Code**; OpenCode keeps no scopes and no
|
|
223
|
+
account identity with that entry, so both are left to the service. An access token inside
|
|
224
|
+
Claude Code's five-minute margin is renewed first, with the request OpenCode's own
|
|
225
|
+
Anthropic provider sends (`opencode-anthropic-auth`: `console.anthropic.com`, Claude
|
|
226
|
+
Code's public client, no scope), and the rotated pair is written back into `auth.json`
|
|
227
|
+
atomically, preserving every other provider. Nothing is stranded by that write: OpenCode's
|
|
228
|
+
auth service re-reads `auth.json` on every lookup and its Anthropic provider asks for the
|
|
229
|
+
credential again inside every request, so a running instance picks up the rotation exactly
|
|
230
|
+
as it picks up its own. A refusal is reported and nothing is written, and a saved copy is
|
|
231
|
+
never renewed, because OpenCode's own entry holds the same refresh token.
|
|
232
|
+
API keys and opaque provider tokens have no reliable email, so their
|
|
233
|
+
labels contain the provider and a SHA-256 fingerprint. Their quota/billing information is
|
|
219
234
|
explicitly unavailable. `OPENCODE_AUTH_CONTENT` overrides the file and blocks file
|
|
220
235
|
management. Provider configuration and environment credentials remain managed by OpenCode.
|
|
221
236
|
|
|
@@ -254,19 +269,27 @@ authswitch does not infer them from account creation or token expiry dates. The
|
|
|
254
269
|
Claude Code adapter declares that, so `limits` explains it once for the provider
|
|
255
270
|
instead of per account.
|
|
256
271
|
|
|
257
|
-
Nothing but Claude Code refreshes a Claude login, so a saved one stops being readable
|
|
258
|
-
|
|
272
|
+
Nothing but Claude Code refreshes a Claude login, so a saved one stops being readable a
|
|
273
|
+
few hours after it was saved. Reading a **saved, inactive** account's status therefore
|
|
259
274
|
refreshes it first, exactly as Claude Code would: when its access token expires within
|
|
260
275
|
five minutes, authswitch exchanges the stored refresh token at Claude's token endpoint,
|
|
261
276
|
keeps every other field of the login, and writes the result only while the saved record
|
|
262
|
-
still holds the refresh token it sent. The
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
login
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
277
|
+
still holds the refresh token it sent. The request is the one Claude Code sends, down to
|
|
278
|
+
the scopes: a login of Claude Code's own OAuth client is renewed with Claude Code's
|
|
279
|
+
current scope set plus the project scopes the login carries -- not with the set the
|
|
280
|
+
login happens to be stored under, which can be an older or wider one the service no
|
|
281
|
+
longer accepts -- and a set the service refuses as `invalid_scope` is sent once more
|
|
282
|
+
with the stored scopes. A login that names its own OAuth client keeps its stored scopes,
|
|
283
|
+
because only that client's grant knows them. A login that is neither one of Claude
|
|
284
|
+
Code's subscriber logins nor stored with a plan is not sent at all. The refresh holds
|
|
285
|
+
the account store's lock, so a switch started at the same time waits for it and then
|
|
286
|
+
activates the refreshed login. The **active** login is never refreshed -- Claude Code
|
|
287
|
+
owns it, and two parties refreshing one login can invalidate the grant. A refusal is
|
|
288
|
+
reported, never worked around -- a rejected grant says so and says what fixes it
|
|
289
|
+
(below), and a service failure, an unreachable service or an unsupported response leave
|
|
290
|
+
the saved login untouched. Requests carry `User-Agent: authswitch/<version>`, and HTTP
|
|
291
|
+
429 is reported as rate limiting with the service's retry time -- never as an exhausted
|
|
292
|
+
or expired account.
|
|
270
293
|
|
|
271
294
|
Claude Code also rotates the refresh token of the login it **is** running on, so reading the
|
|
272
295
|
accounts (`list`, `limits`, `active`, `current`, `watch`, the dashboard) mirrors that login
|
|
@@ -279,14 +302,57 @@ saved implicitly; `stash` is what saves a login. An installation whose native lo
|
|
|
279
302
|
authswitch cannot read mirrors nothing, and a read waits at most a second for a lock a
|
|
280
303
|
switch or Claude Code holds before leaving the saved copy to the next read.
|
|
281
304
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
that
|
|
289
|
-
new
|
|
305
|
+
An account the service has put **on hold** is not a dead login: the hold refuses the grant
|
|
306
|
+
while it lasts and the same login works again once it is lifted, so such an account keeps
|
|
307
|
+
its stored plan, says that it is on hold and where to appeal, and is asked again on the
|
|
308
|
+
next read.
|
|
309
|
+
|
|
310
|
+
A grant the sign-in service refused is remembered in the saved record itself, as a hash
|
|
311
|
+
of the request that was refused -- the refresh token, the client and the scopes, never
|
|
312
|
+
the token itself -- so a new authswitch run, a restarted watch or a second dashboard
|
|
313
|
+
does not replay a dead login. Because the hash covers the request and not only the
|
|
314
|
+
token, a release that changes how authswitch asks gives every such login one honest
|
|
315
|
+
attempt under the new derivation, while a refusal of the request authswitch still sends
|
|
316
|
+
stays remembered. Saving that login again clears it, as does any refresh that replaces
|
|
317
|
+
the saved credential. Such a login reports `Login expired or was rejected. Log in again
|
|
318
|
+
with Claude Code and save it. Claude Code rotates a login's refresh token as it uses it,
|
|
319
|
+
and the service can refuse the older one a saved copy still holds once that login has
|
|
320
|
+
been replaced outside authswitch; authswitch claude stash --keep saves the new one.`
|
|
321
|
+
|
|
322
|
+
Each `n/a` in a Claude row has a reason in the footnote under the table, and each
|
|
323
|
+
reason names what to do:
|
|
324
|
+
|
|
325
|
+
- `Login refresh: Login expired or was rejected.` -- the sign-in service refused the
|
|
326
|
+
saved refresh token itself. Log in again in Claude Code for that account and run
|
|
327
|
+
`authswitch claude stash --keep`; nothing else fixes it.
|
|
328
|
+
- `Login refresh: This Claude account is on hold and cannot sign in.` -- the account,
|
|
329
|
+
not the login. Appeal at the address in the message; the saved login is kept and is
|
|
330
|
+
asked again on the next read.
|
|
331
|
+
- `Login refresh: This saved login has no refresh token, and no subscriber scope or
|
|
332
|
+
plan to refresh with.` -- the saved record is missing what a refresh is made of.
|
|
333
|
+
Save the login again.
|
|
334
|
+
- `Login refresh: this saved login's access token has expired and cannot be renewed
|
|
335
|
+
for this installation.` -- authswitch cannot read Claude Code's own files here (the
|
|
336
|
+
macOS Keychain, or an incomplete native login), so it cannot prove this login is not
|
|
337
|
+
the active one, and never refreshes a login that might be.
|
|
338
|
+
- `Login refresh: The Claude sign-in service returned HTTP ...`, `... could not be
|
|
339
|
+
reached.`, `... timed out.`, `... is rate limiting requests (HTTP 429)` -- the
|
|
340
|
+
service, not the login. The saved login is untouched; read again later.
|
|
341
|
+
- `Profile: ...` or `Usage: ...` -- the account endpoints, asked with a token the
|
|
342
|
+
refresh had just accepted. `Profile: Login expired or was rejected.` means the access
|
|
343
|
+
token itself was refused; the other wordings are the service, as above.
|
|
344
|
+
- `Claude returned a different account or organization` -- the answer was about another
|
|
345
|
+
account and was discarded whole, rather than shown under this account's name.
|
|
346
|
+
- `Claude profile response is unsupported` or `Claude usage response is unsupported` --
|
|
347
|
+
the service answered in a shape authswitch does not read. Nothing is guessed from a
|
|
348
|
+
response it does not understand.
|
|
349
|
+
|
|
350
|
+
An OpenCode `anthropic` row reads the same endpoints and so shows the same reasons. Its
|
|
351
|
+
renewal adds `Login refresh: Login expired or was rejected. Log in again with opencode
|
|
352
|
+
auth login.`, which is Anthropic refusing the refresh token OpenCode's entry holds -- no
|
|
353
|
+
retry changes that, and the refusal is never remembered, because OpenCode owns that entry.
|
|
354
|
+
`This saved Anthropic login's access token has expired.` is a stashed copy, which is left
|
|
355
|
+
alone so that the login OpenCode uses keeps a refresh token the service still accepts.
|
|
290
356
|
|
|
291
357
|
OpenCode and Claude saved records are separate owner-only files under
|
|
292
358
|
`~/.authswitch/opencode` and `~/.authswitch/claude`. Emails are accepted as account
|
|
@@ -982,7 +1048,7 @@ Account identity comes from the `id_token` inside the credential — the email c
|
|
|
982
1048
|
|
|
983
1049
|
**Other Codex clients keep running.** Stopping the managed app-server does not stop an editor extension that spawned its own. Close it, or expect it to keep using the credential it already loaded.
|
|
984
1050
|
|
|
985
|
-
**A running OpenCode can undo a switch.**
|
|
1051
|
+
**A running OpenCode can undo a switch.** Its auth service keeps no login in memory -- every lookup re-reads `auth.json` -- but a request already in flight, which read the previous login before the switch, can write that login's own rotation back afterwards, over a provider map OpenCode replaces in place. Authswitch lists those instances, offers to stop them, warns when any keep running, and detects the overwrite afterwards — but it cannot prevent it while they run. Restart them after a switch. A running Claude Code picks the switch up instead; its guarantee rests on the behaviour and lock protocol verified against Claude Code 2.1.273, and `authswitch claude active` still reports a login that changed outside authswitch.
|
|
986
1052
|
|
|
987
1053
|
**The Codex stash is keyed by email.** Two Codex workspaces with the same email
|
|
988
1054
|
cannot both be saved under that key. Their account IDs are distinguished during
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* autocreated commitinfo by @push.rocks/commitinfo
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
|
-
name:
|
|
6
|
-
version:
|
|
7
|
-
description:
|
|
5
|
+
name: '@modelprofile.com/authswitch',
|
|
6
|
+
version: '6.1.0',
|
|
7
|
+
description: 'Manage Codex, OpenCode and Claude Code accounts with guided switching and live usage status'
|
|
8
8
|
}
|
package/ts/accounts.ts
CHANGED
|
@@ -239,7 +239,8 @@ const STATUS_LOOKUP_CONCURRENCY = 4;
|
|
|
239
239
|
* Bounded status lookups: at most four accounts at a time, started in order, each handed the caller's signal.
|
|
240
240
|
* A lookup that fails reports undefined; once the signal aborts, no further lookup starts. A callback that throws
|
|
241
241
|
* rejects the call, and no other lookup starts after it. No lookup activates, switches or clears a login, though an
|
|
242
|
-
* adapter may renew the tokens of the
|
|
242
|
+
* adapter may renew the tokens of the credential it reads, saved or active, on that method's terms
|
|
243
|
+
* (`IAuthHarness.readAccountStatus`).
|
|
243
244
|
*/
|
|
244
245
|
const lookupStatuses = async (
|
|
245
246
|
harnessArg: IAuthHarness,
|
|
@@ -2,9 +2,9 @@ import * as plugins from './plugins.js';
|
|
|
2
2
|
import { FileHarness, type IFileAccount, type IFileHarnessSnapshot } from './classes.fileharness.js';
|
|
3
3
|
import { CredentialStore, credentialHash, credentialRecord, credentialText, readCredentialDocument, readCredentialRaw, type IStoredCredential } from './classes.credentialstore.js';
|
|
4
4
|
import { HarnessProcesses } from './classes.harnessprocesses.js';
|
|
5
|
-
import { ClaudeAccountStatus } from './classes.claudestatus.js';
|
|
5
|
+
import { ClaudeAccountStatus, type IClaudeLogin } from './classes.claudestatus.js';
|
|
6
6
|
import { ClaudeCodeLocks } from './classes.claudecodelocks.js';
|
|
7
|
-
import { ClaudeTokenRefresh, type IClaudeTokens } from './classes.claudetokenrefresh.js';
|
|
7
|
+
import { claudeGrant, ClaudeTokenRefresh, grantScope, type IClaudeTokens } from './classes.claudetokenrefresh.js';
|
|
8
8
|
import { CLAUDE_LOGIN_REJECTED, ClaudeLoginRejectedError, ClaudeRateLimitError } from './claudehttp.js';
|
|
9
9
|
import { writeSecretFileAtomically } from './helpers.js';
|
|
10
10
|
import type { IHarnessAccountStatus, IHarnessProcessControl, IHarnessState, IHarnessStatusOptions } from './interfaces.harness.js';
|
|
@@ -160,8 +160,33 @@ export class ClaudeCodeHarness extends FileHarness {
|
|
|
160
160
|
throw new Error('Claude Code switch failed while updating account metadata and was rolled back. The outgoing login remains saved; check authswitch claude doctor.');
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
|
-
/**
|
|
164
|
-
|
|
163
|
+
/**
|
|
164
|
+
* The hash that identifies a refused sign-in, so it is remembered without keeping anything of the login.
|
|
165
|
+
*
|
|
166
|
+
* A refusal is about one request: the refresh token it carried, and the client and scopes authswitch derived for
|
|
167
|
+
* it. Binding all three means a login keeps its refusal for as long as authswitch would send the same request
|
|
168
|
+
* again, and that a release which changes the derivation -- adopting a scope set Claude Code changed, say -- gives
|
|
169
|
+
* every such login one honest attempt under the new one instead of repeating a verdict its request no longer earns.
|
|
170
|
+
*/
|
|
171
|
+
private grantKey(oauthArg: Record<string, unknown>): string {
|
|
172
|
+
const grant = claudeGrant(oauthArg);
|
|
173
|
+
return credentialHash(JSON.stringify([credentialText(oauthArg.refreshToken) ?? '', grant?.clientId ?? '', grant === null ? '' : grantScope(grant.scopes)]));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** The login a status lookup asks with: its token, and what this store knows about it. */
|
|
177
|
+
private login(accountArg: IFileAccount): IClaudeLogin {
|
|
178
|
+
const oauth = credentialRecord(accountArg.credential.claudeAiOauth);
|
|
179
|
+
const account = credentialRecord(accountArg.credential.oauthAccount);
|
|
180
|
+
const accountUuid = credentialText(account.accountUuid);
|
|
181
|
+
const organizationUuid = credentialText(account.organizationUuid);
|
|
182
|
+
const plan = credentialText(oauth.subscriptionType);
|
|
183
|
+
return {
|
|
184
|
+
accessToken: credentialText(oauth.accessToken) ?? '',
|
|
185
|
+
scopes: Array.isArray(oauth.scopes) ? oauth.scopes.filter((scope): scope is string => typeof scope === 'string') : [],
|
|
186
|
+
...(accountUuid !== undefined && organizationUuid !== undefined ? { identity: { accountUuid, organizationUuid } } : {}),
|
|
187
|
+
...(plan === undefined ? {} : { plan }),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
165
190
|
|
|
166
191
|
/**
|
|
167
192
|
* The harness's accounts, with the saved copy of the active login brought up to date first.
|
|
@@ -226,28 +251,28 @@ export class ClaudeCodeHarness extends FileHarness {
|
|
|
226
251
|
* is due is refreshed first; when that fails, the status says why and keeps the stored plan, and the saved login is
|
|
227
252
|
* left exactly as it was.
|
|
228
253
|
*
|
|
229
|
-
* A refresh is only ever sent for a login the native files prove is not the active one (`nativeView`), and a
|
|
230
|
-
* the service already
|
|
254
|
+
* A refresh is only ever sent for a login the native files prove is not the active one (`nativeView`), and a request
|
|
255
|
+
* the service already refused is not sent again while the saved record would produce the same one (`grantKey`).
|
|
231
256
|
*/
|
|
232
257
|
public async readAccountStatus(id: string, optionsArg: IHarnessStatusOptions = {}): Promise<IHarnessAccountStatus> {
|
|
233
|
-
const read = (accountArg: IFileAccount) =>
|
|
234
|
-
this.status.read(credentialRecord(accountArg.credential.claudeAiOauth), credentialRecord(accountArg.credential.oauthAccount), optionsArg);
|
|
258
|
+
const read = (accountArg: IFileAccount) => this.status.read(this.login(accountArg), optionsArg);
|
|
235
259
|
const view = this.nativeView(id);
|
|
236
260
|
if (view.active) return read(view.active);
|
|
237
261
|
const saved = this.savedCredential(id);
|
|
262
|
+
const login = this.login(saved);
|
|
238
263
|
const oauth = credentialRecord(saved.credential.claudeAiOauth);
|
|
239
264
|
if (!this.tokens.due(oauth)) return read(saved);
|
|
240
265
|
if (view.unavailable !== null) {
|
|
241
|
-
return this.status.unavailable(
|
|
266
|
+
return this.status.unavailable(login, `Login refresh: this saved login's access token has expired and cannot be renewed for this installation. ${view.unavailable}`);
|
|
242
267
|
}
|
|
243
|
-
if (this.store.read(id).rejectedGrant === this.grantKey(oauth)) return this.status.unavailable(
|
|
268
|
+
if (this.store.read(id).rejectedGrant === this.grantKey(oauth)) return this.status.unavailable(login, `Login refresh: ${SAVED_LOGIN_REJECTED}`);
|
|
244
269
|
let refreshed: IFileAccount;
|
|
245
270
|
try { refreshed = await this.refreshSaved(id, optionsArg.signal); }
|
|
246
271
|
catch (error) {
|
|
247
272
|
if (optionsArg.signal?.aborted) throw error;
|
|
248
273
|
const problem = error instanceof ClaudeLoginRejectedError ? SAVED_LOGIN_REJECTED
|
|
249
274
|
: error instanceof Error ? error.message : 'the saved login could not be refreshed.';
|
|
250
|
-
return this.status.unavailable(
|
|
275
|
+
return this.status.unavailable(login, `Login refresh: ${problem}`,
|
|
251
276
|
error instanceof ClaudeRateLimitError ? { retryAt: error.retryAt } : undefined);
|
|
252
277
|
}
|
|
253
278
|
return read(refreshed);
|
|
@@ -260,7 +285,7 @@ export class ClaudeCodeHarness extends FileHarness {
|
|
|
260
285
|
* became active meanwhile belongs to Claude Code and is returned as it is, one in an installation that can no
|
|
261
286
|
* longer be read is returned unrefreshed, and one another refresh already renewed is not refreshed twice. The new
|
|
262
287
|
* tokens replace the saved ones only while the record still holds the refresh token that was sent, the
|
|
263
|
-
* compare-and-swap Claude Code 2.1.273 applies to its own store (`$fn`, @
|
|
288
|
+
* compare-and-swap Claude Code 2.1.273 applies to its own store (`$fn`, @191212749).
|
|
264
289
|
*/
|
|
265
290
|
private refreshSaved(id: string, signal?: AbortSignal): Promise<IFileAccount> {
|
|
266
291
|
return this.store.locked(async () => {
|