opencode-multi-account-core 0.2.13 → 0.2.15

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/index.d.ts CHANGED
@@ -1,5 +1,21 @@
1
1
  import * as v from 'valibot';
2
2
 
3
+ type ClaimsMap = Record<string, {
4
+ pid: number;
5
+ at: number;
6
+ }>;
7
+ interface ClaimsManager {
8
+ readClaims(): Promise<ClaimsMap>;
9
+ writeClaim(accountId: string): Promise<void>;
10
+ releaseClaim(accountId: string): Promise<void>;
11
+ isClaimedByOther(claims: ClaimsMap, accountId: string | undefined): boolean;
12
+ }
13
+ declare function createClaimsManager(filename?: string): ClaimsManager;
14
+ declare function readClaims(): Promise<ClaimsMap>;
15
+ declare function writeClaim(accountId: string): Promise<void>;
16
+ declare function releaseClaim(accountId: string): Promise<void>;
17
+ declare function isClaimedByOther(claims: ClaimsMap, accountId: string | undefined): boolean;
18
+
3
19
  declare const OAuthCredentialsSchema: v.ObjectSchema<{
4
20
  readonly type: v.LiteralSchema<"oauth", undefined>;
5
21
  readonly refresh: v.StringSchema<undefined>;
@@ -222,8 +238,12 @@ interface RuntimeFactoryLike {
222
238
  }
223
239
  interface AccountManagerDependencies {
224
240
  providerAuthId: string;
241
+ getConfig?: () => Pick<PluginConfig, "soft_quota_threshold_percent" | "cross_process_claims" | "account_selection_strategy" | "max_consecutive_auth_failures" | "rate_limit_min_backoff_ms">;
225
242
  isTokenExpired: (account: Pick<ManagedAccount, "accessToken" | "expiresAt">) => boolean;
226
243
  refreshToken: (currentRefreshToken: string, accountId: string, client: PluginClient) => Promise<TokenRefreshResult>;
244
+ readClaims?: () => Promise<ClaimsMap>;
245
+ writeClaim?: (accountId: string) => Promise<void>;
246
+ isClaimedByOther?: (claims: ClaimsMap, accountId: string | undefined) => boolean;
227
247
  }
228
248
  interface AccountManagerInstance {
229
249
  initialize(currentAuth: OAuthCredentials, client?: PluginClient): Promise<void>;
@@ -259,21 +279,23 @@ interface AccountManagerClass {
259
279
  }
260
280
  declare function createAccountManagerForProvider(dependencies: AccountManagerDependencies): AccountManagerClass;
261
281
 
262
- type ClaimsMap = Record<string, {
263
- pid: number;
264
- at: number;
265
- }>;
266
- declare function readClaims(): Promise<ClaimsMap>;
267
- declare function writeClaim(accountId: string): Promise<void>;
268
- declare function releaseClaim(accountId: string): Promise<void>;
269
- declare function isClaimedByOther(claims: ClaimsMap, accountId: string | undefined): boolean;
270
-
271
282
  type CoreConfig = Pick<PluginConfig, "quiet_mode" | "debug">;
283
+ interface ConfigLoader {
284
+ getConfig(): PluginConfig;
285
+ loadConfig(): Promise<PluginConfig>;
286
+ resetConfigCache(): void;
287
+ updateConfigField<K extends keyof PluginConfig>(key: K, value: PluginConfig[K]): Promise<void>;
288
+ }
289
+ declare function createConfigLoader(filename?: string): ConfigLoader;
272
290
  declare function initCoreConfig(filename: string): void;
273
291
  declare function loadConfig(): Promise<PluginConfig>;
274
292
  declare function getConfig(): PluginConfig;
275
293
  declare function resetConfigCache(): void;
276
- declare function setConfigGetter(getter: () => PluginConfig): void;
294
+ /**
295
+ * @deprecated Provider-scoped config should use createConfigLoader() instead.
296
+ * Kept as a no-op for backward compatibility with external consumers.
297
+ */
298
+ declare function setConfigGetter(_getter: () => PluginConfig): void;
277
299
  declare function updateConfigField<K extends keyof PluginConfig>(key: K, value: PluginConfig[K]): Promise<void>;
278
300
 
279
301
  /**
@@ -566,4 +588,4 @@ declare class CascadeStateManager {
566
588
  getSnapshot(): CascadeState | null;
567
589
  }
568
590
 
569
- export { ACCOUNTS_FILENAME, ANSI, type AccountManagerClass, type AccountManagerDependencies, type AccountManagerInstance, type AccountSelectionStrategy, AccountSelectionStrategySchema, type AccountStorage, AccountStorageSchema, AccountStore, type BuildFailoverPlanOptions, type CascadeState, CascadeStateManager, type ChainConfig, ChainConfigSchema, type ChainEntryConfig, ChainEntryConfigSchema, type ClaimsMap, type CoreConfig, type CredentialRefreshPatch, CredentialRefreshPatchSchema, type DiskCredentials, type ExecutorAccountManager, type ExecutorDependencies, type ExecutorRuntimeFactory, type FailoverCandidate, type FailoverPlan, type FailoverSkip, type KeyAction, type ManagedAccount, type MenuItem, type OAuthAdapter, type OAuthAdapterPlanLabels, type OAuthAdapterTransformConfig, type OAuthCredentials, OAuthCredentialsSchema, type PluginClient, type PluginConfig, PluginConfigSchema, type PoolChainConfig, PoolChainConfigSchema, type PoolConfig, PoolConfigSchema, PoolManager, type ProactiveRefreshDependencies, type ProactiveRefreshQueueClass, type ProactiveRefreshQueueInstance, type ProfileData, type RateLimitAccountManager, type RateLimitDependencies, type RuntimeFactoryLike, type SelectOptions, type StoredAccount, StoredAccountSchema, TokenRefreshError, type TokenRefreshResult, type UsageLimitEntry, UsageLimitEntrySchema, type UsageLimits, UsageLimitsSchema, anthropicOAuthAdapter, confirm, createAccountManagerForProvider, createExecutorForProvider, createMinimalClient, createProactiveRefreshQueueForProvider, createRateLimitHandlers, debugLog, deduplicateAccounts, formatWaitTime, getAccountLabel, getClearedOAuthBody, getConfig, getConfigDir, getErrorCode, initCoreConfig, isClaimedByOther, isTTY, isTokenRefreshError, loadAccounts, loadConfig, loadPoolChainConfig, migrateFromAuthJson, openAIOAuthAdapter, parseKey, readClaims, readStorageFromDisk, releaseClaim, resetConfigCache, savePoolChainConfig, select, setAccountsFilename, setConfigGetter, showToast, sleep, updateConfigField, withDirectoryLock, writeClaim };
591
+ export { ACCOUNTS_FILENAME, ANSI, type AccountManagerClass, type AccountManagerDependencies, type AccountManagerInstance, type AccountSelectionStrategy, AccountSelectionStrategySchema, type AccountStorage, AccountStorageSchema, AccountStore, type BuildFailoverPlanOptions, type CascadeState, CascadeStateManager, type ChainConfig, ChainConfigSchema, type ChainEntryConfig, ChainEntryConfigSchema, type ClaimsManager, type ClaimsMap, type ConfigLoader, type CoreConfig, type CredentialRefreshPatch, CredentialRefreshPatchSchema, type DiskCredentials, type ExecutorAccountManager, type ExecutorDependencies, type ExecutorRuntimeFactory, type FailoverCandidate, type FailoverPlan, type FailoverSkip, type KeyAction, type ManagedAccount, type MenuItem, type OAuthAdapter, type OAuthAdapterPlanLabels, type OAuthAdapterTransformConfig, type OAuthCredentials, OAuthCredentialsSchema, type PluginClient, type PluginConfig, PluginConfigSchema, type PoolChainConfig, PoolChainConfigSchema, type PoolConfig, PoolConfigSchema, PoolManager, type ProactiveRefreshDependencies, type ProactiveRefreshQueueClass, type ProactiveRefreshQueueInstance, type ProfileData, type RateLimitAccountManager, type RateLimitDependencies, type RuntimeFactoryLike, type SelectOptions, type StoredAccount, StoredAccountSchema, TokenRefreshError, type TokenRefreshResult, type UsageLimitEntry, UsageLimitEntrySchema, type UsageLimits, UsageLimitsSchema, anthropicOAuthAdapter, confirm, createAccountManagerForProvider, createClaimsManager, createConfigLoader, createExecutorForProvider, createMinimalClient, createProactiveRefreshQueueForProvider, createRateLimitHandlers, debugLog, deduplicateAccounts, formatWaitTime, getAccountLabel, getClearedOAuthBody, getConfig, getConfigDir, getErrorCode, initCoreConfig, isClaimedByOther, isTTY, isTokenRefreshError, loadAccounts, loadConfig, loadPoolChainConfig, migrateFromAuthJson, openAIOAuthAdapter, parseKey, readClaims, readStorageFromDisk, releaseClaim, resetConfigCache, savePoolChainConfig, select, setAccountsFilename, setConfigGetter, showToast, sleep, updateConfigField, withDirectoryLock, writeClaim };
package/dist/index.js CHANGED
@@ -102,79 +102,85 @@ function isTokenRefreshError(error) {
102
102
  // src/config.ts
103
103
  var DEFAULT_CONFIG_FILENAME = "multiauth-config.json";
104
104
  var DEFAULT_CONFIG = v2.parse(PluginConfigSchema, {});
105
- var configFilename = DEFAULT_CONFIG_FILENAME;
106
- var cachedConfig = null;
107
- var externalConfigGetter = null;
108
105
  function getConfigDir() {
109
106
  return process.env.OPENCODE_CONFIG_DIR || join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "opencode");
110
107
  }
111
- function getConfigPath() {
112
- return join(getConfigDir(), configFilename);
113
- }
114
108
  function parseConfig(raw) {
115
109
  const result = v2.safeParse(PluginConfigSchema, raw);
116
110
  return result.success ? result.output : DEFAULT_CONFIG;
117
111
  }
118
- function initCoreConfig(filename) {
119
- configFilename = filename || DEFAULT_CONFIG_FILENAME;
120
- cachedConfig = null;
121
- }
122
- async function loadConfig() {
123
- if (cachedConfig) return cachedConfig;
124
- const path = getConfigPath();
125
- try {
126
- const content = await fs.readFile(path, "utf-8");
127
- cachedConfig = parseConfig(JSON.parse(content));
128
- } catch {
129
- cachedConfig = DEFAULT_CONFIG;
112
+ function createConfigLoader(filename = DEFAULT_CONFIG_FILENAME) {
113
+ let cachedConfig = null;
114
+ function getConfigPath() {
115
+ return join(getConfigDir(), filename);
130
116
  }
131
- return cachedConfig;
132
- }
133
- function getConfig() {
134
- if (cachedConfig) return cachedConfig;
135
- if (externalConfigGetter && externalConfigGetter !== getConfig) {
117
+ async function loadConfig2() {
118
+ if (cachedConfig) return cachedConfig;
119
+ const path = getConfigPath();
136
120
  try {
137
- return parseConfig(externalConfigGetter());
121
+ const content = await fs.readFile(path, "utf-8");
122
+ cachedConfig = parseConfig(JSON.parse(content));
138
123
  } catch {
139
- return DEFAULT_CONFIG;
124
+ cachedConfig = DEFAULT_CONFIG;
140
125
  }
126
+ return cachedConfig;
141
127
  }
142
- return DEFAULT_CONFIG;
143
- }
144
- function resetConfigCache() {
145
- cachedConfig = null;
146
- }
147
- function setConfigGetter(getter) {
148
- if (getter === getConfig) {
149
- return;
128
+ function getConfig2() {
129
+ return cachedConfig ?? DEFAULT_CONFIG;
150
130
  }
151
- externalConfigGetter = getter;
152
- }
153
- async function updateConfigField(key, value) {
154
- const path = getConfigPath();
155
- let existing = {};
156
- try {
157
- const content2 = await fs.readFile(path, "utf-8");
158
- existing = JSON.parse(content2);
159
- } catch {
131
+ function resetConfigCache2() {
132
+ cachedConfig = null;
160
133
  }
161
- existing[key] = value;
162
- await fs.mkdir(dirname(path), { recursive: true });
163
- const content = `${JSON.stringify(existing, null, 2)}
164
- `;
165
- const tempPath = `${path}.${randomBytes(8).toString("hex")}.tmp`;
166
- try {
167
- await fs.writeFile(tempPath, content, "utf-8");
168
- await fs.rename(tempPath, path);
169
- } catch (error) {
134
+ async function updateConfigField2(key, value) {
135
+ const path = getConfigPath();
136
+ let existing = {};
170
137
  try {
171
- await fs.unlink(tempPath);
138
+ const content2 = await fs.readFile(path, "utf-8");
139
+ existing = JSON.parse(content2);
172
140
  } catch {
173
141
  }
174
- throw error;
142
+ existing[key] = value;
143
+ await fs.mkdir(dirname(path), { recursive: true });
144
+ const content = `${JSON.stringify(existing, null, 2)}
145
+ `;
146
+ const tempPath = `${path}.${randomBytes(8).toString("hex")}.tmp`;
147
+ try {
148
+ await fs.writeFile(tempPath, content, "utf-8");
149
+ await fs.rename(tempPath, path);
150
+ } catch (error) {
151
+ try {
152
+ await fs.unlink(tempPath);
153
+ } catch {
154
+ }
155
+ throw error;
156
+ }
157
+ resetConfigCache2();
158
+ await loadConfig2();
175
159
  }
176
- cachedConfig = null;
177
- await loadConfig();
160
+ return {
161
+ getConfig: getConfig2,
162
+ loadConfig: loadConfig2,
163
+ resetConfigCache: resetConfigCache2,
164
+ updateConfigField: updateConfigField2
165
+ };
166
+ }
167
+ var defaultLoader = createConfigLoader();
168
+ function initCoreConfig(filename) {
169
+ defaultLoader = createConfigLoader(filename);
170
+ }
171
+ async function loadConfig() {
172
+ return defaultLoader.loadConfig();
173
+ }
174
+ function getConfig() {
175
+ return defaultLoader.getConfig();
176
+ }
177
+ function resetConfigCache() {
178
+ defaultLoader.resetConfigCache();
179
+ }
180
+ function setConfigGetter(_getter) {
181
+ }
182
+ async function updateConfigField(key, value) {
183
+ await defaultLoader.updateConfigField(key, value);
178
184
  }
179
185
 
180
186
  // src/utils.ts
@@ -253,8 +259,8 @@ function getClearedOAuthBody() {
253
259
  // src/claims.ts
254
260
  var CLAIMS_FILENAME = "multiauth-claims.json";
255
261
  var CLAIM_EXPIRY_MS = 6e4;
256
- function getClaimsPath() {
257
- return join3(getConfigDir2(), CLAIMS_FILENAME);
262
+ function getClaimsPath(filename) {
263
+ return join3(getConfigDir2(), filename);
258
264
  }
259
265
  function isClaimShape(value) {
260
266
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
@@ -301,8 +307,7 @@ function cleanClaims(claims, now) {
301
307
  }
302
308
  return { cleaned, changed };
303
309
  }
304
- async function writeClaimsFile(claims) {
305
- const path = getClaimsPath();
310
+ async function writeClaimsFile(path, claims) {
306
311
  const tempPath = `${path}.${randomBytes2(6).toString("hex")}.tmp`;
307
312
  await fs2.mkdir(dirname2(path), { recursive: true });
308
313
  try {
@@ -316,54 +321,78 @@ async function writeClaimsFile(claims) {
316
321
  throw error;
317
322
  }
318
323
  }
319
- async function readClaims() {
320
- try {
321
- const data = await fs2.readFile(getClaimsPath(), "utf-8");
322
- const parsed = parseClaims(data);
323
- const now = Date.now();
324
- const { cleaned, changed } = cleanClaims(parsed, now);
325
- if (changed) {
326
- try {
327
- await writeClaimsFile(cleaned);
328
- } catch {
324
+ function createClaimsManager(filename = CLAIMS_FILENAME) {
325
+ async function readClaims2() {
326
+ const claimsPath = getClaimsPath(filename);
327
+ try {
328
+ const data = await fs2.readFile(claimsPath, "utf-8");
329
+ const parsed = parseClaims(data);
330
+ const now = Date.now();
331
+ const { cleaned, changed } = cleanClaims(parsed, now);
332
+ if (changed) {
333
+ try {
334
+ await writeClaimsFile(claimsPath, cleaned);
335
+ } catch {
336
+ }
329
337
  }
338
+ return cleaned;
339
+ } catch {
340
+ return {};
330
341
  }
331
- return cleaned;
332
- } catch {
333
- return {};
334
342
  }
335
- }
336
- async function writeClaim(accountId) {
337
- const now = Date.now();
338
- const claims = await readClaims();
339
- const { cleaned } = cleanClaims(claims, now);
340
- cleaned[accountId] = { pid: process.pid, at: now };
341
- try {
342
- await writeClaimsFile(cleaned);
343
- } catch {
343
+ async function writeClaim2(accountId) {
344
+ const claimsPath = getClaimsPath(filename);
345
+ const now = Date.now();
346
+ const claims = await readClaims2();
347
+ const { cleaned } = cleanClaims(claims, now);
348
+ cleaned[accountId] = { pid: process.pid, at: now };
349
+ try {
350
+ await writeClaimsFile(claimsPath, cleaned);
351
+ } catch {
352
+ }
344
353
  }
345
- }
346
- async function releaseClaim(accountId) {
347
- const now = Date.now();
348
- const claims = await readClaims();
349
- const { cleaned } = cleanClaims(claims, now);
350
- const currentClaim = cleaned[accountId];
351
- if (!currentClaim || currentClaim.pid !== process.pid) {
352
- return;
354
+ async function releaseClaim2(accountId) {
355
+ const claimsPath = getClaimsPath(filename);
356
+ const now = Date.now();
357
+ const claims = await readClaims2();
358
+ const { cleaned } = cleanClaims(claims, now);
359
+ const currentClaim = cleaned[accountId];
360
+ if (!currentClaim || currentClaim.pid !== process.pid) {
361
+ return;
362
+ }
363
+ delete cleaned[accountId];
364
+ try {
365
+ await writeClaimsFile(claimsPath, cleaned);
366
+ } catch {
367
+ }
353
368
  }
354
- delete cleaned[accountId];
355
- try {
356
- await writeClaimsFile(cleaned);
357
- } catch {
369
+ function isClaimedByOther2(claims, accountId) {
370
+ if (!accountId) return false;
371
+ const claim = claims[accountId];
372
+ if (!claim) return false;
373
+ if (Date.now() - claim.at > CLAIM_EXPIRY_MS) return false;
374
+ if (!isProcessAlive(claim.pid)) return false;
375
+ return claim.pid !== process.pid;
358
376
  }
377
+ return {
378
+ readClaims: readClaims2,
379
+ writeClaim: writeClaim2,
380
+ releaseClaim: releaseClaim2,
381
+ isClaimedByOther: isClaimedByOther2
382
+ };
383
+ }
384
+ var defaultClaimsManager = createClaimsManager();
385
+ function readClaims() {
386
+ return defaultClaimsManager.readClaims();
387
+ }
388
+ function writeClaim(accountId) {
389
+ return defaultClaimsManager.writeClaim(accountId);
390
+ }
391
+ function releaseClaim(accountId) {
392
+ return defaultClaimsManager.releaseClaim(accountId);
359
393
  }
360
394
  function isClaimedByOther(claims, accountId) {
361
- if (!accountId) return false;
362
- const claim = claims[accountId];
363
- if (!claim) return false;
364
- if (Date.now() - claim.at > CLAIM_EXPIRY_MS) return false;
365
- if (!isProcessAlive(claim.pid)) return false;
366
- return claim.pid !== process.pid;
395
+ return defaultClaimsManager.isClaimedByOther(claims, accountId);
367
396
  }
368
397
 
369
398
  // src/account-manager.ts
@@ -373,8 +402,12 @@ var HYBRID_SWITCH_MARGIN = 40;
373
402
  function createAccountManagerForProvider(dependencies) {
374
403
  const {
375
404
  providerAuthId,
405
+ getConfig: getProviderConfig = getConfig,
376
406
  isTokenExpired,
377
- refreshToken
407
+ refreshToken,
408
+ readClaims: readProviderClaims = readClaims,
409
+ writeClaim: writeProviderClaim = writeClaim,
410
+ isClaimedByOther: isClaimedByOtherProvider = isClaimedByOther
378
411
  } = dependencies;
379
412
  return class AccountManager {
380
413
  constructor(store) {
@@ -477,7 +510,7 @@ function createAccountManagerForProvider(dependencies) {
477
510
  return this.cached.filter((account) => account.uuid && account.enabled && !account.isAuthDisabled);
478
511
  }
479
512
  exceedsSoftQuota(account) {
480
- const threshold = getConfig().soft_quota_threshold_percent;
513
+ const threshold = getProviderConfig().soft_quota_threshold_percent;
481
514
  if (threshold >= 100) return false;
482
515
  const usage = account.cachedUsage;
483
516
  if (!usage) return false;
@@ -547,8 +580,8 @@ function createAccountManagerForProvider(dependencies) {
547
580
  this.clearExpiredRateLimits();
548
581
  const eligible = this.getEligibleAccounts();
549
582
  if (eligible.length === 0) return null;
550
- const config = getConfig();
551
- const claims = config.cross_process_claims ? await readClaims() : {};
583
+ const config = getProviderConfig();
584
+ const claims = config.cross_process_claims ? await readProviderClaims() : {};
552
585
  const strategy = config.account_selection_strategy;
553
586
  let selected;
554
587
  switch (strategy) {
@@ -569,7 +602,7 @@ function createAccountManagerForProvider(dependencies) {
569
602
  });
570
603
  }
571
604
  if (config.cross_process_claims && selected?.uuid) {
572
- writeClaim(selected.uuid).catch(() => {
605
+ writeProviderClaim(selected.uuid).catch(() => {
573
606
  });
574
607
  }
575
608
  return selected;
@@ -596,7 +629,7 @@ function createAccountManagerForProvider(dependencies) {
596
629
  return current;
597
630
  }
598
631
  const unclaimed = eligible.find(
599
- (account) => this.isUsable(account) && !isClaimedByOther(claims, account.uuid)
632
+ (account) => this.isUsable(account) && !isClaimedByOtherProvider(claims, account.uuid)
600
633
  );
601
634
  if (unclaimed) {
602
635
  this.activateAccount(unclaimed);
@@ -613,7 +646,7 @@ function createAccountManagerForProvider(dependencies) {
613
646
  for (let i = 0; i < eligible.length; i++) {
614
647
  const index = (this.roundRobinCursor + i) % eligible.length;
615
648
  const account = eligible[index];
616
- if (this.isUsable(account) && !isClaimedByOther(claims, account.uuid)) {
649
+ if (this.isUsable(account) && !isClaimedByOtherProvider(claims, account.uuid)) {
617
650
  this.roundRobinCursor = (index + 1) % eligible.length;
618
651
  this.activateAccount(account);
619
652
  return account;
@@ -660,12 +693,12 @@ function createAccountManagerForProvider(dependencies) {
660
693
  calculateHybridScore(account, isActive, claims) {
661
694
  const maxUtilization = Math.min(100, Math.max(0, this.getMaxUtilization(account)));
662
695
  const usageScore = (100 - maxUtilization) / 100 * 450;
663
- const maxFailures = Math.max(1, getConfig().max_consecutive_auth_failures);
696
+ const maxFailures = Math.max(1, getProviderConfig().max_consecutive_auth_failures);
664
697
  const healthScore = Math.max(0, (maxFailures - account.consecutiveAuthFailures) / maxFailures * 250);
665
698
  const secondsSinceUsed = (Date.now() - account.lastUsed) / 1e3;
666
699
  const freshnessScore = Math.min(secondsSinceUsed, 900) / 900 * 60;
667
700
  const stickinessBonus = isActive ? 120 : 0;
668
- const claimPenalty = isClaimedByOther(claims, account.uuid) ? -200 : 0;
701
+ const claimPenalty = isClaimedByOtherProvider(claims, account.uuid) ? -200 : 0;
669
702
  return usageScore + healthScore + freshnessScore + stickinessBonus + claimPenalty;
670
703
  }
671
704
  getMaxUtilization(account) {
@@ -680,7 +713,7 @@ function createAccountManagerForProvider(dependencies) {
680
713
  account.lastUsed = Date.now();
681
714
  }
682
715
  async markRateLimited(uuid, backoffMs) {
683
- const effectiveBackoff = backoffMs ?? getConfig().rate_limit_min_backoff_ms;
716
+ const effectiveBackoff = backoffMs ?? getProviderConfig().rate_limit_min_backoff_ms;
684
717
  this.last429Map.set(uuid, Date.now());
685
718
  await this.store.mutateAccount(uuid, (account) => {
686
719
  account.rateLimitResetAt = Date.now() + effectiveBackoff;
@@ -737,7 +770,7 @@ function createAccountManagerForProvider(dependencies) {
737
770
  const account = storage.accounts.find((entry) => entry.uuid === uuid);
738
771
  if (!account) return;
739
772
  account.consecutiveAuthFailures = (account.consecutiveAuthFailures ?? 0) + 1;
740
- const maxFailures = getConfig().max_consecutive_auth_failures;
773
+ const maxFailures = getProviderConfig().max_consecutive_auth_failures;
741
774
  const usableCount = storage.accounts.filter(
742
775
  (entry) => entry.enabled && !entry.isAuthDisabled && entry.uuid !== uuid
743
776
  ).length;
@@ -2335,6 +2368,8 @@ export {
2335
2368
  anthropicOAuthAdapter,
2336
2369
  confirm,
2337
2370
  createAccountManagerForProvider,
2371
+ createClaimsManager,
2372
+ createConfigLoader,
2338
2373
  createExecutorForProvider,
2339
2374
  createMinimalClient,
2340
2375
  createProactiveRefreshQueueForProvider,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/account-manager.ts","../src/claims.ts","../src/utils.ts","../src/config.ts","../src/types.ts","../src/account-store.ts","../src/storage.ts","../src/constants.ts","../src/file-lock.ts","../src/executor.ts","../src/proactive-refresh.ts","../src/rate-limit.ts","../src/auth-migration.ts","../src/ui/ansi.ts","../src/ui/select.ts","../src/ui/confirm.ts","../src/adapters/anthropic.ts","../src/adapters/openai.ts","../src/pool-types.ts","../src/pool-config-store.ts","../src/pool-manager.ts","../src/cascade-state.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { readClaims, writeClaim, isClaimedByOther, type ClaimsMap } from \"./claims\";\nimport { getConfig } from \"./config\";\nimport { getClearedOAuthBody } from \"./utils\";\nimport type { AccountStore } from \"./account-store\";\nimport type {\n ManagedAccount,\n OAuthCredentials,\n PluginClient,\n StoredAccount,\n TokenRefreshResult,\n UsageLimits,\n} from \"./types\";\n\nconst STARTUP_REFRESH_CONCURRENCY = 3;\nconst RECENT_429_COOLDOWN_MS = 30_000;\nconst HYBRID_SWITCH_MARGIN = 40;\n\nexport interface ProfileData {\n email?: string;\n planTier: string;\n}\n\nexport interface RuntimeFactoryLike {\n invalidate(uuid: string): void;\n}\n\nexport interface AccountManagerDependencies {\n providerAuthId: string;\n isTokenExpired: (account: Pick<ManagedAccount, \"accessToken\" | \"expiresAt\">) => boolean;\n refreshToken: (\n currentRefreshToken: string,\n accountId: string,\n client: PluginClient,\n ) => Promise<TokenRefreshResult>;\n}\n\nexport interface AccountManagerInstance {\n initialize(currentAuth: OAuthCredentials, client?: PluginClient): Promise<void>;\n refresh(): Promise<void>;\n getAccountCount(): number;\n getAccounts(): ManagedAccount[];\n getActiveAccount(): ManagedAccount | null;\n setClient(client: PluginClient): void;\n setRuntimeFactory(factory: RuntimeFactoryLike): void;\n hasAnyUsableAccount(): boolean;\n isRateLimited(account: ManagedAccount): boolean;\n clearExpiredRateLimits(): void;\n getMinWaitTime(): number;\n selectAccount(): Promise<ManagedAccount | null>;\n markRateLimited(uuid: string, backoffMs?: number): Promise<void>;\n markRevoked(uuid: string): Promise<void>;\n markSuccess(uuid: string): Promise<void>;\n markAuthFailure(uuid: string, result: TokenRefreshResult): Promise<void>;\n applyUsageCache(uuid: string, usage: UsageLimits): Promise<void>;\n applyProfileCache(uuid: string, profile: ProfileData): Promise<void>;\n ensureValidToken(uuid: string, client: PluginClient): Promise<TokenRefreshResult>;\n validateNonActiveTokens(client: PluginClient): Promise<void>;\n removeAccount(index: number): Promise<boolean>;\n clearAllAccounts(): Promise<void>;\n addAccount(auth: OAuthCredentials, email?: string): Promise<void>;\n toggleEnabled(uuid: string): Promise<void>;\n replaceAccountCredentials(uuid: string, auth: OAuthCredentials): Promise<void>;\n retryAuth(uuid: string, client: PluginClient): Promise<TokenRefreshResult>;\n}\n\nexport interface AccountManagerClass {\n new (store: AccountStore): AccountManagerInstance;\n create(store: AccountStore, currentAuth: OAuthCredentials, client?: PluginClient): Promise<AccountManagerInstance>;\n}\n\nexport function createAccountManagerForProvider(dependencies: AccountManagerDependencies): AccountManagerClass {\n const {\n providerAuthId,\n isTokenExpired,\n refreshToken,\n } = dependencies;\n\n return class AccountManager {\n private cached: ManagedAccount[] = [];\n private activeAccountUuid?: string;\n private client: PluginClient | null = null;\n private runtimeFactory: RuntimeFactoryLike | null = null;\n private roundRobinCursor = 0;\n private last429Map = new Map<string, number>();\n\n constructor(private store: AccountStore) {}\n\n static async create(\n store: AccountStore,\n currentAuth: OAuthCredentials,\n client?: PluginClient,\n ): Promise<AccountManager> {\n const manager = new AccountManager(store);\n await manager.initialize(currentAuth, client);\n return manager;\n }\n\n async initialize(currentAuth: OAuthCredentials, client?: PluginClient): Promise<void> {\n if (client) this.client = client;\n\n const storage = await this.store.load();\n if (storage.accounts.length > 0) {\n this.cached = storage.accounts.map((account, index) => this.toManagedAccount(account, index));\n this.activeAccountUuid = storage.activeAccountUuid;\n if (!this.getActiveAccount() && this.cached.length > 0) {\n this.activeAccountUuid = this.cached[0]!.uuid;\n }\n return;\n }\n\n if (currentAuth.refresh) {\n const newAccount = this.createNewAccount(currentAuth, Date.now());\n await this.store.addAccount(newAccount);\n await this.store.setActiveUuid(newAccount.uuid);\n this.cached = [this.toManagedAccount(newAccount, 0)];\n this.activeAccountUuid = newAccount.uuid;\n }\n }\n\n async refresh(): Promise<void> {\n const storage = await this.store.load();\n this.cached = storage.accounts.map((account, index) => this.toManagedAccount(account, index));\n if (storage.activeAccountUuid) {\n this.activeAccountUuid = storage.activeAccountUuid;\n }\n }\n\n private toManagedAccount(storedAccount: StoredAccount, index: number): ManagedAccount {\n return {\n index,\n uuid: storedAccount.uuid,\n accountId: storedAccount.accountId,\n label: storedAccount.label,\n email: storedAccount.email,\n planTier: storedAccount.planTier,\n refreshToken: storedAccount.refreshToken,\n accessToken: storedAccount.accessToken,\n expiresAt: storedAccount.expiresAt,\n addedAt: storedAccount.addedAt,\n lastUsed: storedAccount.lastUsed,\n enabled: storedAccount.enabled,\n rateLimitResetAt: storedAccount.rateLimitResetAt,\n cachedUsage: storedAccount.cachedUsage,\n cachedUsageAt: storedAccount.cachedUsageAt,\n consecutiveAuthFailures: storedAccount.consecutiveAuthFailures,\n isAuthDisabled: storedAccount.isAuthDisabled,\n authDisabledReason: storedAccount.authDisabledReason,\n last429At: storedAccount.uuid ? this.last429Map.get(storedAccount.uuid) : undefined,\n };\n }\n\n private createNewAccount(auth: OAuthCredentials, now: number): StoredAccount {\n return {\n uuid: randomUUID(),\n refreshToken: auth.refresh,\n accessToken: auth.access,\n expiresAt: auth.expires,\n addedAt: now,\n lastUsed: now,\n enabled: true,\n planTier: \"\",\n consecutiveAuthFailures: 0,\n isAuthDisabled: false,\n };\n }\n\n getAccountCount(): number {\n return this.getEligibleAccounts().length;\n }\n\n getAccounts(): ManagedAccount[] {\n return [...this.cached];\n }\n\n getActiveAccount(): ManagedAccount | null {\n if (this.activeAccountUuid) {\n return this.cached.find((account) => account.uuid === this.activeAccountUuid) ?? null;\n }\n return this.cached[0] ?? null;\n }\n\n setClient(client: PluginClient): void {\n this.client = client;\n }\n\n setRuntimeFactory(factory: RuntimeFactoryLike): void {\n this.runtimeFactory = factory;\n }\n\n private getEligibleAccounts(): ManagedAccount[] {\n return this.cached.filter((account) => account.uuid && account.enabled && !account.isAuthDisabled);\n }\n\n private exceedsSoftQuota(account: ManagedAccount): boolean {\n const threshold = getConfig().soft_quota_threshold_percent;\n if (threshold >= 100) return false;\n\n const usage = account.cachedUsage;\n if (!usage) return false;\n\n const tiers = [usage.five_hour, usage.seven_day];\n return tiers.some((tier) => tier != null && tier.utilization >= threshold);\n }\n\n hasAnyUsableAccount(): boolean {\n return this.getEligibleAccounts().length > 0;\n }\n\n isRateLimited(account: ManagedAccount): boolean {\n if (account.rateLimitResetAt && Date.now() < account.rateLimitResetAt) {\n return true;\n }\n return this.isUsageExhausted(account);\n }\n\n private isUsageExhausted(account: ManagedAccount): boolean {\n const usage = account.cachedUsage;\n if (!usage) return false;\n\n const now = Date.now();\n const tiers = [usage.five_hour, usage.seven_day];\n return tiers.some((tier) =>\n tier != null\n && tier.utilization >= 100\n && tier.resets_at != null\n && Date.parse(tier.resets_at) > now,\n );\n }\n\n clearExpiredRateLimits(): void {\n const now = Date.now();\n for (const account of this.cached) {\n if (account.rateLimitResetAt && now >= account.rateLimitResetAt) {\n account.rateLimitResetAt = undefined;\n }\n }\n }\n\n getMinWaitTime(): number {\n const eligible = this.getEligibleAccounts();\n const available = eligible.filter((account) => !this.isRateLimited(account));\n if (available.length > 0) return 0;\n\n const now = Date.now();\n const waits: number[] = [];\n\n for (const account of eligible) {\n if (account.rateLimitResetAt) {\n const ms = account.rateLimitResetAt - now;\n if (ms > 0) waits.push(ms);\n }\n\n const usageResetMs = this.getUsageResetMs(account);\n if (usageResetMs !== null && usageResetMs > 0) {\n waits.push(usageResetMs);\n }\n }\n\n return waits.length > 0 ? Math.min(...waits) : 0;\n }\n\n private getUsageResetMs(account: ManagedAccount): number | null {\n const usage = account.cachedUsage;\n if (!usage) return null;\n\n const now = Date.now();\n const candidates: number[] = [];\n const tiers = [usage.five_hour, usage.seven_day];\n\n for (const tier of tiers) {\n if (tier != null && tier.utilization >= 100 && tier.resets_at != null) {\n const ms = Date.parse(tier.resets_at) - now;\n if (ms > 0) candidates.push(ms);\n }\n }\n\n return candidates.length > 0 ? Math.min(...candidates) : null;\n }\n\n async selectAccount(): Promise<ManagedAccount | null> {\n await this.refresh();\n this.clearExpiredRateLimits();\n\n const eligible = this.getEligibleAccounts();\n if (eligible.length === 0) return null;\n\n const config = getConfig();\n const claims = config.cross_process_claims ? await readClaims() : {};\n\n const strategy = config.account_selection_strategy;\n let selected: ManagedAccount | null;\n switch (strategy) {\n case \"round-robin\":\n selected = this.selectRoundRobin(eligible, claims);\n break;\n case \"hybrid\":\n selected = this.selectHybrid(eligible, claims);\n break;\n case \"sticky\":\n default:\n selected = this.selectSticky(eligible, claims);\n break;\n }\n\n if (selected?.uuid) {\n this.activeAccountUuid = selected.uuid;\n this.store.setActiveUuid(selected.uuid).catch(() => {});\n }\n\n if (config.cross_process_claims && selected?.uuid) {\n writeClaim(selected.uuid).catch(() => {});\n }\n\n return selected;\n }\n\n private isUsable(account: ManagedAccount): boolean {\n return !this.isRateLimited(account)\n && !this.isInRecentCooldown(account)\n && !this.exceedsSoftQuota(account);\n }\n\n private isInRecentCooldown(account: ManagedAccount): boolean {\n if (!account.last429At) return false;\n return Date.now() - account.last429At < RECENT_429_COOLDOWN_MS;\n }\n\n private fallbackNotRateLimited(eligible: ManagedAccount[]): ManagedAccount | null {\n const account = eligible.find((candidate) => !this.isRateLimited(candidate));\n if (account) {\n this.activateAccount(account);\n return account;\n }\n return null;\n }\n\n private selectSticky(eligible: ManagedAccount[], claims: ClaimsMap): ManagedAccount | null {\n const current = this.getActiveAccount();\n if (current?.enabled && !current.isAuthDisabled && this.isUsable(current)) {\n this.activateAccount(current);\n return current;\n }\n\n const unclaimed = eligible.find(\n (account) => this.isUsable(account) && !isClaimedByOther(claims, account.uuid),\n );\n if (unclaimed) {\n this.activateAccount(unclaimed);\n return unclaimed;\n }\n\n const available = eligible.find((account) => this.isUsable(account));\n if (available) {\n this.activateAccount(available);\n return available;\n }\n\n return this.fallbackNotRateLimited(eligible);\n }\n\n private selectRoundRobin(eligible: ManagedAccount[], claims: ClaimsMap): ManagedAccount | null {\n for (let i = 0; i < eligible.length; i++) {\n const index = (this.roundRobinCursor + i) % eligible.length;\n const account = eligible[index]!;\n if (this.isUsable(account) && !isClaimedByOther(claims, account.uuid)) {\n this.roundRobinCursor = (index + 1) % eligible.length;\n this.activateAccount(account);\n return account;\n }\n }\n\n for (let i = 0; i < eligible.length; i++) {\n const index = (this.roundRobinCursor + i) % eligible.length;\n const account = eligible[index]!;\n if (this.isUsable(account)) {\n this.roundRobinCursor = (index + 1) % eligible.length;\n this.activateAccount(account);\n return account;\n }\n }\n\n return this.fallbackNotRateLimited(eligible);\n }\n\n private selectHybrid(eligible: ManagedAccount[], claims: ClaimsMap): ManagedAccount | null {\n const usable = eligible.filter((account) => this.isUsable(account));\n const pool = usable.length > 0\n ? usable\n : eligible.filter((account) => !this.isRateLimited(account));\n\n if (pool.length === 0) return null;\n\n const activeUuid = this.activeAccountUuid;\n\n let best = pool[0]!;\n let bestScore = this.calculateHybridScore(best, best.uuid === activeUuid, claims);\n\n for (let i = 1; i < pool.length; i++) {\n const account = pool[i]!;\n const score = this.calculateHybridScore(account, account.uuid === activeUuid, claims);\n if (score > bestScore) {\n best = account;\n bestScore = score;\n }\n }\n\n const current = pool.find((account) => account.uuid === activeUuid);\n if (current && current !== best) {\n const currentScore = this.calculateHybridScore(current, true, claims);\n const bestWithoutStickiness = this.calculateHybridScore(best, false, claims);\n if (bestWithoutStickiness <= currentScore + HYBRID_SWITCH_MARGIN) {\n this.activateAccount(current);\n return current;\n }\n }\n\n this.activateAccount(best);\n return best;\n }\n\n private calculateHybridScore(account: ManagedAccount, isActive: boolean, claims: ClaimsMap): number {\n const maxUtilization = Math.min(100, Math.max(0, this.getMaxUtilization(account)));\n const usageScore = ((100 - maxUtilization) / 100) * 450;\n\n const maxFailures = Math.max(1, getConfig().max_consecutive_auth_failures);\n const healthScore = Math.max(0, ((maxFailures - account.consecutiveAuthFailures) / maxFailures) * 250);\n\n const secondsSinceUsed = (Date.now() - account.lastUsed) / 1000;\n const freshnessScore = (Math.min(secondsSinceUsed, 900) / 900) * 60;\n\n const stickinessBonus = isActive ? 120 : 0;\n const claimPenalty = isClaimedByOther(claims, account.uuid) ? -200 : 0;\n\n return usageScore + healthScore + freshnessScore + stickinessBonus + claimPenalty;\n }\n\n private getMaxUtilization(account: ManagedAccount): number {\n const usage = account.cachedUsage;\n if (!usage) return 65;\n\n const tiers = [usage.five_hour, usage.seven_day];\n const utilizations = tiers\n .filter((tier): tier is NonNullable<typeof tier> => tier != null)\n .map((tier) => tier.utilization);\n\n return utilizations.length > 0 ? Math.max(...utilizations) : 65;\n }\n\n private activateAccount(account: ManagedAccount): void {\n this.activeAccountUuid = account.uuid;\n account.lastUsed = Date.now();\n }\n\n async markRateLimited(uuid: string, backoffMs?: number): Promise<void> {\n const effectiveBackoff = backoffMs ?? getConfig().rate_limit_min_backoff_ms;\n this.last429Map.set(uuid, Date.now());\n await this.store.mutateAccount(uuid, (account) => {\n account.rateLimitResetAt = Date.now() + effectiveBackoff;\n });\n }\n\n async markRevoked(uuid: string): Promise<void> {\n await this.removeAccountByUuid(uuid);\n }\n\n async markSuccess(uuid: string): Promise<void> {\n this.last429Map.delete(uuid);\n await this.store.mutateAccount(uuid, (account) => {\n account.rateLimitResetAt = undefined;\n account.consecutiveAuthFailures = 0;\n account.lastUsed = Date.now();\n });\n }\n\n private syncToOpenCode(account: Pick<StoredAccount, \"refreshToken\" | \"accessToken\" | \"expiresAt\">): void {\n if (!this.client || !account.accessToken || !account.expiresAt) return;\n this.client.auth.set({\n path: { id: providerAuthId },\n body: {\n type: \"oauth\",\n refresh: account.refreshToken,\n access: account.accessToken,\n expires: account.expiresAt,\n },\n }).catch(() => {});\n }\n\n private async clearOpenCodeAuthIfNoAccountsRemain(): Promise<void> {\n if (!this.client) return;\n\n const storage = await this.store.load();\n if (storage.accounts.length > 0) return;\n\n await this.client.auth\n .set({\n path: { id: providerAuthId },\n body: getClearedOAuthBody(),\n })\n .catch(() => {});\n }\n\n private async removeAccountByUuid(uuid: string): Promise<void> {\n const removed = await this.store.removeAccount(uuid);\n if (!removed) return;\n\n this.last429Map.delete(uuid);\n this.runtimeFactory?.invalidate(uuid);\n await this.refresh();\n await this.clearOpenCodeAuthIfNoAccountsRemain();\n }\n\n async markAuthFailure(uuid: string, result: TokenRefreshResult): Promise<void> {\n if (!result.ok && result.permanent) {\n await this.removeAccountByUuid(uuid);\n return;\n }\n\n await this.store.mutateStorage((storage) => {\n const account = storage.accounts.find((entry) => entry.uuid === uuid);\n if (!account) return;\n\n account.consecutiveAuthFailures = (account.consecutiveAuthFailures ?? 0) + 1;\n const maxFailures = getConfig().max_consecutive_auth_failures;\n const usableCount = storage.accounts.filter(\n (entry) => entry.enabled && !entry.isAuthDisabled && entry.uuid !== uuid,\n ).length;\n\n if (account.consecutiveAuthFailures >= maxFailures && usableCount > 0) {\n account.isAuthDisabled = true;\n account.authDisabledReason = `${maxFailures} consecutive auth failures`;\n }\n });\n }\n\n async applyUsageCache(uuid: string, usage: UsageLimits): Promise<void> {\n await this.store.mutateAccount(uuid, (account) => {\n const now = Date.now();\n const exhaustedTierResetTimes = [usage.five_hour, usage.seven_day]\n .flatMap((tier) => {\n if (tier == null || tier.utilization < 100 || tier.resets_at == null) {\n return [];\n }\n return [Date.parse(tier.resets_at)];\n })\n .filter((resetAt) => Number.isFinite(resetAt) && resetAt > now);\n\n account.cachedUsage = usage;\n account.cachedUsageAt = Date.now();\n account.rateLimitResetAt = exhaustedTierResetTimes.length > 0\n ? Math.min(...exhaustedTierResetTimes)\n : undefined;\n });\n }\n\n async applyProfileCache(uuid: string, profile: ProfileData): Promise<void> {\n await this.store.mutateAccount(uuid, (account) => {\n account.email = profile.email ?? account.email;\n account.planTier = profile.planTier;\n });\n }\n\n async ensureValidToken(uuid: string, client: PluginClient): Promise<TokenRefreshResult> {\n const credentials = await this.store.readCredentials(uuid);\n if (!credentials) return { ok: false, permanent: true };\n\n if (credentials.accessToken && credentials.expiresAt && !isTokenExpired(credentials)) {\n return {\n ok: true,\n patch: { accessToken: credentials.accessToken, expiresAt: credentials.expiresAt },\n };\n }\n\n const result = await refreshToken(credentials.refreshToken, uuid, client);\n if (!result.ok) return result;\n\n const updated = await this.store.mutateAccount(uuid, (account) => {\n account.accessToken = result.patch.accessToken;\n account.expiresAt = result.patch.expiresAt;\n if (result.patch.refreshToken) account.refreshToken = result.patch.refreshToken;\n if (result.patch.uuid && result.patch.uuid !== uuid) account.uuid = result.patch.uuid;\n if (result.patch.accountId) account.accountId = result.patch.accountId;\n if (result.patch.email) account.email = result.patch.email;\n account.consecutiveAuthFailures = 0;\n account.isAuthDisabled = false;\n account.authDisabledReason = undefined;\n });\n\n if (result.patch.uuid && result.patch.uuid !== uuid && this.activeAccountUuid === uuid) {\n this.activeAccountUuid = result.patch.uuid;\n this.store.setActiveUuid(result.patch.uuid).catch(() => {});\n }\n\n if (updated && (uuid === this.activeAccountUuid || updated.uuid === this.activeAccountUuid)) {\n this.syncToOpenCode(updated);\n }\n\n return result;\n }\n\n async validateNonActiveTokens(client: PluginClient): Promise<void> {\n await this.refresh();\n\n const activeUuid = this.activeAccountUuid;\n const eligible = this.cached.filter(\n (account) => account.enabled && !account.isAuthDisabled && account.uuid && account.uuid !== activeUuid,\n );\n\n for (let i = 0; i < eligible.length; i += STARTUP_REFRESH_CONCURRENCY) {\n const batch = eligible.slice(i, i + STARTUP_REFRESH_CONCURRENCY);\n await Promise.all(\n batch.map(async (account) => {\n if (!account.uuid || !isTokenExpired(account)) return;\n\n const result = await this.ensureValidToken(account.uuid, client);\n if (!result.ok) {\n await this.markAuthFailure(account.uuid, result);\n }\n }),\n );\n }\n }\n\n async removeAccount(index: number): Promise<boolean> {\n const account = this.cached[index];\n if (!account?.uuid) return false;\n\n const removed = await this.store.removeAccount(account.uuid);\n if (removed) {\n await this.refresh();\n }\n return removed;\n }\n\n async clearAllAccounts(): Promise<void> {\n await this.store.clear();\n this.cached = [];\n this.activeAccountUuid = undefined;\n }\n\n async addAccount(auth: OAuthCredentials, email?: string): Promise<void> {\n if (!auth.refresh) return;\n\n const existingByToken = this.cached.find((account) => account.refreshToken === auth.refresh);\n if (existingByToken) return;\n\n if (email) {\n const existingByEmail = this.cached.find(\n (account) => account.email && account.email === email,\n );\n if (existingByEmail?.uuid) {\n await this.replaceAccountCredentials(existingByEmail.uuid, auth);\n return;\n }\n }\n\n const newAccount = this.createNewAccount(auth, Date.now());\n if (email) newAccount.email = email;\n await this.store.addAccount(newAccount);\n this.activeAccountUuid = newAccount.uuid;\n await this.store.setActiveUuid(newAccount.uuid);\n await this.refresh();\n }\n\n async toggleEnabled(uuid: string): Promise<void> {\n await this.store.mutateAccount(uuid, (account) => {\n account.enabled = !(account.enabled ?? true);\n if (account.enabled) {\n account.isAuthDisabled = false;\n account.authDisabledReason = undefined;\n account.consecutiveAuthFailures = 0;\n }\n });\n }\n\n async replaceAccountCredentials(uuid: string, auth: OAuthCredentials): Promise<void> {\n const updated = await this.store.mutateAccount(uuid, (account) => {\n account.refreshToken = auth.refresh;\n account.accessToken = auth.access;\n account.expiresAt = auth.expires;\n account.lastUsed = Date.now();\n account.enabled = true;\n account.isAuthDisabled = false;\n account.authDisabledReason = undefined;\n account.consecutiveAuthFailures = 0;\n account.rateLimitResetAt = undefined;\n });\n this.runtimeFactory?.invalidate(uuid);\n\n if (updated && uuid === this.activeAccountUuid) {\n this.syncToOpenCode(updated);\n }\n }\n\n async retryAuth(uuid: string, client: PluginClient): Promise<TokenRefreshResult> {\n await this.store.mutateAccount(uuid, (account) => {\n account.consecutiveAuthFailures = 0;\n account.isAuthDisabled = false;\n account.authDisabledReason = undefined;\n });\n this.runtimeFactory?.invalidate(uuid);\n\n const credentials = await this.store.readCredentials(uuid);\n if (!credentials) return { ok: false, permanent: true };\n\n const result = await refreshToken(credentials.refreshToken, uuid, client);\n if (result.ok) {\n const updated = await this.store.mutateAccount(uuid, (account) => {\n account.accessToken = result.patch.accessToken;\n account.expiresAt = result.patch.expiresAt;\n if (result.patch.refreshToken) account.refreshToken = result.patch.refreshToken;\n if (result.patch.uuid) account.uuid = result.patch.uuid;\n if (result.patch.accountId) account.accountId = result.patch.accountId;\n if (result.patch.email) account.email = result.patch.email;\n account.enabled = true;\n account.consecutiveAuthFailures = 0;\n });\n this.runtimeFactory?.invalidate(uuid);\n if (result.patch.uuid) {\n this.runtimeFactory?.invalidate(result.patch.uuid);\n }\n\n const nextUuid = result.patch.uuid ?? uuid;\n if (this.activeAccountUuid === uuid && result.patch.uuid && result.patch.uuid !== uuid) {\n this.activeAccountUuid = result.patch.uuid;\n await this.store.setActiveUuid(result.patch.uuid);\n }\n\n if (updated && (uuid === this.activeAccountUuid || nextUuid === this.activeAccountUuid)) {\n const freshCredentials = await this.store.readCredentials(nextUuid);\n if (freshCredentials) {\n this.syncToOpenCode({\n refreshToken: freshCredentials.refreshToken,\n accessToken: freshCredentials.accessToken,\n expiresAt: freshCredentials.expiresAt,\n });\n }\n }\n } else {\n await this.markAuthFailure(uuid, result);\n this.runtimeFactory?.invalidate(uuid);\n }\n\n return result;\n }\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport { randomBytes } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\nimport { getConfigDir } from \"./utils\";\n\nconst CLAIMS_FILENAME = \"multiauth-claims.json\";\nconst CLAIM_EXPIRY_MS = 60_000;\n\nexport type ClaimsMap = Record<string, { pid: number; at: number }>;\n\nfunction getClaimsPath(): string {\n return join(getConfigDir(), CLAIMS_FILENAME);\n}\n\nfunction isClaimShape(value: unknown): value is { pid: number; at: number } {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n const claim = value as Record<string, unknown>;\n return (\n typeof claim.pid === \"number\"\n && Number.isInteger(claim.pid)\n && claim.pid > 0\n && typeof claim.at === \"number\"\n && Number.isFinite(claim.at)\n );\n}\n\nfunction parseClaims(raw: string): ClaimsMap {\n let parsed: unknown;\n\n try {\n parsed = JSON.parse(raw);\n } catch {\n return {};\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return {};\n }\n\n const claims: ClaimsMap = {};\n for (const [accountId, claim] of Object.entries(parsed)) {\n if (isClaimShape(claim)) {\n claims[accountId] = claim;\n }\n }\n\n return claims;\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction cleanClaims(\n claims: ClaimsMap,\n now: number,\n): { cleaned: ClaimsMap; changed: boolean } {\n const cleaned: ClaimsMap = {};\n let changed = false;\n\n for (const [accountId, claim] of Object.entries(claims)) {\n const expiredByTime = now - claim.at > CLAIM_EXPIRY_MS;\n const zombieClaim = !isProcessAlive(claim.pid);\n if (expiredByTime || zombieClaim) {\n changed = true;\n continue;\n }\n\n cleaned[accountId] = claim;\n }\n\n return { cleaned, changed };\n}\n\nasync function writeClaimsFile(claims: ClaimsMap): Promise<void> {\n const path = getClaimsPath();\n const tempPath = `${path}.${randomBytes(6).toString(\"hex\")}.tmp`;\n await fs.mkdir(dirname(path), { recursive: true });\n\n try {\n await fs.writeFile(tempPath, JSON.stringify(claims, null, 2), { encoding: \"utf-8\", mode: 0o600 });\n await fs.rename(tempPath, path);\n } catch (error) {\n try {\n await fs.unlink(tempPath);\n } catch {\n // ignore cleanup failure\n }\n throw error;\n }\n}\n\nexport async function readClaims(): Promise<ClaimsMap> {\n try {\n const data = await fs.readFile(getClaimsPath(), \"utf-8\");\n const parsed = parseClaims(data);\n const now = Date.now();\n const { cleaned, changed } = cleanClaims(parsed, now);\n\n if (changed) {\n try {\n await writeClaimsFile(cleaned);\n } catch {\n // best-effort cleanup\n }\n }\n\n return cleaned;\n } catch {\n return {};\n }\n}\n\n// Best-effort read-modify-write: not atomic across processes, but acceptable\n// because stale/duplicate claims self-expire via CLAIM_EXPIRY_MS and zombie detection.\nexport async function writeClaim(accountId: string): Promise<void> {\n const now = Date.now();\n const claims = await readClaims();\n const { cleaned } = cleanClaims(claims, now);\n\n cleaned[accountId] = { pid: process.pid, at: now };\n\n try {\n await writeClaimsFile(cleaned);\n } catch {\n // best-effort claim update\n }\n}\n\n// Best-effort read-modify-write: same rationale as writeClaim above.\nexport async function releaseClaim(accountId: string): Promise<void> {\n const now = Date.now();\n const claims = await readClaims();\n const { cleaned } = cleanClaims(claims, now);\n\n const currentClaim = cleaned[accountId];\n if (!currentClaim || currentClaim.pid !== process.pid) {\n return;\n }\n\n delete cleaned[accountId];\n\n try {\n await writeClaimsFile(cleaned);\n } catch {\n // best-effort release\n }\n}\n\nexport function isClaimedByOther(\n claims: ClaimsMap,\n accountId: string | undefined,\n): boolean {\n if (!accountId) return false;\n const claim = claims[accountId];\n if (!claim) return false;\n if (Date.now() - claim.at > CLAIM_EXPIRY_MS) return false;\n if (!isProcessAlive(claim.pid)) return false;\n return claim.pid !== process.pid;\n}\n","import { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { getConfig } from \"./config\";\nimport type { ManagedAccount, PluginClient } from \"./types\";\n\n// ─── Shared Filesystem Utilities ─────────────────────────────────\n\nexport function getConfigDir(): string {\n return process.env.OPENCODE_CONFIG_DIR\n || join(process.env.XDG_CONFIG_HOME || join(homedir(), \".config\"), \"opencode\");\n}\n\nexport function getErrorCode(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null || !(\"code\" in error)) {\n return undefined;\n }\n const code = (error as { code?: unknown }).code;\n return typeof code === \"string\" ? code : undefined;\n}\n\n// ─── Formatting & Display ────────────────────────────────────────\n\nexport function formatWaitTime(ms: number): string {\n const totalSeconds = Math.ceil(ms / 1000);\n if (totalSeconds < 60) return `${totalSeconds}s`;\n\n const days = Math.floor(totalSeconds / 86_400);\n const hours = Math.floor((totalSeconds % 86_400) / 3_600);\n const minutes = Math.floor((totalSeconds % 3_600) / 60);\n const seconds = totalSeconds % 60;\n\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (hours > 0) parts.push(`${hours}h`);\n if (minutes > 0) parts.push(`${minutes}m`);\n if (seconds > 0 && days === 0) parts.push(`${seconds}s`);\n\n return parts.join(\" \") || \"0s\";\n}\n\nexport function getAccountLabel(account: ManagedAccount): string {\n if (account.label) return account.label;\n if (account.email) return account.email;\n if (account.uuid) return `Account (${account.uuid.slice(0, 8)})`;\n return `Account ${account.index + 1}`;\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function showToast(\n client: PluginClient,\n message: string,\n variant: \"info\" | \"warning\" | \"success\" | \"error\",\n): Promise<void> {\n if (getConfig().quiet_mode) return;\n try {\n await client.tui.showToast({ body: { message, variant } });\n } catch {\n // TUI may not be available\n }\n}\n\nexport function debugLog(\n client: PluginClient,\n message: string,\n extra?: Record<string, unknown>,\n): void {\n if (!getConfig().debug) return;\n client.app.log({\n body: { service: \"claude-multiauth\", level: \"debug\", message, extra },\n }).catch(() => {});\n}\n\nexport function createMinimalClient(): PluginClient {\n return {\n auth: {\n set: async () => {},\n },\n tui: {\n showToast: async () => {},\n },\n app: {\n log: async () => {},\n },\n };\n}\n\n// ─── OAuth Helpers ───────────────────────────────────────────────\n\nexport function getClearedOAuthBody() {\n return {\n type: \"oauth\" as const,\n refresh: \"\",\n access: \"\",\n expires: 0,\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport { randomBytes } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport * as v from \"valibot\";\nimport { PluginConfigSchema } from \"./types\";\nimport type { PluginConfig } from \"./types\";\n\nexport type CoreConfig = Pick<PluginConfig, \"quiet_mode\" | \"debug\">;\n\nconst DEFAULT_CONFIG_FILENAME = \"multiauth-config.json\";\nconst DEFAULT_CONFIG: PluginConfig = v.parse(PluginConfigSchema, {});\n\nlet configFilename = DEFAULT_CONFIG_FILENAME;\nlet cachedConfig: PluginConfig | null = null;\nlet externalConfigGetter: (() => PluginConfig) | null = null;\n\nfunction getConfigDir(): string {\n return process.env.OPENCODE_CONFIG_DIR\n || join(process.env.XDG_CONFIG_HOME || join(homedir(), \".config\"), \"opencode\");\n}\n\nfunction getConfigPath(): string {\n return join(getConfigDir(), configFilename);\n}\n\nfunction parseConfig(raw: unknown): PluginConfig {\n const result = v.safeParse(PluginConfigSchema, raw);\n return result.success ? result.output : DEFAULT_CONFIG;\n}\n\nexport function initCoreConfig(filename: string): void {\n configFilename = filename || DEFAULT_CONFIG_FILENAME;\n cachedConfig = null;\n}\n\nexport async function loadConfig(): Promise<PluginConfig> {\n if (cachedConfig) return cachedConfig;\n\n const path = getConfigPath();\n try {\n const content = await fs.readFile(path, \"utf-8\");\n cachedConfig = parseConfig(JSON.parse(content));\n } catch {\n cachedConfig = DEFAULT_CONFIG;\n }\n\n return cachedConfig;\n}\n\nexport function getConfig(): PluginConfig {\n if (cachedConfig) return cachedConfig;\n\n if (externalConfigGetter && externalConfigGetter !== getConfig) {\n try {\n return parseConfig(externalConfigGetter());\n } catch {\n return DEFAULT_CONFIG;\n }\n }\n\n return DEFAULT_CONFIG;\n}\n\nexport function resetConfigCache(): void {\n cachedConfig = null;\n}\n\nexport function setConfigGetter(getter: () => PluginConfig): void {\n if (getter === getConfig) {\n return;\n }\n externalConfigGetter = getter;\n}\n\nexport async function updateConfigField<K extends keyof PluginConfig>(\n key: K,\n value: PluginConfig[K],\n): Promise<void> {\n const path = getConfigPath();\n\n let existing: Record<string, unknown> = {};\n try {\n const content = await fs.readFile(path, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {}\n\n existing[key] = value;\n\n await fs.mkdir(dirname(path), { recursive: true });\n const content = `${JSON.stringify(existing, null, 2)}\\n`;\n const tempPath = `${path}.${randomBytes(8).toString(\"hex\")}.tmp`;\n try {\n await fs.writeFile(tempPath, content, \"utf-8\");\n await fs.rename(tempPath, path);\n } catch (error) {\n try {\n await fs.unlink(tempPath);\n } catch {}\n throw error;\n }\n\n cachedConfig = null;\n await loadConfig();\n}\n","import * as v from \"valibot\";\n\nexport const OAuthCredentialsSchema = v.object({\n type: v.literal(\"oauth\"),\n refresh: v.string(),\n access: v.string(),\n expires: v.number(),\n});\n\nexport const UsageLimitEntrySchema = v.object({\n utilization: v.number(),\n resets_at: v.nullable(v.string()),\n});\n\nexport const UsageLimitsSchema = v.object({\n five_hour: v.optional(v.nullable(UsageLimitEntrySchema), null),\n seven_day: v.optional(v.nullable(UsageLimitEntrySchema), null),\n seven_day_sonnet: v.optional(v.nullable(UsageLimitEntrySchema), null),\n});\n\nexport const CredentialRefreshPatchSchema = v.object({\n accessToken: v.string(),\n expiresAt: v.number(),\n refreshToken: v.optional(v.string()),\n uuid: v.optional(v.string()),\n accountId: v.optional(v.string()),\n email: v.optional(v.string()),\n});\n\nexport const StoredAccountSchema = v.object({\n uuid: v.optional(v.string()),\n accountId: v.optional(v.string()),\n label: v.optional(v.string()),\n email: v.optional(v.string()),\n planTier: v.optional(v.string(), \"\"),\n refreshToken: v.string(),\n accessToken: v.optional(v.string()),\n expiresAt: v.optional(v.number()),\n addedAt: v.number(),\n lastUsed: v.number(),\n enabled: v.optional(v.boolean(), true),\n rateLimitResetAt: v.optional(v.number()),\n cachedUsage: v.optional(UsageLimitsSchema),\n cachedUsageAt: v.optional(v.number()),\n consecutiveAuthFailures: v.optional(v.number(), 0),\n isAuthDisabled: v.optional(v.boolean(), false),\n authDisabledReason: v.optional(v.string()),\n});\n\nexport const AccountStorageSchema = v.object({\n version: v.literal(1),\n accounts: v.optional(v.array(StoredAccountSchema), []),\n activeAccountUuid: v.optional(v.string()),\n});\n\nexport const AccountSelectionStrategySchema = v.picklist([\"sticky\", \"round-robin\", \"hybrid\"]);\n\nexport const PluginConfigSchema = v.object({\n account_selection_strategy: v.optional(AccountSelectionStrategySchema, \"sticky\"),\n cross_process_claims: v.optional(v.boolean(), true),\n soft_quota_threshold_percent: v.optional(v.pipe(v.number(), v.minValue(0), v.maxValue(100)), 100),\n rate_limit_min_backoff_ms: v.optional(v.pipe(v.number(), v.minValue(0)), 30_000),\n default_retry_after_ms: v.optional(v.pipe(v.number(), v.minValue(0)), 60_000),\n max_consecutive_auth_failures: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1)), 3),\n token_failure_backoff_ms: v.optional(v.pipe(v.number(), v.minValue(0)), 30_000),\n proactive_refresh: v.optional(v.boolean(), true),\n proactive_refresh_buffer_seconds: v.optional(v.pipe(v.number(), v.minValue(60)), 1800),\n proactive_refresh_interval_seconds: v.optional(v.pipe(v.number(), v.minValue(30)), 300),\n quiet_mode: v.optional(v.boolean(), false),\n debug: v.optional(v.boolean(), false),\n});\n\nexport type OAuthCredentials = v.InferOutput<typeof OAuthCredentialsSchema>;\nexport type UsageLimitEntry = v.InferOutput<typeof UsageLimitEntrySchema>;\nexport type UsageLimits = v.InferOutput<typeof UsageLimitsSchema>;\nexport type CredentialRefreshPatch = v.InferOutput<typeof CredentialRefreshPatchSchema>;\nexport type StoredAccount = v.InferOutput<typeof StoredAccountSchema>;\nexport type AccountStorage = v.InferOutput<typeof AccountStorageSchema>;\nexport type AccountSelectionStrategy = v.InferOutput<typeof AccountSelectionStrategySchema>;\nexport type PluginConfig = v.InferOutput<typeof PluginConfigSchema>;\n\nexport type TokenRefreshResult =\n | { ok: true; patch: CredentialRefreshPatch }\n | { ok: false; permanent: boolean; status?: number };\n\nexport class TokenRefreshError extends Error {\n readonly status?: number;\n readonly permanent: boolean;\n\n constructor(permanent: boolean, status?: number) {\n super(status === undefined ? \"Token refresh failed\" : `Token refresh failed: ${status}`);\n this.name = \"TokenRefreshError\";\n this.status = status;\n this.permanent = permanent;\n Object.setPrototypeOf(this, TokenRefreshError.prototype);\n }\n}\n\nexport function isTokenRefreshError(error: unknown): error is TokenRefreshError {\n if (error instanceof TokenRefreshError) return true;\n if (!(error instanceof Error)) return false;\n\n const candidate = error as Error & Partial<TokenRefreshError>;\n return (\n candidate.name === \"TokenRefreshError\"\n && typeof candidate.permanent === \"boolean\"\n && (candidate.status === undefined || typeof candidate.status === \"number\")\n );\n}\n\nexport interface ManagedAccount {\n index: number;\n uuid?: string;\n accountId?: string;\n label?: string;\n email?: string;\n planTier?: string;\n refreshToken: string;\n accessToken?: string;\n expiresAt?: number;\n addedAt: number;\n lastUsed: number;\n enabled: boolean;\n rateLimitResetAt?: number;\n last429At?: number;\n cachedUsage?: UsageLimits;\n cachedUsageAt?: number;\n consecutiveAuthFailures: number;\n isAuthDisabled: boolean;\n authDisabledReason?: string;\n}\n\nexport interface PluginClient {\n auth: {\n set: (params: {\n path: { id: string };\n body: {\n type: string;\n refresh: string;\n access: string;\n expires: number;\n };\n }) => Promise<void>;\n };\n tui: {\n showToast: (params: {\n body: {\n title?: string;\n message: string;\n variant: \"info\" | \"warning\" | \"success\" | \"error\";\n };\n }) => Promise<void>;\n };\n app: {\n log: (params: {\n body: {\n service: string;\n level: \"debug\" | \"info\" | \"warn\" | \"error\";\n message: string;\n extra?: Record<string, unknown>;\n };\n }) => Promise<void>;\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport { randomBytes } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\nimport * as v from \"valibot\";\nimport { loadAccounts, readStorageFromDisk } from \"./storage\";\nimport { ACCOUNTS_FILENAME } from \"./constants\";\nimport { withDirectoryLock } from \"./file-lock\";\nimport { AccountStorageSchema } from \"./types\";\nimport { getConfigDir, getErrorCode } from \"./utils\";\nimport type { AccountStorage, StoredAccount } from \"./types\";\n\nconst FILE_MODE = 0o600;\n\nfunction resolveStoragePath(filename: string): string {\n return join(getConfigDir(), filename);\n}\n\nfunction createEmptyStorage(): AccountStorage {\n return { version: 1, accounts: [] };\n}\n\nfunction buildTempPath(targetPath: string): string {\n return `${targetPath}.${randomBytes(8).toString(\"hex\")}.tmp`;\n}\n\nasync function writeAtomicText(targetPath: string, content: string): Promise<void> {\n await fs.mkdir(dirname(targetPath), { recursive: true });\n const tempPath = buildTempPath(targetPath);\n try {\n await fs.writeFile(tempPath, content, { encoding: \"utf-8\", mode: FILE_MODE });\n await fs.chmod(tempPath, FILE_MODE);\n await fs.rename(tempPath, targetPath);\n await fs.chmod(targetPath, FILE_MODE);\n } catch (error) {\n try {\n await fs.unlink(tempPath);\n } catch {}\n throw error;\n }\n}\n\nasync function writeStorageAtomic(targetPath: string, storage: AccountStorage): Promise<void> {\n const validation = v.safeParse(AccountStorageSchema, storage);\n if (!validation.success) {\n throw new Error(\"Invalid account storage payload\");\n }\n await writeAtomicText(targetPath, `${JSON.stringify(validation.output, null, 2)}\\n`);\n}\n\nasync function ensureStorageFileExists(targetPath: string): Promise<void> {\n await fs.mkdir(dirname(targetPath), { recursive: true });\n const emptyContent = `${JSON.stringify(createEmptyStorage(), null, 2)}\\n`;\n try {\n await fs.writeFile(targetPath, emptyContent, { flag: \"wx\", mode: FILE_MODE });\n } catch (error) {\n if (getErrorCode(error) !== \"EEXIST\") throw error;\n }\n}\n\nexport interface DiskCredentials {\n refreshToken: string;\n accessToken?: string;\n expiresAt?: number;\n accountId?: string;\n}\n\nexport class AccountStore {\n private readonly storagePath: string;\n\n constructor(filename?: string) {\n this.storagePath = resolveStoragePath(filename ?? ACCOUNTS_FILENAME);\n }\n\n private async withLock<T>(fn: (storagePath: string) => Promise<T>): Promise<T> {\n await ensureStorageFileExists(this.storagePath);\n return await withDirectoryLock(this.storagePath, () => fn(this.storagePath));\n }\n\n async load(): Promise<AccountStorage> {\n const storage = await loadAccounts(this.storagePath);\n return storage ?? createEmptyStorage();\n }\n\n async readCredentials(uuid: string): Promise<DiskCredentials | null> {\n const storage = await readStorageFromDisk(this.storagePath, false);\n if (!storage) return null;\n\n const account = storage.accounts.find((a) => a.uuid === uuid);\n if (!account) return null;\n\n return {\n refreshToken: account.refreshToken,\n accessToken: account.accessToken,\n expiresAt: account.expiresAt,\n accountId: account.accountId,\n };\n }\n\n async mutateAccount(\n uuid: string,\n fn: (account: StoredAccount) => void,\n ): Promise<StoredAccount | null> {\n return await this.withLock(async (storagePath) => {\n const current = await readStorageFromDisk(storagePath, false);\n if (!current) return null;\n\n const account = current.accounts.find((a) => a.uuid === uuid);\n if (!account) return null;\n\n fn(account);\n\n await writeStorageAtomic(storagePath, current);\n return { ...account };\n });\n }\n\n async mutateStorage(\n fn: (storage: AccountStorage) => void,\n ): Promise<void> {\n await this.withLock(async (storagePath) => {\n const current = await readStorageFromDisk(storagePath, false) ?? createEmptyStorage();\n fn(current);\n await writeStorageAtomic(storagePath, current);\n });\n }\n\n async addAccount(account: StoredAccount): Promise<void> {\n await this.withLock(async (storagePath) => {\n const current = await readStorageFromDisk(storagePath, false) ?? createEmptyStorage();\n const exists = current.accounts.some(\n (a) => a.uuid === account.uuid || a.refreshToken === account.refreshToken,\n );\n if (exists) return;\n\n current.accounts.push(account);\n await writeStorageAtomic(storagePath, current);\n });\n }\n\n async removeAccount(uuid: string): Promise<boolean> {\n return await this.withLock(async (storagePath) => {\n const current = await readStorageFromDisk(storagePath, false);\n if (!current) return false;\n\n const initialLength = current.accounts.length;\n current.accounts = current.accounts.filter((a) => a.uuid !== uuid);\n if (current.accounts.length === initialLength) return false;\n\n if (current.activeAccountUuid === uuid) {\n current.activeAccountUuid = current.accounts[0]?.uuid;\n }\n\n await writeStorageAtomic(storagePath, current);\n return true;\n });\n }\n\n async setActiveUuid(uuid: string | undefined): Promise<void> {\n await this.mutateStorage((storage) => {\n storage.activeAccountUuid = uuid;\n });\n }\n\n async clear(): Promise<void> {\n await this.withLock(async (storagePath) => {\n await writeStorageAtomic(storagePath, createEmptyStorage());\n });\n }\n}\n","import { promises as fs } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport * as v from \"valibot\";\nimport { ACCOUNTS_FILENAME } from \"./constants\";\nimport { AccountStorageSchema } from \"./types\";\nimport { getConfigDir, getErrorCode } from \"./utils\";\nimport type { AccountStorage, StoredAccount } from \"./types\";\n\nfunction getDefaultStoragePath(): string {\n return join(getConfigDir(), ACCOUNTS_FILENAME);\n}\n\nasync function backupCorruptFile(targetPath: string, content: string): Promise<void> {\n const backupPath = `${targetPath}.corrupt.${Date.now()}.bak`;\n await fs.mkdir(dirname(backupPath), { recursive: true });\n await fs.writeFile(backupPath, content, \"utf-8\");\n}\n\nexport async function readStorageFromDisk(\n targetPath: string,\n backupOnCorrupt: boolean,\n): Promise<AccountStorage | null> {\n let content: string;\n try {\n content = await fs.readFile(targetPath, \"utf-8\");\n } catch (error) {\n if (getErrorCode(error) === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(content);\n } catch {\n if (backupOnCorrupt) {\n try {\n await backupCorruptFile(targetPath, content);\n } catch {\n // best-effort backup\n }\n }\n return null;\n }\n\n const validation = v.safeParse(AccountStorageSchema, parsed);\n if (!validation.success) {\n if (backupOnCorrupt) {\n try {\n await backupCorruptFile(targetPath, content);\n } catch {\n // best-effort backup\n }\n }\n return null;\n }\n\n return validation.output;\n}\n\nexport function deduplicateAccounts(accounts: StoredAccount[]): StoredAccount[] {\n const deduplicated: StoredAccount[] = [];\n const indexByUuid = new Map<string, number>();\n\n for (const account of accounts) {\n if (!account.uuid) {\n deduplicated.push(account);\n continue;\n }\n\n const existingIndex = indexByUuid.get(account.uuid);\n if (existingIndex === undefined) {\n indexByUuid.set(account.uuid, deduplicated.length);\n deduplicated.push(account);\n continue;\n }\n\n const existingAccount = deduplicated[existingIndex];\n if (!existingAccount || account.lastUsed >= existingAccount.lastUsed) {\n deduplicated[existingIndex] = account;\n }\n }\n\n return deduplicated;\n}\n\nexport async function loadAccounts(storagePath?: string): Promise<AccountStorage | null> {\n const effectivePath = storagePath ?? getDefaultStoragePath();\n const storage = await readStorageFromDisk(effectivePath, true);\n if (!storage) {\n return null;\n }\n\n return {\n ...storage,\n accounts: deduplicateAccounts(storage.accounts || []),\n };\n}\n","const DEFAULT_ACCOUNTS_FILENAME = \"multiauth-accounts.json\";\n\n/**\n * @deprecated Use `new AccountStore(filename)` instead.\n * This global is kept only for backward-compatible test helpers.\n * When two plugins share the same core module instance, mutating\n * this global causes one plugin to read the other's account file.\n */\nexport let ACCOUNTS_FILENAME = DEFAULT_ACCOUNTS_FILENAME;\n\n/**\n * @deprecated Use `new AccountStore(filename)` instead.\n */\nexport function setAccountsFilename(filename: string): void {\n if (!filename) {\n ACCOUNTS_FILENAME = DEFAULT_ACCOUNTS_FILENAME;\n return;\n }\n\n ACCOUNTS_FILENAME = filename;\n}\n","import { promises as fs } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nconst DEFAULT_STALE_MS = 10_000;\nconst DEFAULT_RETRY_DELAY_MS = 50;\nconst DEFAULT_MAX_RETRIES = 10;\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function removeIfStale(lockPath: string, staleMs: number): Promise<void> {\n try {\n const stat = await fs.stat(lockPath);\n if (Date.now() - stat.mtimeMs > staleMs) {\n await fs.rm(lockPath, { recursive: true, force: true });\n }\n } catch {}\n}\n\nexport async function withDirectoryLock<T>(\n targetPath: string,\n fn: () => Promise<T>,\n options?: {\n staleMs?: number;\n retryDelayMs?: number;\n retries?: number;\n },\n): Promise<T> {\n const lockPath = `${targetPath}.lock`;\n const staleMs = options?.staleMs ?? DEFAULT_STALE_MS;\n const retryDelayMs = options?.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n const retries = options?.retries ?? DEFAULT_MAX_RETRIES;\n\n await fs.mkdir(dirname(targetPath), { recursive: true });\n\n for (let attempt = 0; ; attempt += 1) {\n try {\n await fs.mkdir(lockPath, { mode: 0o700 });\n break;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException | undefined)?.code;\n if (code !== \"EEXIST\") {\n throw error;\n }\n\n await removeIfStale(lockPath, staleMs);\n if (attempt >= retries) {\n throw new Error(`Failed to acquire lock for ${targetPath}`);\n }\n await sleep(retryDelayMs * (attempt + 1));\n }\n }\n\n try {\n return await fn();\n } finally {\n await fs.rm(lockPath, { recursive: true, force: true }).catch(() => {});\n }\n}\n","import {\n isTokenRefreshError,\n type ManagedAccount,\n type PluginClient,\n type TokenRefreshResult,\n} from \"./types\";\n\nconst MIN_MAX_RETRIES = 6;\nconst RETRIES_PER_ACCOUNT = 3;\nconst MAX_SERVER_RETRIES_PER_ATTEMPT = 2;\nconst MAX_RESOLVE_ATTEMPTS = 10;\nconst SERVER_RETRY_BASE_MS = 1_000;\nconst SERVER_RETRY_MAX_MS = 4_000;\nexport interface ExecutorAccountManager {\n getAccountCount(): number;\n refresh(): Promise<void>;\n selectAccount(): Promise<ManagedAccount | null>;\n markSuccess(uuid: string): Promise<void>;\n markAuthFailure(uuid: string, result: TokenRefreshResult): Promise<void>;\n markRevoked(uuid: string): Promise<void>;\n hasAnyUsableAccount(): boolean;\n getMinWaitTime(): number;\n}\n\nexport interface ExecutorRuntimeFactory {\n getRuntime(uuid: string): Promise<{ fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response> }>;\n invalidate(uuid: string): void;\n}\n\nexport interface ExecutorDependencies {\n handleRateLimitResponse: (\n manager: unknown,\n client: PluginClient,\n account: ManagedAccount,\n response: Response,\n ) => Promise<void>;\n formatWaitTime: (ms: number) => string;\n sleep: (ms: number) => Promise<void>;\n showToast: (\n client: PluginClient,\n message: string,\n variant: \"info\" | \"warning\" | \"success\" | \"error\",\n ) => Promise<void>;\n getAccountLabel: (account: ManagedAccount) => string;\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === \"AbortError\";\n}\n\nexport function createExecutorForProvider(\n providerName: string,\n dependencies: ExecutorDependencies,\n): {\n executeWithAccountRotation: (\n manager: ExecutorAccountManager,\n runtimeFactory: ExecutorRuntimeFactory,\n client: PluginClient,\n input: RequestInfo | URL,\n init?: RequestInit,\n ) => Promise<Response>;\n} {\n const {\n handleRateLimitResponse,\n formatWaitTime,\n sleep,\n showToast,\n getAccountLabel,\n } = dependencies;\n\n async function executeWithAccountRotation(\n manager: ExecutorAccountManager,\n runtimeFactory: ExecutorRuntimeFactory,\n client: PluginClient,\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> {\n const maxRetries = Math.max(MIN_MAX_RETRIES, manager.getAccountCount() * RETRIES_PER_ACCOUNT);\n let previousAccountUuid: string | undefined;\n\n type StatusTransition =\n | { type: \"success\"; response: Response }\n | { type: \"handled\"; response?: Response }\n | { type: \"retryOuter\" };\n\n async function retryServerErrors(\n account: ManagedAccount,\n runtime: Awaited<ReturnType<ExecutorRuntimeFactory[\"getRuntime\"]>>,\n ): Promise<Response | null> {\n for (let attempt = 0; attempt < MAX_SERVER_RETRIES_PER_ATTEMPT; attempt++) {\n const backoff = Math.min(SERVER_RETRY_BASE_MS * 2 ** attempt, SERVER_RETRY_MAX_MS);\n const jitteredBackoff = backoff * (0.5 + Math.random() * 0.5);\n await sleep(jitteredBackoff);\n\n let retryResponse: Response;\n try {\n retryResponse = await runtime.fetch(input, init);\n } catch (error) {\n if (isAbortError(error)) throw error;\n if (await handleRuntimeFetchFailure(manager, runtimeFactory, client, account, error)) {\n return null;\n }\n void showToast(client, `${getAccountLabel(account)} network error — switching`, \"warning\");\n return null;\n }\n\n if (retryResponse.status < 500) return retryResponse;\n }\n\n return null;\n }\n\n const dispatchResponseStatus = async (\n account: ManagedAccount,\n accountUuid: string,\n runtime: Awaited<ReturnType<ExecutorRuntimeFactory[\"getRuntime\"]>>,\n response: Response,\n allow401Retry: boolean,\n from401RefreshRetry: boolean,\n ): Promise<StatusTransition> => {\n if (response.status >= 500) {\n const recovered = await retryServerErrors(account, runtime);\n if (recovered === null) {\n return { type: \"retryOuter\" };\n }\n response = recovered;\n }\n\n if (response.status === 401) {\n if (allow401Retry) {\n runtimeFactory.invalidate(accountUuid);\n try {\n const retryRuntime = await runtimeFactory.getRuntime(accountUuid);\n const retryResponse = await retryRuntime.fetch(input, init);\n return dispatchResponseStatus(account, accountUuid, retryRuntime, retryResponse, false, true);\n } catch (error) {\n if (isAbortError(error)) throw error;\n if (await handleRuntimeFetchFailure(manager, runtimeFactory, client, account, error)) {\n return { type: \"retryOuter\" };\n }\n return { type: \"retryOuter\" };\n }\n }\n\n await manager.markAuthFailure(accountUuid, { ok: false, permanent: false });\n await manager.refresh();\n\n if (!manager.hasAnyUsableAccount()) {\n void showToast(client, \"All accounts have auth failures.\", \"error\");\n throw new Error(\n `All ${providerName} accounts have authentication failures. Re-authenticate with \\`opencode auth login\\`.`,\n );\n }\n\n void showToast(client, `${getAccountLabel(account)} auth failed — switching to next account.`, \"warning\");\n return { type: \"retryOuter\" };\n }\n\n if (response.status === 403) {\n const revoked = await isRevokedTokenResponse(response);\n if (revoked) {\n await manager.markRevoked(accountUuid);\n await manager.refresh();\n void showToast(\n client,\n `${getAccountLabel(account)} disabled: OAuth token revoked.`,\n \"error\",\n );\n\n if (!manager.hasAnyUsableAccount()) {\n throw new Error(\n `All ${providerName} accounts have been revoked or disabled. Re-authenticate with \\`opencode auth login\\`.`,\n );\n }\n return { type: \"retryOuter\" };\n }\n\n if (from401RefreshRetry) {\n return { type: \"handled\", response };\n }\n }\n\n if (response.status === 429) {\n await handleRateLimitResponse(manager, client, account, response);\n return { type: \"handled\" };\n }\n\n return { type: \"success\", response };\n };\n\n for (let retries = 1; retries <= maxRetries; retries++) {\n await manager.refresh();\n const account = await resolveAccount(manager, client);\n const accountUuid = account.uuid;\n if (!accountUuid) continue;\n\n if (previousAccountUuid && accountUuid !== previousAccountUuid && manager.getAccountCount() > 1) {\n void showToast(client, `Switched to ${getAccountLabel(account)}`, \"info\");\n }\n previousAccountUuid = accountUuid;\n\n let runtime: Awaited<ReturnType<ExecutorRuntimeFactory[\"getRuntime\"]>>;\n let response: Response;\n try {\n runtime = await runtimeFactory.getRuntime(accountUuid);\n response = await runtime.fetch(input, init);\n } catch (error) {\n if (isAbortError(error)) throw error;\n if (await handleRuntimeFetchFailure(manager, runtimeFactory, client, account, error)) {\n continue;\n }\n void showToast(client, `${getAccountLabel(account)} network error — switching`, \"warning\");\n continue;\n }\n\n const transition = await dispatchResponseStatus(account, accountUuid, runtime, response, true, false);\n if (transition.type === \"retryOuter\" || transition.type === \"handled\") {\n if (transition.type === \"handled\" && transition.response) {\n return transition.response;\n }\n continue;\n }\n\n await manager.markSuccess(accountUuid);\n return transition.response;\n }\n\n throw new Error(\n `Exhausted ${maxRetries} retries across all accounts. All attempts failed due to auth errors, rate limits, or token issues.`,\n );\n }\n\n async function handleRuntimeFetchFailure(\n manager: ExecutorAccountManager,\n runtimeFactory: ExecutorRuntimeFactory,\n client: PluginClient,\n account: ManagedAccount,\n error: unknown,\n ): Promise<boolean> {\n if (!isTokenRefreshError(error)) return false;\n if (!account.uuid) return false;\n\n const accountUuid = account.uuid;\n runtimeFactory.invalidate(accountUuid);\n await manager.markAuthFailure(accountUuid, {\n ok: false,\n permanent: error.permanent,\n });\n await manager.refresh();\n\n if (!manager.hasAnyUsableAccount()) {\n void showToast(client, \"All accounts have auth failures.\", \"error\");\n throw new Error(\n `All ${providerName} accounts have authentication failures. Re-authenticate with \\`opencode auth login\\`.`,\n );\n }\n\n void showToast(client, `${getAccountLabel(account)} auth failed — switching to next account.`, \"warning\");\n return true;\n }\n\n async function resolveAccount(\n manager: ExecutorAccountManager,\n client: PluginClient,\n ): Promise<ManagedAccount> {\n let attempts = 0;\n\n while (true) {\n if (++attempts > MAX_RESOLVE_ATTEMPTS) {\n throw new Error(\n `Failed to resolve an available account after ${MAX_RESOLVE_ATTEMPTS} attempts. All accounts may be rate-limited or disabled.`,\n );\n }\n\n const account = await manager.selectAccount();\n if (account) return account;\n\n if (!manager.hasAnyUsableAccount()) {\n throw new Error(\n `All ${providerName} accounts are disabled. Re-authenticate with \\`opencode auth login\\`.`,\n );\n }\n\n const waitMs = manager.getMinWaitTime();\n if (waitMs <= 0) {\n throw new Error(\n `All ${providerName} accounts are rate-limited. Add more accounts with \\`opencode auth login\\` or wait.`,\n );\n }\n\n await showToast(\n client,\n `All ${manager.getAccountCount()} account(s) rate-limited. Waiting ${formatWaitTime(waitMs)}...`,\n \"warning\",\n );\n await sleep(waitMs);\n }\n }\n\n return {\n executeWithAccountRotation,\n };\n}\n\nasync function isRevokedTokenResponse(response: Response): Promise<boolean> {\n try {\n const cloned = response.clone();\n const body = await cloned.text();\n return body.includes(\"revoked\");\n } catch {\n return false;\n }\n}\n","import { AccountStore } from \"./account-store\";\nimport type { PluginClient, PluginConfig, StoredAccount, TokenRefreshResult } from \"./types\";\nimport { getClearedOAuthBody } from \"./utils\";\n\nconst INITIAL_DELAY_MS = 5_000;\n\nexport interface ProactiveRefreshDependencies {\n providerAuthId: string;\n getConfig: () => PluginConfig;\n refreshToken: (\n currentRefreshToken: string,\n accountId: string,\n client: PluginClient,\n ) => Promise<TokenRefreshResult>;\n isTokenExpired: (account: Pick<StoredAccount, \"accessToken\" | \"expiresAt\">) => boolean;\n debugLog: (client: PluginClient, message: string, extra?: Record<string, unknown>) => void;\n}\n\nexport interface ProactiveRefreshQueueInstance {\n start(): void;\n stop(): Promise<void>;\n}\n\nexport interface ProactiveRefreshQueueClass {\n new (\n client: PluginClient,\n store: AccountStore,\n onInvalidate?: (uuid: string) => void,\n ): ProactiveRefreshQueueInstance;\n}\n\nexport function createProactiveRefreshQueueForProvider(dependencies: ProactiveRefreshDependencies): ProactiveRefreshQueueClass {\n const {\n providerAuthId,\n getConfig,\n refreshToken,\n isTokenExpired,\n debugLog,\n } = dependencies;\n\n return class ProactiveRefreshQueue {\n private timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n private runToken = 0;\n private inFlight: Promise<void> | null = null;\n\n constructor(\n private readonly client: PluginClient,\n private readonly store: AccountStore,\n private readonly onInvalidate?: (uuid: string) => void,\n ) {}\n\n start(): void {\n const config = getConfig();\n if (!config.proactive_refresh) return;\n\n this.runToken++;\n if (this.timeoutHandle) {\n clearTimeout(this.timeoutHandle);\n this.timeoutHandle = null;\n }\n this.scheduleNext(this.runToken, INITIAL_DELAY_MS);\n\n debugLog(this.client, \"Proactive refresh started\", {\n intervalSeconds: config.proactive_refresh_interval_seconds,\n bufferSeconds: config.proactive_refresh_buffer_seconds,\n });\n }\n\n async stop(): Promise<void> {\n this.runToken++;\n if (this.timeoutHandle) {\n clearTimeout(this.timeoutHandle);\n this.timeoutHandle = null;\n }\n if (this.inFlight) {\n await this.inFlight;\n this.inFlight = null;\n }\n debugLog(this.client, \"Proactive refresh stopped\");\n }\n\n private scheduleNext(token: number, delayMs: number): void {\n this.timeoutHandle = setTimeout(() => {\n if (token !== this.runToken) return;\n this.inFlight = this.runCheck(token).finally(() => {\n this.inFlight = null;\n });\n }, delayMs);\n }\n\n private needsProactiveRefresh(account: Pick<StoredAccount, \"accessToken\" | \"expiresAt\">): boolean {\n if (!account.accessToken || !account.expiresAt) return false;\n if (isTokenExpired(account)) return false;\n const bufferMs = getConfig().proactive_refresh_buffer_seconds * 1000;\n return account.expiresAt <= Date.now() + bufferMs;\n }\n\n private async runCheck(token: number): Promise<void> {\n try {\n const stored = await this.store.load();\n if (token !== this.runToken) return;\n\n const candidates = stored.accounts.filter((a) =>\n a.enabled !== false\n && !a.isAuthDisabled\n && a.uuid\n && this.needsProactiveRefresh(a),\n );\n\n if (candidates.length === 0) return;\n\n debugLog(this.client, `Proactive refresh: ${candidates.length} account(s) approaching expiry`);\n\n for (const account of candidates) {\n if (token !== this.runToken) return;\n\n const credentials = await this.store.readCredentials(account.uuid!);\n if (!credentials || !this.needsProactiveRefresh(credentials)) continue;\n\n const result = await refreshToken(credentials.refreshToken, account.uuid!, this.client);\n if (result.ok) {\n await this.store.mutateAccount(account.uuid!, (target) => {\n target.accessToken = result.patch.accessToken;\n target.expiresAt = result.patch.expiresAt;\n if (result.patch.refreshToken) target.refreshToken = result.patch.refreshToken;\n if (result.patch.uuid) target.uuid = result.patch.uuid;\n if (result.patch.email) target.email = result.patch.email;\n if (result.patch.accountId) target.accountId = result.patch.accountId;\n target.consecutiveAuthFailures = 0;\n target.isAuthDisabled = false;\n target.authDisabledReason = undefined;\n });\n this.onInvalidate?.(account.uuid!);\n } else {\n await this.persistFailure(account, result.permanent);\n }\n }\n } catch (error) {\n debugLog(this.client, `Proactive refresh check error: ${error}`);\n } finally {\n if (token === this.runToken) {\n const intervalMs = getConfig().proactive_refresh_interval_seconds * 1000;\n this.scheduleNext(token, intervalMs);\n }\n }\n }\n\n private async persistFailure(account: StoredAccount, permanent: boolean): Promise<void> {\n try {\n const accountUuid = account.uuid;\n if (!accountUuid) return;\n\n if (permanent) {\n const removed = await this.store.removeAccount(accountUuid);\n if (!removed) return;\n\n this.onInvalidate?.(accountUuid);\n await this.clearOpenCodeAuthIfNoAccountsRemain();\n return;\n }\n\n await this.store.mutateStorage((storage) => {\n const target = storage.accounts.find((entry) => entry.uuid === accountUuid);\n if (!target) return;\n\n target.consecutiveAuthFailures = (target.consecutiveAuthFailures ?? 0) + 1;\n const maxFailures = getConfig().max_consecutive_auth_failures;\n const usableCount = storage.accounts.filter(\n (entry) => entry.enabled && !entry.isAuthDisabled && entry.uuid !== accountUuid,\n ).length;\n\n if (target.consecutiveAuthFailures >= maxFailures && usableCount > 0) {\n target.isAuthDisabled = true;\n target.authDisabledReason = `${maxFailures} consecutive auth failures (proactive refresh)`;\n }\n });\n } catch {\n debugLog(this.client, `Failed to persist auth failure for ${account.uuid}`);\n }\n }\n\n private async clearOpenCodeAuthIfNoAccountsRemain(): Promise<void> {\n const storage = await this.store.load();\n if (storage.accounts.length > 0) return;\n\n await this.client.auth\n .set({\n path: { id: providerAuthId },\n body: getClearedOAuthBody(),\n })\n .catch(() => {});\n }\n };\n}\n","import type { ManagedAccount, PluginClient, PluginConfig, UsageLimits } from \"./types\";\n\nconst USAGE_FETCH_COOLDOWN_MS = 30_000;\n\nexport interface RateLimitDependencies {\n fetchUsage: (accessToken: string, accountId?: string) => Promise<{ ok: true; data: UsageLimits } | { ok: false; reason: string }>;\n getConfig: () => Pick<PluginConfig, \"default_retry_after_ms\">;\n formatWaitTime: (ms: number) => string;\n getAccountLabel: (account: ManagedAccount) => string;\n showToast: (\n client: PluginClient,\n message: string,\n variant: \"info\" | \"warning\" | \"success\" | \"error\",\n ) => Promise<void>;\n}\n\nexport interface RateLimitAccountManager {\n markRateLimited(uuid: string, backoffMs?: number): Promise<void>;\n applyUsageCache(uuid: string, usage: UsageLimits): Promise<void>;\n getAccountCount(): number;\n}\n\nexport function createRateLimitHandlers(dependencies: RateLimitDependencies) {\n const {\n fetchUsage,\n getConfig,\n formatWaitTime,\n getAccountLabel,\n showToast,\n } = dependencies;\n\n function retryAfterMsFromResponse(response: Response): number {\n const retryAfterMs = response.headers.get(\"retry-after-ms\");\n if (retryAfterMs) {\n const parsed = parseInt(retryAfterMs, 10);\n if (!isNaN(parsed) && parsed > 0) return parsed;\n }\n\n const retryAfter = response.headers.get(\"retry-after\");\n if (retryAfter) {\n const parsed = parseInt(retryAfter, 10);\n if (!isNaN(parsed) && parsed > 0) return parsed * 1000;\n }\n\n return getConfig().default_retry_after_ms;\n }\n\n function getResetMsFromUsage(account: ManagedAccount): number | null {\n const usage = account.cachedUsage;\n if (!usage) return null;\n\n const now = Date.now();\n const candidates: number[] = [];\n\n if (usage.five_hour?.resets_at) {\n const ms = Date.parse(usage.five_hour.resets_at) - now;\n if (ms > 0) candidates.push(ms);\n }\n if (usage.seven_day?.resets_at) {\n const ms = Date.parse(usage.seven_day.resets_at) - now;\n if (ms > 0) candidates.push(ms);\n }\n\n return candidates.length > 0 ? Math.min(...candidates) : null;\n }\n\n async function fetchUsageLimits(accessToken: string, accountId?: string): Promise<UsageLimits | null> {\n if (!accessToken) return null;\n try {\n const result = await fetchUsage(accessToken, accountId);\n return result.ok ? result.data : null;\n } catch {\n return null;\n }\n }\n\n async function handleRateLimitResponse(\n manager: RateLimitAccountManager,\n client: PluginClient,\n account: ManagedAccount,\n response: Response,\n ): Promise<void> {\n if (!account.uuid) return;\n\n const resetMs = getResetMsFromUsage(account) ?? retryAfterMsFromResponse(response);\n await manager.markRateLimited(account.uuid, resetMs);\n\n const shouldFetchUsage = account.accessToken\n && (!account.cachedUsageAt || Date.now() - account.cachedUsageAt > USAGE_FETCH_COOLDOWN_MS);\n\n if (shouldFetchUsage) {\n const usage = await fetchUsageLimits(account.accessToken!, account.accountId);\n if (usage) {\n await manager.applyUsageCache(account.uuid, usage);\n }\n }\n\n if (manager.getAccountCount() > 1) {\n void showToast(\n client,\n `${getAccountLabel(account)} rate-limited (resets in ${formatWaitTime(resetMs)}). Switching...`,\n \"warning\",\n );\n }\n }\n\n return {\n retryAfterMsFromResponse,\n getResetMsFromUsage,\n fetchUsageLimits,\n handleRateLimitResponse,\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getConfigDir } from \"./utils\";\nimport type { AccountStore } from \"./account-store\";\n\nconst AUTH_JSON_FILENAME = \"auth.json\";\n\ninterface AuthJsonCredential {\n type: string;\n refresh: string;\n access?: string;\n expires?: number;\n}\n\nfunction isValidOAuthCredential(value: unknown): value is AuthJsonCredential {\n if (typeof value !== \"object\" || value === null) return false;\n\n const candidate = value as Record<string, unknown>;\n return (\n candidate.type === \"oauth\" &&\n typeof candidate.refresh === \"string\" &&\n candidate.refresh.length > 0\n );\n}\n\nfunction resolveAuthJsonPath(): string {\n return join(getConfigDir(), AUTH_JSON_FILENAME);\n}\n\nasync function readAuthJson(): Promise<Record<string, unknown> | null> {\n const authPath = resolveAuthJsonPath();\n\n let content: string;\n try {\n content = await fs.readFile(authPath, \"utf-8\");\n } catch {\n return null;\n }\n\n try {\n const parsed = JSON.parse(content);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return null;\n }\n return parsed as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\n/**\n * Imports an existing OAuth credential from OpenCode's auth.json\n * into the multi-account storage on first use.\n *\n * Only runs when storage has zero accounts. Does not modify auth.json.\n *\n * @param providerKey - The key in auth.json (\"anthropic\" or \"openai\")\n * @param store - The AccountStore instance to import into\n * @returns true if a credential was imported, false otherwise\n */\nexport async function migrateFromAuthJson(\n providerKey: string,\n store: AccountStore,\n): Promise<boolean> {\n const storage = await store.load();\n const hasExistingAccounts = storage.accounts.length > 0;\n if (hasExistingAccounts) return false;\n\n const authData = await readAuthJson();\n if (!authData) return false;\n\n const providerCredential = authData[providerKey];\n if (!isValidOAuthCredential(providerCredential)) return false;\n\n const now = Date.now();\n const newAccount = {\n uuid: crypto.randomUUID(),\n refreshToken: providerCredential.refresh,\n accessToken: providerCredential.access,\n expiresAt: providerCredential.expires,\n addedAt: now,\n lastUsed: now,\n enabled: true,\n planTier: \"\",\n consecutiveAuthFailures: 0,\n isAuthDisabled: false,\n };\n\n await store.addAccount(newAccount);\n await store.setActiveUuid(newAccount.uuid);\n\n return true;\n}\n","export const ANSI = {\n hide: \"\\x1b[?25l\",\n show: \"\\x1b[?25h\",\n up: (n = 1) => `\\x1b[${n}A`,\n down: (n = 1) => `\\x1b[${n}B`,\n clearLine: \"\\x1b[2K\",\n\n cyan: \"\\x1b[36m\",\n green: \"\\x1b[32m\",\n red: \"\\x1b[31m\",\n yellow: \"\\x1b[33m\",\n dim: \"\\x1b[2m\",\n bold: \"\\x1b[1m\",\n reset: \"\\x1b[0m\",\n} as const;\n\nexport type KeyAction = \"up\" | \"down\" | \"enter\" | \"escape\" | \"escape-start\" | null;\n\nexport function parseKey(data: Buffer): KeyAction {\n const s = data.toString();\n\n // Standard: \\x1b[A / Application mode: \\x1bOA\n if (s === \"\\x1b[A\" || s === \"\\x1bOA\") return \"up\";\n if (s === \"\\x1b[B\" || s === \"\\x1bOB\") return \"down\";\n\n if (s === \"\\r\" || s === \"\\n\") return \"enter\";\n if (s === \"\\x03\") return \"escape\";\n\n // Bare escape byte — may be start of arrow key sequence\n if (s === \"\\x1b\") return \"escape-start\";\n\n return null;\n}\n\nexport function isTTY(): boolean {\n return Boolean(process.stdin.isTTY);\n}\n","import { ANSI, isTTY, parseKey } from \"./ansi\";\n\nexport interface MenuItem<T = string> {\n label: string;\n value: T;\n hint?: string;\n disabled?: boolean;\n separator?: boolean;\n color?: \"red\" | \"green\" | \"yellow\" | \"cyan\";\n}\n\nexport interface SelectOptions {\n message: string;\n subtitle?: string;\n}\n\nconst ESCAPE_TIMEOUT_MS = 50;\n\nconst COLOR_MAP: Record<string, string> = {\n red: ANSI.red,\n green: ANSI.green,\n yellow: ANSI.yellow,\n cyan: ANSI.cyan,\n};\n\nexport async function select<T>(\n items: MenuItem<T>[],\n options: SelectOptions,\n): Promise<T | null> {\n if (!isTTY()) {\n throw new Error(\"Interactive select requires a TTY terminal\");\n }\n\n const enabledItems = items.filter((i) => !i.disabled && !i.separator);\n if (enabledItems.length === 0) {\n throw new Error(\"All items disabled\");\n }\n\n if (enabledItems.length === 1) {\n return enabledItems[0]!.value;\n }\n\n const { message, subtitle } = options;\n const { stdin, stdout } = process;\n\n let cursor = items.findIndex((i) => !i.disabled && !i.separator);\n if (cursor === -1) cursor = 0;\n let escapeTimeout: ReturnType<typeof setTimeout> | null = null;\n let isCleanedUp = false;\n let isFirstRender = true;\n\n const getTotalLines = (): number => {\n const subtitleLines = subtitle ? 3 : 0;\n return 1 + subtitleLines + items.length + 1 + 1;\n };\n\n const renderItemLabel = (item: MenuItem<T>, isSelected: boolean): string => {\n const colorCode = item.color ? (COLOR_MAP[item.color] ?? \"\") : \"\";\n\n if (item.disabled) {\n return `${ANSI.dim}${item.label} (unavailable)${ANSI.reset}`;\n }\n\n const hintSuffix = item.hint ? ` ${ANSI.dim}${item.hint}${ANSI.reset}` : \"\";\n\n if (isSelected) {\n const label = colorCode ? `${colorCode}${item.label}${ANSI.reset}` : item.label;\n return `${label}${hintSuffix}`;\n }\n\n const dimLabel = colorCode\n ? `${ANSI.dim}${colorCode}${item.label}${ANSI.reset}`\n : `${ANSI.dim}${item.label}${ANSI.reset}`;\n return `${dimLabel}${hintSuffix}`;\n };\n\n const render = () => {\n const totalLines = getTotalLines();\n\n if (!isFirstRender) {\n stdout.write(ANSI.up(totalLines) + \"\\r\");\n }\n isFirstRender = false;\n\n stdout.write(`${ANSI.clearLine}${ANSI.dim}\\u250c ${ANSI.reset}${message}\\n`);\n\n if (subtitle) {\n stdout.write(`${ANSI.clearLine}${ANSI.dim}\\u2502${ANSI.reset}\\n`);\n stdout.write(`${ANSI.clearLine}${ANSI.cyan}\\u25c6${ANSI.reset} ${subtitle}\\n`);\n stdout.write(`${ANSI.clearLine}\\n`);\n }\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (!item) continue;\n\n if (item.separator) {\n stdout.write(`${ANSI.clearLine}${ANSI.dim}\\u2502${ANSI.reset}\\n`);\n continue;\n }\n\n const isSelected = i === cursor;\n const labelText = renderItemLabel(item, isSelected);\n const bullet = isSelected\n ? `${ANSI.green}\\u25cf${ANSI.reset}`\n : `${ANSI.dim}\\u25cb${ANSI.reset}`;\n\n stdout.write(`${ANSI.clearLine}${ANSI.cyan}\\u2502${ANSI.reset} ${bullet} ${labelText}\\n`);\n }\n\n stdout.write(`${ANSI.clearLine}${ANSI.cyan}\\u2502${ANSI.reset} ${ANSI.dim}\\u2191/\\u2193 to select \\u2022 Enter: confirm${ANSI.reset}\\n`);\n stdout.write(`${ANSI.clearLine}${ANSI.cyan}\\u2514${ANSI.reset}\\n`);\n };\n\n return new Promise((resolve) => {\n const wasRaw = stdin.isRaw ?? false;\n\n const cleanup = () => {\n if (isCleanedUp) return;\n isCleanedUp = true;\n\n if (escapeTimeout) {\n clearTimeout(escapeTimeout);\n escapeTimeout = null;\n }\n\n try {\n stdin.removeListener(\"data\", onKey);\n stdin.setRawMode(wasRaw);\n stdin.pause();\n stdout.write(ANSI.show);\n } catch {\n // best-effort cleanup\n }\n\n process.removeListener(\"SIGINT\", onSignal);\n process.removeListener(\"SIGTERM\", onSignal);\n };\n\n const onSignal = () => {\n cleanup();\n resolve(null);\n };\n\n const finishWithValue = (value: T | null) => {\n cleanup();\n resolve(value);\n };\n\n const findNextSelectable = (from: number, direction: 1 | -1): number => {\n if (items.length === 0) return from;\n let next = from;\n do {\n next = (next + direction + items.length) % items.length;\n } while (items[next]?.disabled || items[next]?.separator);\n return next;\n };\n\n const onKey = (data: Buffer) => {\n if (escapeTimeout) {\n clearTimeout(escapeTimeout);\n escapeTimeout = null;\n }\n\n const action = parseKey(data);\n\n switch (action) {\n case \"up\":\n cursor = findNextSelectable(cursor, -1);\n render();\n return;\n case \"down\":\n cursor = findNextSelectable(cursor, 1);\n render();\n return;\n case \"enter\":\n finishWithValue(items[cursor]?.value ?? null);\n return;\n case \"escape\":\n finishWithValue(null);\n return;\n case \"escape-start\":\n escapeTimeout = setTimeout(() => {\n finishWithValue(null);\n }, ESCAPE_TIMEOUT_MS);\n return;\n default:\n return;\n }\n };\n\n process.once(\"SIGINT\", onSignal);\n process.once(\"SIGTERM\", onSignal);\n\n try {\n stdin.setRawMode(true);\n } catch {\n cleanup();\n resolve(null);\n return;\n }\n\n stdin.resume();\n stdout.write(ANSI.hide);\n render();\n\n stdin.on(\"data\", onKey);\n });\n}\n","import { select } from \"./select\";\n\nexport async function confirm(message: string, defaultYes = false): Promise<boolean> {\n const items = defaultYes\n ? [\n { label: \"Yes\", value: true },\n { label: \"No\", value: false },\n ]\n : [\n { label: \"No\", value: false },\n { label: \"Yes\", value: true },\n ];\n\n const result = await select(items, { message });\n return result ?? false;\n}\n","import type { OAuthAdapter } from \"./types\";\n\nexport const anthropicOAuthAdapter: OAuthAdapter = {\n id: \"anthropic\",\n authProviderId: \"anthropic\",\n modelDisplayName: \"Claude\",\n statusToolName: \"claude_multiauth_status\",\n authMethodLabel: \"Claude Pro/Max (Multi-Auth)\",\n serviceLogName: \"claude-multiauth\",\n oauthClientId: \"9d1c250a-e61b-44d9-88ed-5944d1962f5e\",\n tokenEndpoint: \"https://console.anthropic.com/v1/oauth/token\",\n usageEndpoint: \"https://api.anthropic.com/api/oauth/usage\",\n profileEndpoint: \"https://api.anthropic.com/api/oauth/profile\",\n oauthBetaHeader: \"oauth-2025-04-20\",\n requestBetaHeader: \"oauth-2025-04-20,interleaved-thinking-2025-05-14\",\n cliUserAgent: \"claude-cli/2.1.2 (external, cli)\",\n cliVersion: \"2.1.80\",\n billingSalt: \"59cf53e54c78\",\n toolPrefix: \"mcp_\",\n accountStorageFilename: \"anthropic-multi-account-accounts.json\",\n transform: {\n rewriteOpenCodeBranding: true,\n addToolPrefix: true,\n stripToolPrefixInResponse: true,\n enableMessagesBetaQuery: true,\n },\n planLabels: {\n max: \"Claude Max\",\n pro: \"Claude Pro\",\n free: \"Free\",\n },\n supported: true,\n};\n","import type { OAuthAdapter } from \"./types\";\n\nconst ISSUER = \"https://auth.openai.com\";\n\nexport const openAIOAuthAdapter: OAuthAdapter = {\n id: \"openai\",\n authProviderId: \"openai\",\n modelDisplayName: \"ChatGPT\",\n statusToolName: \"chatgpt_multiauth_status\",\n authMethodLabel: \"ChatGPT Plus/Pro (Multi-Auth)\",\n serviceLogName: \"chatgpt-multiauth\",\n oauthClientId: \"app_EMoamEEZ73f0CkXaXp7hrann\",\n tokenEndpoint: `${ISSUER}/oauth/token`,\n usageEndpoint: \"\",\n profileEndpoint: \"\",\n oauthBetaHeader: \"\",\n requestBetaHeader: \"\",\n cliUserAgent: \"opencode/1.1.53\",\n cliVersion: \"\",\n billingSalt: \"\",\n toolPrefix: \"mcp_\",\n accountStorageFilename: \"openai-multi-account-accounts.json\",\n transform: {\n rewriteOpenCodeBranding: false,\n addToolPrefix: false,\n stripToolPrefixInResponse: false,\n enableMessagesBetaQuery: false,\n },\n planLabels: {\n pro: \"ChatGPT Pro\",\n plus: \"ChatGPT Plus\",\n go: \"ChatGPT Go\",\n free: \"Free\",\n },\n supported: true,\n};\n","import * as v from \"valibot\";\n\n// ─── Valibot Schemas (disk-persisted config) ─────────────────────\n\nexport const PoolConfigSchema = v.object({\n name: v.string(),\n baseProvider: v.string(),\n members: v.array(v.string()),\n enabled: v.boolean(),\n});\n\nexport const ChainEntryConfigSchema = v.object({\n pool: v.string(),\n model: v.optional(v.string()),\n enabled: v.boolean(),\n});\n\nexport const ChainConfigSchema = v.object({\n name: v.string(),\n entries: v.array(ChainEntryConfigSchema),\n enabled: v.boolean(),\n});\n\nexport const PoolChainConfigSchema = v.object({\n pools: v.optional(v.array(PoolConfigSchema), []),\n chains: v.optional(v.array(ChainConfigSchema), []),\n});\n\n// ─── Inferred Types (from schemas) ───────────────────────────────\n\nexport type PoolConfig = v.InferOutput<typeof PoolConfigSchema>;\nexport type ChainEntryConfig = v.InferOutput<typeof ChainEntryConfigSchema>;\nexport type ChainConfig = v.InferOutput<typeof ChainConfigSchema>;\nexport type PoolChainConfig = v.InferOutput<typeof PoolChainConfigSchema>;\n\n// In-memory cascade state (NOT persisted)\nexport interface CascadeState {\n prompt: string;\n attemptedAccounts: Set<string>;\n visitedChainIndexes: Set<number>;\n}\n\n// Candidate for failover rotation\nexport interface FailoverCandidate {\n poolName: string;\n accountUuid: string;\n source: \"pool\" | \"chain\";\n chainIndex?: number;\n}\n\n// Skipped entry during failover planning\nexport interface FailoverSkip {\n type: \"pool_exhausted\" | \"chain_disabled\" | \"account_attempted\" | \"account_unavailable\";\n poolName: string;\n reason: string;\n detail?: string;\n}\n","import { promises as fs } from \"node:fs\";\nimport { randomBytes } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\nimport * as v from \"valibot\";\nimport { withDirectoryLock } from \"./file-lock\";\nimport { getConfigDir, getErrorCode } from \"./utils\";\nimport { PoolChainConfigSchema } from \"./pool-types\";\nimport type { PoolChainConfig } from \"./pool-types\";\n\nconst POOL_CONFIG_FILENAME = \"multiauth-pools.json\";\nconst FILE_MODE = 0o600;\n\nfunction createEmptyConfig(): PoolChainConfig {\n return { pools: [], chains: [] };\n}\n\nfunction getGlobalConfigPath(): string {\n return join(getConfigDir(), POOL_CONFIG_FILENAME);\n}\n\nfunction buildTempPath(targetPath: string): string {\n return `${targetPath}.${randomBytes(8).toString(\"hex\")}.tmp`;\n}\n\nasync function resolveConfigPath(): Promise<string> {\n const projectPath = join(process.cwd(), \".opencode\", POOL_CONFIG_FILENAME);\n try {\n await fs.access(projectPath);\n return projectPath;\n } catch {\n }\n return getGlobalConfigPath();\n}\n\nasync function ensureConfigFileExists(targetPath: string): Promise<void> {\n await fs.mkdir(dirname(targetPath), { recursive: true });\n const emptyContent = `${JSON.stringify(createEmptyConfig(), null, 2)}\\n`;\n try {\n await fs.writeFile(targetPath, emptyContent, { flag: \"wx\", mode: FILE_MODE });\n } catch (error) {\n if (getErrorCode(error) !== \"EEXIST\") throw error;\n }\n}\n\nasync function writeAtomicText(targetPath: string, content: string): Promise<void> {\n await fs.mkdir(dirname(targetPath), { recursive: true });\n const tempPath = buildTempPath(targetPath);\n try {\n await fs.writeFile(tempPath, content, { encoding: \"utf-8\", mode: FILE_MODE });\n await fs.chmod(tempPath, FILE_MODE);\n await fs.rename(tempPath, targetPath);\n await fs.chmod(targetPath, FILE_MODE);\n } catch (error) {\n try {\n await fs.unlink(tempPath);\n } catch {}\n throw error;\n }\n}\n\nasync function withConfigLock<T>(fn: (configPath: string) => Promise<T>): Promise<T> {\n const configPath = await resolveConfigPath();\n await ensureConfigFileExists(configPath);\n return await withDirectoryLock(configPath, () => fn(configPath));\n}\n\nfunction parsePoolChainConfig(content: string): PoolChainConfig | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(content);\n } catch {\n return null;\n }\n\n const validation = v.safeParse(PoolChainConfigSchema, parsed);\n return validation.success ? validation.output : null;\n}\n\nexport async function loadPoolChainConfig(): Promise<PoolChainConfig> {\n const path = await resolveConfigPath();\n try {\n const content = await fs.readFile(path, \"utf-8\");\n return parsePoolChainConfig(content) ?? createEmptyConfig();\n } catch {\n return createEmptyConfig();\n }\n}\n\nexport async function savePoolChainConfig(config: PoolChainConfig): Promise<void> {\n await withConfigLock(async (configPath) => {\n const validation = v.safeParse(PoolChainConfigSchema, config);\n if (!validation.success) {\n throw new Error(\"Invalid pool/chain config payload\");\n }\n await writeAtomicText(configPath, `${JSON.stringify(validation.output, null, 2)}\\n`);\n });\n}\n","import type { ManagedAccount } from \"./types\";\nimport type { FailoverCandidate, FailoverSkip, PoolChainConfig, PoolConfig } from \"./pool-types\";\n\nconst DEFAULT_EXHAUSTED_COOLDOWN_MS = 5 * 60 * 1000;\n\ninterface PoolAwareAccountManager {\n getAccounts(): ManagedAccount[];\n isRateLimited(account: ManagedAccount): boolean;\n selectAccount(): Promise<ManagedAccount | null>;\n}\n\nexport interface BuildFailoverPlanOptions {\n attemptedAccounts?: Set<string>;\n visitedChainIndexes?: Set<number>;\n}\n\nexport interface FailoverPlan {\n candidates: FailoverCandidate[];\n skips: FailoverSkip[];\n}\n\nexport class PoolManager {\n private poolsByName = new Map<string, PoolConfig>();\n private exhaustedUntilByAccount = new Map<string, number>();\n private exhaustedCooldownMs: number;\n\n constructor(options?: { exhaustedCooldownMs?: number }) {\n this.exhaustedCooldownMs = options?.exhaustedCooldownMs ?? DEFAULT_EXHAUSTED_COOLDOWN_MS;\n }\n\n loadPools(configs: PoolConfig[]): void {\n this.poolsByName.clear();\n for (const pool of configs) {\n this.poolsByName.set(pool.name, pool);\n }\n }\n\n getPoolForAccount(accountUuid: string): PoolConfig | null {\n for (const pool of this.poolsByName.values()) {\n if (!pool.enabled) continue;\n if (pool.members.includes(accountUuid)) return pool;\n }\n return null;\n }\n\n getAvailableMembers(pool: PoolConfig, accountManager: PoolAwareAccountManager): string[] {\n if (!pool.enabled) return [];\n this.clearExpiredExhausted();\n\n const accountsByUuid = new Map<string, ManagedAccount>();\n for (const account of accountManager.getAccounts()) {\n if (!account.uuid) continue;\n accountsByUuid.set(account.uuid, account);\n }\n\n return pool.members.filter((accountUuid) => {\n const account = accountsByUuid.get(accountUuid);\n if (!account) return false;\n if (!account.enabled || account.isAuthDisabled) return false;\n if (this.isExhausted(accountUuid)) return false;\n if (accountManager.isRateLimited(account)) return false;\n return true;\n });\n }\n\n markExhausted(accountUuid: string): void {\n this.exhaustedUntilByAccount.set(accountUuid, Date.now() + this.exhaustedCooldownMs);\n }\n\n async getNextMember(\n pool: PoolConfig,\n currentUuid: string | undefined,\n accountManager: PoolAwareAccountManager,\n ): Promise<string | null> {\n const availableMembers = this.getAvailableMembers(pool, accountManager);\n if (availableMembers.length === 0) return null;\n\n const excluded = new Set<string>();\n if (currentUuid) excluded.add(currentUuid);\n\n const preferred = await this.selectPreferredMember(availableMembers, excluded, accountManager);\n if (preferred) return preferred;\n\n for (const candidate of availableMembers) {\n if (candidate !== currentUuid) return candidate;\n }\n\n return null;\n }\n\n async buildFailoverPlan(\n currentAccount: Pick<ManagedAccount, \"uuid\" | \"accountId\"> | null,\n config: PoolChainConfig,\n accountManager: PoolAwareAccountManager,\n options?: BuildFailoverPlanOptions,\n ): Promise<FailoverPlan> {\n this.loadPools(config.pools ?? []);\n\n if ((config.pools?.length ?? 0) === 0 && (config.chains?.length ?? 0) === 0) {\n return { candidates: [], skips: [] };\n }\n\n const attemptedAccounts = options?.attemptedAccounts ?? new Set<string>();\n const visitedChainIndexes = options?.visitedChainIndexes ?? new Set<number>();\n const currentUuid = currentAccount?.uuid;\n\n const candidates: FailoverCandidate[] = [];\n const skips: FailoverSkip[] = [];\n const addedCandidateUuids = new Set<string>();\n\n const appendPoolCandidates = async (\n poolName: string,\n source: \"pool\" | \"chain\",\n chainIndex?: number,\n ): Promise<void> => {\n const pool = this.poolsByName.get(poolName);\n if (!pool || !pool.enabled) {\n skips.push({\n type: \"chain_disabled\",\n poolName,\n reason: \"Pool is missing or disabled\",\n });\n return;\n }\n\n const available = this.getAvailableMembers(pool, accountManager);\n if (available.length === 0) {\n skips.push({\n type: \"pool_exhausted\",\n poolName,\n reason: \"No available members\",\n });\n return;\n }\n\n const poolExclusions = new Set<string>();\n if (currentUuid) poolExclusions.add(currentUuid);\n\n while (poolExclusions.size < available.length + (currentUuid ? 1 : 0)) {\n const nextMember = await this.selectPreferredMember(available, poolExclusions, accountManager);\n if (!nextMember) break;\n\n poolExclusions.add(nextMember);\n\n if (attemptedAccounts.has(nextMember)) {\n skips.push({\n type: \"account_attempted\",\n poolName,\n reason: \"Already attempted in this cascade\",\n detail: nextMember,\n });\n continue;\n }\n\n if (addedCandidateUuids.has(nextMember)) continue;\n\n candidates.push({\n poolName,\n accountUuid: nextMember,\n source,\n chainIndex,\n });\n addedCandidateUuids.add(nextMember);\n }\n\n for (const memberUuid of available) {\n if (poolExclusions.has(memberUuid)) continue;\n if (attemptedAccounts.has(memberUuid)) {\n skips.push({\n type: \"account_attempted\",\n poolName,\n reason: \"Already attempted in this cascade\",\n detail: memberUuid,\n });\n continue;\n }\n if (addedCandidateUuids.has(memberUuid)) continue;\n\n candidates.push({\n poolName,\n accountUuid: memberUuid,\n source,\n chainIndex,\n });\n addedCandidateUuids.add(memberUuid);\n }\n };\n\n if (currentUuid) {\n const currentPool = this.getPoolForAccount(currentUuid);\n if (currentPool) {\n await appendPoolCandidates(currentPool.name, \"pool\");\n }\n }\n\n let flattenedChainIndex = 0;\n for (const chain of config.chains ?? []) {\n if (!chain.enabled) {\n for (let i = 0; i < chain.entries.length; i++) {\n skips.push({\n type: \"chain_disabled\",\n poolName: chain.entries[i]?.pool ?? chain.name,\n reason: `Chain '${chain.name}' is disabled`,\n });\n flattenedChainIndex += 1;\n }\n continue;\n }\n\n for (const entry of chain.entries) {\n if (visitedChainIndexes.has(flattenedChainIndex)) {\n skips.push({\n type: \"chain_disabled\",\n poolName: entry.pool,\n reason: \"Chain entry already visited in this cascade\",\n detail: `${flattenedChainIndex}`,\n });\n flattenedChainIndex += 1;\n continue;\n }\n\n if (!entry.enabled) {\n skips.push({\n type: \"chain_disabled\",\n poolName: entry.pool,\n reason: \"Chain entry is disabled\",\n detail: `${flattenedChainIndex}`,\n });\n flattenedChainIndex += 1;\n continue;\n }\n\n await appendPoolCandidates(entry.pool, \"chain\", flattenedChainIndex);\n flattenedChainIndex += 1;\n }\n }\n\n return { candidates, skips };\n }\n\n private isExhausted(accountUuid: string): boolean {\n const exhaustedUntil = this.exhaustedUntilByAccount.get(accountUuid);\n if (!exhaustedUntil) return false;\n if (Date.now() >= exhaustedUntil) {\n this.exhaustedUntilByAccount.delete(accountUuid);\n return false;\n }\n return true;\n }\n\n private clearExpiredExhausted(): void {\n const now = Date.now();\n for (const [accountUuid, exhaustedUntil] of this.exhaustedUntilByAccount.entries()) {\n if (now >= exhaustedUntil) this.exhaustedUntilByAccount.delete(accountUuid);\n }\n }\n\n private async selectPreferredMember(\n availableMembers: string[],\n excludedMembers: Set<string>,\n accountManager: PoolAwareAccountManager,\n ): Promise<string | null> {\n const availableSet = new Set(availableMembers);\n const maxAttempts = Math.max(availableMembers.length * 2, 6);\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const selected = await accountManager.selectAccount();\n if (!selected?.uuid) continue;\n if (!availableSet.has(selected.uuid)) continue;\n if (excludedMembers.has(selected.uuid)) continue;\n return selected.uuid;\n }\n\n for (const memberUuid of availableMembers) {\n if (!excludedMembers.has(memberUuid)) return memberUuid;\n }\n return null;\n }\n}\n","import type { CascadeState } from \"./pool-types\";\n\nfunction createCascadeState(prompt: string, currentAccountUuid?: string): CascadeState {\n const attemptedAccounts = new Set<string>();\n if (currentAccountUuid) {\n attemptedAccounts.add(currentAccountUuid);\n }\n\n return {\n prompt,\n attemptedAccounts,\n visitedChainIndexes: new Set<number>(),\n };\n}\n\nexport class CascadeStateManager {\n public suppressNextStartTurn = false;\n private cascadeState: CascadeState | null = null;\n\n startTurn(prompt: string, currentAccountUuid?: string): CascadeState {\n if (this.suppressNextStartTurn) {\n this.suppressNextStartTurn = false;\n return this.ensureCascadeState(prompt, currentAccountUuid);\n }\n\n const shouldReset = !this.cascadeState || this.cascadeState.prompt !== prompt;\n if (shouldReset) {\n this.cascadeState = createCascadeState(prompt, currentAccountUuid);\n return this.cascadeState;\n }\n\n return this.ensureCascadeState(prompt, currentAccountUuid);\n }\n\n ensureCascadeState(prompt: string, currentAccountUuid?: string): CascadeState {\n if (!this.cascadeState || this.cascadeState.prompt !== prompt) {\n this.cascadeState = createCascadeState(prompt, currentAccountUuid);\n return this.cascadeState;\n }\n\n if (currentAccountUuid) {\n this.cascadeState.attemptedAccounts.add(currentAccountUuid);\n }\n\n return this.cascadeState;\n }\n\n markAttempted(accountUuid: string): void {\n if (!this.cascadeState) return;\n this.cascadeState.attemptedAccounts.add(accountUuid);\n }\n\n markVisitedChainIndex(index: number): void {\n if (!this.cascadeState) return;\n this.cascadeState.visitedChainIndexes.add(index);\n }\n\n clearCascadeState(): void {\n this.cascadeState = null;\n this.suppressNextStartTurn = false;\n }\n\n getSnapshot(): CascadeState | null {\n if (!this.cascadeState) return null;\n return {\n prompt: this.cascadeState.prompt,\n attemptedAccounts: new Set(this.cascadeState.attemptedAccounts),\n visitedChainIndexes: new Set(this.cascadeState.visitedChainIndexes),\n };\n }\n}\n"],"mappings":"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","names":["fs","randomBytes","dirname","join","join","homedir","v","content","getConfigDir","join","homedir","join","getConfigDir","randomBytes","fs","dirname","fs","randomBytes","dirname","join","v","fs","dirname","join","v","join","getConfigDir","fs","dirname","fs","dirname","sleep","join","getConfigDir","randomBytes","fs","dirname","formatWaitTime","sleep","showToast","getAccountLabel","getConfig","debugLog","getConfig","formatWaitTime","getAccountLabel","showToast","fs","join","join","getConfigDir","fs","v","fs","randomBytes","dirname","join","v","FILE_MODE","join","getConfigDir","buildTempPath","randomBytes","fs","dirname","writeAtomicText"]}
1
+ {"version":3,"sources":["../src/account-manager.ts","../src/claims.ts","../src/utils.ts","../src/config.ts","../src/types.ts","../src/account-store.ts","../src/storage.ts","../src/constants.ts","../src/file-lock.ts","../src/executor.ts","../src/proactive-refresh.ts","../src/rate-limit.ts","../src/auth-migration.ts","../src/ui/ansi.ts","../src/ui/select.ts","../src/ui/confirm.ts","../src/adapters/anthropic.ts","../src/adapters/openai.ts","../src/pool-types.ts","../src/pool-config-store.ts","../src/pool-manager.ts","../src/cascade-state.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { readClaims, writeClaim, isClaimedByOther, type ClaimsMap } from \"./claims\";\nimport { getConfig } from \"./config\";\nimport { getClearedOAuthBody } from \"./utils\";\nimport type { AccountStore } from \"./account-store\";\nimport type {\n ManagedAccount,\n OAuthCredentials,\n PluginClient,\n PluginConfig,\n StoredAccount,\n TokenRefreshResult,\n UsageLimits,\n} from \"./types\";\n\nconst STARTUP_REFRESH_CONCURRENCY = 3;\nconst RECENT_429_COOLDOWN_MS = 30_000;\nconst HYBRID_SWITCH_MARGIN = 40;\n\nexport interface ProfileData {\n email?: string;\n planTier: string;\n}\n\nexport interface RuntimeFactoryLike {\n invalidate(uuid: string): void;\n}\n\nexport interface AccountManagerDependencies {\n providerAuthId: string;\n getConfig?: () => Pick<PluginConfig, \"soft_quota_threshold_percent\" | \"cross_process_claims\" | \"account_selection_strategy\" | \"max_consecutive_auth_failures\" | \"rate_limit_min_backoff_ms\">;\n isTokenExpired: (account: Pick<ManagedAccount, \"accessToken\" | \"expiresAt\">) => boolean;\n refreshToken: (\n currentRefreshToken: string,\n accountId: string,\n client: PluginClient,\n ) => Promise<TokenRefreshResult>;\n readClaims?: () => Promise<ClaimsMap>;\n writeClaim?: (accountId: string) => Promise<void>;\n isClaimedByOther?: (claims: ClaimsMap, accountId: string | undefined) => boolean;\n}\n\nexport interface AccountManagerInstance {\n initialize(currentAuth: OAuthCredentials, client?: PluginClient): Promise<void>;\n refresh(): Promise<void>;\n getAccountCount(): number;\n getAccounts(): ManagedAccount[];\n getActiveAccount(): ManagedAccount | null;\n setClient(client: PluginClient): void;\n setRuntimeFactory(factory: RuntimeFactoryLike): void;\n hasAnyUsableAccount(): boolean;\n isRateLimited(account: ManagedAccount): boolean;\n clearExpiredRateLimits(): void;\n getMinWaitTime(): number;\n selectAccount(): Promise<ManagedAccount | null>;\n markRateLimited(uuid: string, backoffMs?: number): Promise<void>;\n markRevoked(uuid: string): Promise<void>;\n markSuccess(uuid: string): Promise<void>;\n markAuthFailure(uuid: string, result: TokenRefreshResult): Promise<void>;\n applyUsageCache(uuid: string, usage: UsageLimits): Promise<void>;\n applyProfileCache(uuid: string, profile: ProfileData): Promise<void>;\n ensureValidToken(uuid: string, client: PluginClient): Promise<TokenRefreshResult>;\n validateNonActiveTokens(client: PluginClient): Promise<void>;\n removeAccount(index: number): Promise<boolean>;\n clearAllAccounts(): Promise<void>;\n addAccount(auth: OAuthCredentials, email?: string): Promise<void>;\n toggleEnabled(uuid: string): Promise<void>;\n replaceAccountCredentials(uuid: string, auth: OAuthCredentials): Promise<void>;\n retryAuth(uuid: string, client: PluginClient): Promise<TokenRefreshResult>;\n}\n\nexport interface AccountManagerClass {\n new (store: AccountStore): AccountManagerInstance;\n create(store: AccountStore, currentAuth: OAuthCredentials, client?: PluginClient): Promise<AccountManagerInstance>;\n}\n\nexport function createAccountManagerForProvider(dependencies: AccountManagerDependencies): AccountManagerClass {\n const {\n providerAuthId,\n getConfig: getProviderConfig = getConfig,\n isTokenExpired,\n refreshToken,\n readClaims: readProviderClaims = readClaims,\n writeClaim: writeProviderClaim = writeClaim,\n isClaimedByOther: isClaimedByOtherProvider = isClaimedByOther,\n } = dependencies;\n\n return class AccountManager {\n private cached: ManagedAccount[] = [];\n private activeAccountUuid?: string;\n private client: PluginClient | null = null;\n private runtimeFactory: RuntimeFactoryLike | null = null;\n private roundRobinCursor = 0;\n private last429Map = new Map<string, number>();\n\n constructor(private store: AccountStore) {}\n\n static async create(\n store: AccountStore,\n currentAuth: OAuthCredentials,\n client?: PluginClient,\n ): Promise<AccountManager> {\n const manager = new AccountManager(store);\n await manager.initialize(currentAuth, client);\n return manager;\n }\n\n async initialize(currentAuth: OAuthCredentials, client?: PluginClient): Promise<void> {\n if (client) this.client = client;\n\n const storage = await this.store.load();\n if (storage.accounts.length > 0) {\n this.cached = storage.accounts.map((account, index) => this.toManagedAccount(account, index));\n this.activeAccountUuid = storage.activeAccountUuid;\n if (!this.getActiveAccount() && this.cached.length > 0) {\n this.activeAccountUuid = this.cached[0]!.uuid;\n }\n return;\n }\n\n if (currentAuth.refresh) {\n const newAccount = this.createNewAccount(currentAuth, Date.now());\n await this.store.addAccount(newAccount);\n await this.store.setActiveUuid(newAccount.uuid);\n this.cached = [this.toManagedAccount(newAccount, 0)];\n this.activeAccountUuid = newAccount.uuid;\n }\n }\n\n async refresh(): Promise<void> {\n const storage = await this.store.load();\n this.cached = storage.accounts.map((account, index) => this.toManagedAccount(account, index));\n if (storage.activeAccountUuid) {\n this.activeAccountUuid = storage.activeAccountUuid;\n }\n }\n\n private toManagedAccount(storedAccount: StoredAccount, index: number): ManagedAccount {\n return {\n index,\n uuid: storedAccount.uuid,\n accountId: storedAccount.accountId,\n label: storedAccount.label,\n email: storedAccount.email,\n planTier: storedAccount.planTier,\n refreshToken: storedAccount.refreshToken,\n accessToken: storedAccount.accessToken,\n expiresAt: storedAccount.expiresAt,\n addedAt: storedAccount.addedAt,\n lastUsed: storedAccount.lastUsed,\n enabled: storedAccount.enabled,\n rateLimitResetAt: storedAccount.rateLimitResetAt,\n cachedUsage: storedAccount.cachedUsage,\n cachedUsageAt: storedAccount.cachedUsageAt,\n consecutiveAuthFailures: storedAccount.consecutiveAuthFailures,\n isAuthDisabled: storedAccount.isAuthDisabled,\n authDisabledReason: storedAccount.authDisabledReason,\n last429At: storedAccount.uuid ? this.last429Map.get(storedAccount.uuid) : undefined,\n };\n }\n\n private createNewAccount(auth: OAuthCredentials, now: number): StoredAccount {\n return {\n uuid: randomUUID(),\n refreshToken: auth.refresh,\n accessToken: auth.access,\n expiresAt: auth.expires,\n addedAt: now,\n lastUsed: now,\n enabled: true,\n planTier: \"\",\n consecutiveAuthFailures: 0,\n isAuthDisabled: false,\n };\n }\n\n getAccountCount(): number {\n return this.getEligibleAccounts().length;\n }\n\n getAccounts(): ManagedAccount[] {\n return [...this.cached];\n }\n\n getActiveAccount(): ManagedAccount | null {\n if (this.activeAccountUuid) {\n return this.cached.find((account) => account.uuid === this.activeAccountUuid) ?? null;\n }\n return this.cached[0] ?? null;\n }\n\n setClient(client: PluginClient): void {\n this.client = client;\n }\n\n setRuntimeFactory(factory: RuntimeFactoryLike): void {\n this.runtimeFactory = factory;\n }\n\n private getEligibleAccounts(): ManagedAccount[] {\n return this.cached.filter((account) => account.uuid && account.enabled && !account.isAuthDisabled);\n }\n\n private exceedsSoftQuota(account: ManagedAccount): boolean {\n const threshold = getProviderConfig().soft_quota_threshold_percent;\n if (threshold >= 100) return false;\n\n const usage = account.cachedUsage;\n if (!usage) return false;\n\n const tiers = [usage.five_hour, usage.seven_day];\n return tiers.some((tier) => tier != null && tier.utilization >= threshold);\n }\n\n hasAnyUsableAccount(): boolean {\n return this.getEligibleAccounts().length > 0;\n }\n\n isRateLimited(account: ManagedAccount): boolean {\n if (account.rateLimitResetAt && Date.now() < account.rateLimitResetAt) {\n return true;\n }\n return this.isUsageExhausted(account);\n }\n\n private isUsageExhausted(account: ManagedAccount): boolean {\n const usage = account.cachedUsage;\n if (!usage) return false;\n\n const now = Date.now();\n const tiers = [usage.five_hour, usage.seven_day];\n return tiers.some((tier) =>\n tier != null\n && tier.utilization >= 100\n && tier.resets_at != null\n && Date.parse(tier.resets_at) > now,\n );\n }\n\n clearExpiredRateLimits(): void {\n const now = Date.now();\n for (const account of this.cached) {\n if (account.rateLimitResetAt && now >= account.rateLimitResetAt) {\n account.rateLimitResetAt = undefined;\n }\n }\n }\n\n getMinWaitTime(): number {\n const eligible = this.getEligibleAccounts();\n const available = eligible.filter((account) => !this.isRateLimited(account));\n if (available.length > 0) return 0;\n\n const now = Date.now();\n const waits: number[] = [];\n\n for (const account of eligible) {\n if (account.rateLimitResetAt) {\n const ms = account.rateLimitResetAt - now;\n if (ms > 0) waits.push(ms);\n }\n\n const usageResetMs = this.getUsageResetMs(account);\n if (usageResetMs !== null && usageResetMs > 0) {\n waits.push(usageResetMs);\n }\n }\n\n return waits.length > 0 ? Math.min(...waits) : 0;\n }\n\n private getUsageResetMs(account: ManagedAccount): number | null {\n const usage = account.cachedUsage;\n if (!usage) return null;\n\n const now = Date.now();\n const candidates: number[] = [];\n const tiers = [usage.five_hour, usage.seven_day];\n\n for (const tier of tiers) {\n if (tier != null && tier.utilization >= 100 && tier.resets_at != null) {\n const ms = Date.parse(tier.resets_at) - now;\n if (ms > 0) candidates.push(ms);\n }\n }\n\n return candidates.length > 0 ? Math.min(...candidates) : null;\n }\n\n async selectAccount(): Promise<ManagedAccount | null> {\n await this.refresh();\n this.clearExpiredRateLimits();\n\n const eligible = this.getEligibleAccounts();\n if (eligible.length === 0) return null;\n\n const config = getProviderConfig();\n const claims = config.cross_process_claims ? await readProviderClaims() : {};\n\n const strategy = config.account_selection_strategy;\n let selected: ManagedAccount | null;\n switch (strategy) {\n case \"round-robin\":\n selected = this.selectRoundRobin(eligible, claims);\n break;\n case \"hybrid\":\n selected = this.selectHybrid(eligible, claims);\n break;\n case \"sticky\":\n default:\n selected = this.selectSticky(eligible, claims);\n break;\n }\n\n if (selected?.uuid) {\n this.activeAccountUuid = selected.uuid;\n this.store.setActiveUuid(selected.uuid).catch(() => {});\n }\n\n if (config.cross_process_claims && selected?.uuid) {\n writeProviderClaim(selected.uuid).catch(() => {});\n }\n\n return selected;\n }\n\n private isUsable(account: ManagedAccount): boolean {\n return !this.isRateLimited(account)\n && !this.isInRecentCooldown(account)\n && !this.exceedsSoftQuota(account);\n }\n\n private isInRecentCooldown(account: ManagedAccount): boolean {\n if (!account.last429At) return false;\n return Date.now() - account.last429At < RECENT_429_COOLDOWN_MS;\n }\n\n private fallbackNotRateLimited(eligible: ManagedAccount[]): ManagedAccount | null {\n const account = eligible.find((candidate) => !this.isRateLimited(candidate));\n if (account) {\n this.activateAccount(account);\n return account;\n }\n return null;\n }\n\n private selectSticky(eligible: ManagedAccount[], claims: ClaimsMap): ManagedAccount | null {\n const current = this.getActiveAccount();\n if (current?.enabled && !current.isAuthDisabled && this.isUsable(current)) {\n this.activateAccount(current);\n return current;\n }\n\n const unclaimed = eligible.find(\n (account) => this.isUsable(account) && !isClaimedByOtherProvider(claims, account.uuid),\n );\n if (unclaimed) {\n this.activateAccount(unclaimed);\n return unclaimed;\n }\n\n const available = eligible.find((account) => this.isUsable(account));\n if (available) {\n this.activateAccount(available);\n return available;\n }\n\n return this.fallbackNotRateLimited(eligible);\n }\n\n private selectRoundRobin(eligible: ManagedAccount[], claims: ClaimsMap): ManagedAccount | null {\n for (let i = 0; i < eligible.length; i++) {\n const index = (this.roundRobinCursor + i) % eligible.length;\n const account = eligible[index]!;\n if (this.isUsable(account) && !isClaimedByOtherProvider(claims, account.uuid)) {\n this.roundRobinCursor = (index + 1) % eligible.length;\n this.activateAccount(account);\n return account;\n }\n }\n\n for (let i = 0; i < eligible.length; i++) {\n const index = (this.roundRobinCursor + i) % eligible.length;\n const account = eligible[index]!;\n if (this.isUsable(account)) {\n this.roundRobinCursor = (index + 1) % eligible.length;\n this.activateAccount(account);\n return account;\n }\n }\n\n return this.fallbackNotRateLimited(eligible);\n }\n\n private selectHybrid(eligible: ManagedAccount[], claims: ClaimsMap): ManagedAccount | null {\n const usable = eligible.filter((account) => this.isUsable(account));\n const pool = usable.length > 0\n ? usable\n : eligible.filter((account) => !this.isRateLimited(account));\n\n if (pool.length === 0) return null;\n\n const activeUuid = this.activeAccountUuid;\n\n let best = pool[0]!;\n let bestScore = this.calculateHybridScore(best, best.uuid === activeUuid, claims);\n\n for (let i = 1; i < pool.length; i++) {\n const account = pool[i]!;\n const score = this.calculateHybridScore(account, account.uuid === activeUuid, claims);\n if (score > bestScore) {\n best = account;\n bestScore = score;\n }\n }\n\n const current = pool.find((account) => account.uuid === activeUuid);\n if (current && current !== best) {\n const currentScore = this.calculateHybridScore(current, true, claims);\n const bestWithoutStickiness = this.calculateHybridScore(best, false, claims);\n if (bestWithoutStickiness <= currentScore + HYBRID_SWITCH_MARGIN) {\n this.activateAccount(current);\n return current;\n }\n }\n\n this.activateAccount(best);\n return best;\n }\n\n private calculateHybridScore(account: ManagedAccount, isActive: boolean, claims: ClaimsMap): number {\n const maxUtilization = Math.min(100, Math.max(0, this.getMaxUtilization(account)));\n const usageScore = ((100 - maxUtilization) / 100) * 450;\n\n const maxFailures = Math.max(1, getProviderConfig().max_consecutive_auth_failures);\n const healthScore = Math.max(0, ((maxFailures - account.consecutiveAuthFailures) / maxFailures) * 250);\n\n const secondsSinceUsed = (Date.now() - account.lastUsed) / 1000;\n const freshnessScore = (Math.min(secondsSinceUsed, 900) / 900) * 60;\n\n const stickinessBonus = isActive ? 120 : 0;\n const claimPenalty = isClaimedByOtherProvider(claims, account.uuid) ? -200 : 0;\n\n return usageScore + healthScore + freshnessScore + stickinessBonus + claimPenalty;\n }\n\n private getMaxUtilization(account: ManagedAccount): number {\n const usage = account.cachedUsage;\n if (!usage) return 65;\n\n const tiers = [usage.five_hour, usage.seven_day];\n const utilizations = tiers\n .filter((tier): tier is NonNullable<typeof tier> => tier != null)\n .map((tier) => tier.utilization);\n\n return utilizations.length > 0 ? Math.max(...utilizations) : 65;\n }\n\n private activateAccount(account: ManagedAccount): void {\n this.activeAccountUuid = account.uuid;\n account.lastUsed = Date.now();\n }\n\n async markRateLimited(uuid: string, backoffMs?: number): Promise<void> {\n const effectiveBackoff = backoffMs ?? getProviderConfig().rate_limit_min_backoff_ms;\n this.last429Map.set(uuid, Date.now());\n await this.store.mutateAccount(uuid, (account) => {\n account.rateLimitResetAt = Date.now() + effectiveBackoff;\n });\n }\n\n async markRevoked(uuid: string): Promise<void> {\n await this.removeAccountByUuid(uuid);\n }\n\n async markSuccess(uuid: string): Promise<void> {\n this.last429Map.delete(uuid);\n await this.store.mutateAccount(uuid, (account) => {\n account.rateLimitResetAt = undefined;\n account.consecutiveAuthFailures = 0;\n account.lastUsed = Date.now();\n });\n }\n\n private syncToOpenCode(account: Pick<StoredAccount, \"refreshToken\" | \"accessToken\" | \"expiresAt\">): void {\n if (!this.client || !account.accessToken || !account.expiresAt) return;\n this.client.auth.set({\n path: { id: providerAuthId },\n body: {\n type: \"oauth\",\n refresh: account.refreshToken,\n access: account.accessToken,\n expires: account.expiresAt,\n },\n }).catch(() => {});\n }\n\n private async clearOpenCodeAuthIfNoAccountsRemain(): Promise<void> {\n if (!this.client) return;\n\n const storage = await this.store.load();\n if (storage.accounts.length > 0) return;\n\n await this.client.auth\n .set({\n path: { id: providerAuthId },\n body: getClearedOAuthBody(),\n })\n .catch(() => {});\n }\n\n private async removeAccountByUuid(uuid: string): Promise<void> {\n const removed = await this.store.removeAccount(uuid);\n if (!removed) return;\n\n this.last429Map.delete(uuid);\n this.runtimeFactory?.invalidate(uuid);\n await this.refresh();\n await this.clearOpenCodeAuthIfNoAccountsRemain();\n }\n\n async markAuthFailure(uuid: string, result: TokenRefreshResult): Promise<void> {\n if (!result.ok && result.permanent) {\n await this.removeAccountByUuid(uuid);\n return;\n }\n\n await this.store.mutateStorage((storage) => {\n const account = storage.accounts.find((entry) => entry.uuid === uuid);\n if (!account) return;\n\n account.consecutiveAuthFailures = (account.consecutiveAuthFailures ?? 0) + 1;\n const maxFailures = getProviderConfig().max_consecutive_auth_failures;\n const usableCount = storage.accounts.filter(\n (entry) => entry.enabled && !entry.isAuthDisabled && entry.uuid !== uuid,\n ).length;\n\n if (account.consecutiveAuthFailures >= maxFailures && usableCount > 0) {\n account.isAuthDisabled = true;\n account.authDisabledReason = `${maxFailures} consecutive auth failures`;\n }\n });\n }\n\n async applyUsageCache(uuid: string, usage: UsageLimits): Promise<void> {\n await this.store.mutateAccount(uuid, (account) => {\n const now = Date.now();\n const exhaustedTierResetTimes = [usage.five_hour, usage.seven_day]\n .flatMap((tier) => {\n if (tier == null || tier.utilization < 100 || tier.resets_at == null) {\n return [];\n }\n return [Date.parse(tier.resets_at)];\n })\n .filter((resetAt) => Number.isFinite(resetAt) && resetAt > now);\n\n account.cachedUsage = usage;\n account.cachedUsageAt = Date.now();\n account.rateLimitResetAt = exhaustedTierResetTimes.length > 0\n ? Math.min(...exhaustedTierResetTimes)\n : undefined;\n });\n }\n\n async applyProfileCache(uuid: string, profile: ProfileData): Promise<void> {\n await this.store.mutateAccount(uuid, (account) => {\n account.email = profile.email ?? account.email;\n account.planTier = profile.planTier;\n });\n }\n\n async ensureValidToken(uuid: string, client: PluginClient): Promise<TokenRefreshResult> {\n const credentials = await this.store.readCredentials(uuid);\n if (!credentials) return { ok: false, permanent: true };\n\n if (credentials.accessToken && credentials.expiresAt && !isTokenExpired(credentials)) {\n return {\n ok: true,\n patch: { accessToken: credentials.accessToken, expiresAt: credentials.expiresAt },\n };\n }\n\n const result = await refreshToken(credentials.refreshToken, uuid, client);\n if (!result.ok) return result;\n\n const updated = await this.store.mutateAccount(uuid, (account) => {\n account.accessToken = result.patch.accessToken;\n account.expiresAt = result.patch.expiresAt;\n if (result.patch.refreshToken) account.refreshToken = result.patch.refreshToken;\n if (result.patch.uuid && result.patch.uuid !== uuid) account.uuid = result.patch.uuid;\n if (result.patch.accountId) account.accountId = result.patch.accountId;\n if (result.patch.email) account.email = result.patch.email;\n account.consecutiveAuthFailures = 0;\n account.isAuthDisabled = false;\n account.authDisabledReason = undefined;\n });\n\n if (result.patch.uuid && result.patch.uuid !== uuid && this.activeAccountUuid === uuid) {\n this.activeAccountUuid = result.patch.uuid;\n this.store.setActiveUuid(result.patch.uuid).catch(() => {});\n }\n\n if (updated && (uuid === this.activeAccountUuid || updated.uuid === this.activeAccountUuid)) {\n this.syncToOpenCode(updated);\n }\n\n return result;\n }\n\n async validateNonActiveTokens(client: PluginClient): Promise<void> {\n await this.refresh();\n\n const activeUuid = this.activeAccountUuid;\n const eligible = this.cached.filter(\n (account) => account.enabled && !account.isAuthDisabled && account.uuid && account.uuid !== activeUuid,\n );\n\n for (let i = 0; i < eligible.length; i += STARTUP_REFRESH_CONCURRENCY) {\n const batch = eligible.slice(i, i + STARTUP_REFRESH_CONCURRENCY);\n await Promise.all(\n batch.map(async (account) => {\n if (!account.uuid || !isTokenExpired(account)) return;\n\n const result = await this.ensureValidToken(account.uuid, client);\n if (!result.ok) {\n await this.markAuthFailure(account.uuid, result);\n }\n }),\n );\n }\n }\n\n async removeAccount(index: number): Promise<boolean> {\n const account = this.cached[index];\n if (!account?.uuid) return false;\n\n const removed = await this.store.removeAccount(account.uuid);\n if (removed) {\n await this.refresh();\n }\n return removed;\n }\n\n async clearAllAccounts(): Promise<void> {\n await this.store.clear();\n this.cached = [];\n this.activeAccountUuid = undefined;\n }\n\n async addAccount(auth: OAuthCredentials, email?: string): Promise<void> {\n if (!auth.refresh) return;\n\n const existingByToken = this.cached.find((account) => account.refreshToken === auth.refresh);\n if (existingByToken) return;\n\n if (email) {\n const existingByEmail = this.cached.find(\n (account) => account.email && account.email === email,\n );\n if (existingByEmail?.uuid) {\n await this.replaceAccountCredentials(existingByEmail.uuid, auth);\n return;\n }\n }\n\n const newAccount = this.createNewAccount(auth, Date.now());\n if (email) newAccount.email = email;\n await this.store.addAccount(newAccount);\n this.activeAccountUuid = newAccount.uuid;\n await this.store.setActiveUuid(newAccount.uuid);\n await this.refresh();\n }\n\n async toggleEnabled(uuid: string): Promise<void> {\n await this.store.mutateAccount(uuid, (account) => {\n account.enabled = !(account.enabled ?? true);\n if (account.enabled) {\n account.isAuthDisabled = false;\n account.authDisabledReason = undefined;\n account.consecutiveAuthFailures = 0;\n }\n });\n }\n\n async replaceAccountCredentials(uuid: string, auth: OAuthCredentials): Promise<void> {\n const updated = await this.store.mutateAccount(uuid, (account) => {\n account.refreshToken = auth.refresh;\n account.accessToken = auth.access;\n account.expiresAt = auth.expires;\n account.lastUsed = Date.now();\n account.enabled = true;\n account.isAuthDisabled = false;\n account.authDisabledReason = undefined;\n account.consecutiveAuthFailures = 0;\n account.rateLimitResetAt = undefined;\n });\n this.runtimeFactory?.invalidate(uuid);\n\n if (updated && uuid === this.activeAccountUuid) {\n this.syncToOpenCode(updated);\n }\n }\n\n async retryAuth(uuid: string, client: PluginClient): Promise<TokenRefreshResult> {\n await this.store.mutateAccount(uuid, (account) => {\n account.consecutiveAuthFailures = 0;\n account.isAuthDisabled = false;\n account.authDisabledReason = undefined;\n });\n this.runtimeFactory?.invalidate(uuid);\n\n const credentials = await this.store.readCredentials(uuid);\n if (!credentials) return { ok: false, permanent: true };\n\n const result = await refreshToken(credentials.refreshToken, uuid, client);\n if (result.ok) {\n const updated = await this.store.mutateAccount(uuid, (account) => {\n account.accessToken = result.patch.accessToken;\n account.expiresAt = result.patch.expiresAt;\n if (result.patch.refreshToken) account.refreshToken = result.patch.refreshToken;\n if (result.patch.uuid) account.uuid = result.patch.uuid;\n if (result.patch.accountId) account.accountId = result.patch.accountId;\n if (result.patch.email) account.email = result.patch.email;\n account.enabled = true;\n account.consecutiveAuthFailures = 0;\n });\n this.runtimeFactory?.invalidate(uuid);\n if (result.patch.uuid) {\n this.runtimeFactory?.invalidate(result.patch.uuid);\n }\n\n const nextUuid = result.patch.uuid ?? uuid;\n if (this.activeAccountUuid === uuid && result.patch.uuid && result.patch.uuid !== uuid) {\n this.activeAccountUuid = result.patch.uuid;\n await this.store.setActiveUuid(result.patch.uuid);\n }\n\n if (updated && (uuid === this.activeAccountUuid || nextUuid === this.activeAccountUuid)) {\n const freshCredentials = await this.store.readCredentials(nextUuid);\n if (freshCredentials) {\n this.syncToOpenCode({\n refreshToken: freshCredentials.refreshToken,\n accessToken: freshCredentials.accessToken,\n expiresAt: freshCredentials.expiresAt,\n });\n }\n }\n } else {\n await this.markAuthFailure(uuid, result);\n this.runtimeFactory?.invalidate(uuid);\n }\n\n return result;\n }\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport { randomBytes } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\nimport { getConfigDir } from \"./utils\";\n\nconst CLAIMS_FILENAME = \"multiauth-claims.json\";\nconst CLAIM_EXPIRY_MS = 60_000;\n\nexport type ClaimsMap = Record<string, { pid: number; at: number }>;\n\nexport interface ClaimsManager {\n readClaims(): Promise<ClaimsMap>;\n writeClaim(accountId: string): Promise<void>;\n releaseClaim(accountId: string): Promise<void>;\n isClaimedByOther(claims: ClaimsMap, accountId: string | undefined): boolean;\n}\n\nfunction getClaimsPath(filename: string): string {\n return join(getConfigDir(), filename);\n}\n\nfunction isClaimShape(value: unknown): value is { pid: number; at: number } {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n const claim = value as Record<string, unknown>;\n return (\n typeof claim.pid === \"number\"\n && Number.isInteger(claim.pid)\n && claim.pid > 0\n && typeof claim.at === \"number\"\n && Number.isFinite(claim.at)\n );\n}\n\nfunction parseClaims(raw: string): ClaimsMap {\n let parsed: unknown;\n\n try {\n parsed = JSON.parse(raw);\n } catch {\n return {};\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return {};\n }\n\n const claims: ClaimsMap = {};\n for (const [accountId, claim] of Object.entries(parsed)) {\n if (isClaimShape(claim)) {\n claims[accountId] = claim;\n }\n }\n\n return claims;\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction cleanClaims(\n claims: ClaimsMap,\n now: number,\n): { cleaned: ClaimsMap; changed: boolean } {\n const cleaned: ClaimsMap = {};\n let changed = false;\n\n for (const [accountId, claim] of Object.entries(claims)) {\n const expiredByTime = now - claim.at > CLAIM_EXPIRY_MS;\n const zombieClaim = !isProcessAlive(claim.pid);\n if (expiredByTime || zombieClaim) {\n changed = true;\n continue;\n }\n\n cleaned[accountId] = claim;\n }\n\n return { cleaned, changed };\n}\n\nasync function writeClaimsFile(path: string, claims: ClaimsMap): Promise<void> {\n const tempPath = `${path}.${randomBytes(6).toString(\"hex\")}.tmp`;\n await fs.mkdir(dirname(path), { recursive: true });\n\n try {\n await fs.writeFile(tempPath, JSON.stringify(claims, null, 2), { encoding: \"utf-8\", mode: 0o600 });\n await fs.rename(tempPath, path);\n } catch (error) {\n try {\n await fs.unlink(tempPath);\n } catch {\n // ignore cleanup failure\n }\n throw error;\n }\n}\n\nexport function createClaimsManager(filename: string = CLAIMS_FILENAME): ClaimsManager {\n async function readClaims(): Promise<ClaimsMap> {\n const claimsPath = getClaimsPath(filename);\n try {\n const data = await fs.readFile(claimsPath, \"utf-8\");\n const parsed = parseClaims(data);\n const now = Date.now();\n const { cleaned, changed } = cleanClaims(parsed, now);\n\n if (changed) {\n try {\n await writeClaimsFile(claimsPath, cleaned);\n } catch {\n }\n }\n\n return cleaned;\n } catch {\n return {};\n }\n }\n\n async function writeClaim(accountId: string): Promise<void> {\n const claimsPath = getClaimsPath(filename);\n const now = Date.now();\n const claims = await readClaims();\n const { cleaned } = cleanClaims(claims, now);\n\n cleaned[accountId] = { pid: process.pid, at: now };\n\n try {\n await writeClaimsFile(claimsPath, cleaned);\n } catch {\n }\n }\n\n async function releaseClaim(accountId: string): Promise<void> {\n const claimsPath = getClaimsPath(filename);\n const now = Date.now();\n const claims = await readClaims();\n const { cleaned } = cleanClaims(claims, now);\n\n const currentClaim = cleaned[accountId];\n if (!currentClaim || currentClaim.pid !== process.pid) {\n return;\n }\n\n delete cleaned[accountId];\n\n try {\n await writeClaimsFile(claimsPath, cleaned);\n } catch {\n }\n }\n\n function isClaimedByOther(\n claims: ClaimsMap,\n accountId: string | undefined,\n ): boolean {\n if (!accountId) return false;\n const claim = claims[accountId];\n if (!claim) return false;\n if (Date.now() - claim.at > CLAIM_EXPIRY_MS) return false;\n if (!isProcessAlive(claim.pid)) return false;\n return claim.pid !== process.pid;\n }\n\n return {\n readClaims,\n writeClaim,\n releaseClaim,\n isClaimedByOther,\n };\n}\n\nconst defaultClaimsManager = createClaimsManager();\n\nexport function readClaims(): Promise<ClaimsMap> {\n return defaultClaimsManager.readClaims();\n}\n\nexport function writeClaim(accountId: string): Promise<void> {\n return defaultClaimsManager.writeClaim(accountId);\n}\n\nexport function releaseClaim(accountId: string): Promise<void> {\n return defaultClaimsManager.releaseClaim(accountId);\n}\n\nexport function isClaimedByOther(\n claims: ClaimsMap,\n accountId: string | undefined,\n): boolean {\n return defaultClaimsManager.isClaimedByOther(claims, accountId);\n}\n","import { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { getConfig } from \"./config\";\nimport type { ManagedAccount, PluginClient } from \"./types\";\n\n// ─── Shared Filesystem Utilities ─────────────────────────────────\n\nexport function getConfigDir(): string {\n return process.env.OPENCODE_CONFIG_DIR\n || join(process.env.XDG_CONFIG_HOME || join(homedir(), \".config\"), \"opencode\");\n}\n\nexport function getErrorCode(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null || !(\"code\" in error)) {\n return undefined;\n }\n const code = (error as { code?: unknown }).code;\n return typeof code === \"string\" ? code : undefined;\n}\n\n// ─── Formatting & Display ────────────────────────────────────────\n\nexport function formatWaitTime(ms: number): string {\n const totalSeconds = Math.ceil(ms / 1000);\n if (totalSeconds < 60) return `${totalSeconds}s`;\n\n const days = Math.floor(totalSeconds / 86_400);\n const hours = Math.floor((totalSeconds % 86_400) / 3_600);\n const minutes = Math.floor((totalSeconds % 3_600) / 60);\n const seconds = totalSeconds % 60;\n\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (hours > 0) parts.push(`${hours}h`);\n if (minutes > 0) parts.push(`${minutes}m`);\n if (seconds > 0 && days === 0) parts.push(`${seconds}s`);\n\n return parts.join(\" \") || \"0s\";\n}\n\nexport function getAccountLabel(account: ManagedAccount): string {\n if (account.label) return account.label;\n if (account.email) return account.email;\n if (account.uuid) return `Account (${account.uuid.slice(0, 8)})`;\n return `Account ${account.index + 1}`;\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function showToast(\n client: PluginClient,\n message: string,\n variant: \"info\" | \"warning\" | \"success\" | \"error\",\n): Promise<void> {\n if (getConfig().quiet_mode) return;\n try {\n await client.tui.showToast({ body: { message, variant } });\n } catch {\n // TUI may not be available\n }\n}\n\nexport function debugLog(\n client: PluginClient,\n message: string,\n extra?: Record<string, unknown>,\n): void {\n if (!getConfig().debug) return;\n client.app.log({\n body: { service: \"claude-multiauth\", level: \"debug\", message, extra },\n }).catch(() => {});\n}\n\nexport function createMinimalClient(): PluginClient {\n return {\n auth: {\n set: async () => {},\n },\n tui: {\n showToast: async () => {},\n },\n app: {\n log: async () => {},\n },\n };\n}\n\n// ─── OAuth Helpers ───────────────────────────────────────────────\n\nexport function getClearedOAuthBody() {\n return {\n type: \"oauth\" as const,\n refresh: \"\",\n access: \"\",\n expires: 0,\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport { randomBytes } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport * as v from \"valibot\";\nimport { PluginConfigSchema } from \"./types\";\nimport type { PluginConfig } from \"./types\";\n\nexport type CoreConfig = Pick<PluginConfig, \"quiet_mode\" | \"debug\">;\n\nconst DEFAULT_CONFIG_FILENAME = \"multiauth-config.json\";\nconst DEFAULT_CONFIG: PluginConfig = v.parse(PluginConfigSchema, {});\n\nexport interface ConfigLoader {\n getConfig(): PluginConfig;\n loadConfig(): Promise<PluginConfig>;\n resetConfigCache(): void;\n updateConfigField<K extends keyof PluginConfig>(key: K, value: PluginConfig[K]): Promise<void>;\n}\n\nfunction getConfigDir(): string {\n return process.env.OPENCODE_CONFIG_DIR\n || join(process.env.XDG_CONFIG_HOME || join(homedir(), \".config\"), \"opencode\");\n}\n\nfunction parseConfig(raw: unknown): PluginConfig {\n const result = v.safeParse(PluginConfigSchema, raw);\n return result.success ? result.output : DEFAULT_CONFIG;\n}\n\nexport function createConfigLoader(filename: string = DEFAULT_CONFIG_FILENAME): ConfigLoader {\n let cachedConfig: PluginConfig | null = null;\n\n function getConfigPath(): string {\n return join(getConfigDir(), filename);\n }\n\n async function loadConfig(): Promise<PluginConfig> {\n if (cachedConfig) return cachedConfig;\n\n const path = getConfigPath();\n try {\n const content = await fs.readFile(path, \"utf-8\");\n cachedConfig = parseConfig(JSON.parse(content));\n } catch {\n cachedConfig = DEFAULT_CONFIG;\n }\n\n return cachedConfig;\n }\n\n function getConfig(): PluginConfig {\n return cachedConfig ?? DEFAULT_CONFIG;\n }\n\n function resetConfigCache(): void {\n cachedConfig = null;\n }\n\n async function updateConfigField<K extends keyof PluginConfig>(\n key: K,\n value: PluginConfig[K],\n ): Promise<void> {\n const path = getConfigPath();\n\n let existing: Record<string, unknown> = {};\n try {\n const content = await fs.readFile(path, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {}\n\n existing[key] = value;\n\n await fs.mkdir(dirname(path), { recursive: true });\n const content = `${JSON.stringify(existing, null, 2)}\\n`;\n const tempPath = `${path}.${randomBytes(8).toString(\"hex\")}.tmp`;\n try {\n await fs.writeFile(tempPath, content, \"utf-8\");\n await fs.rename(tempPath, path);\n } catch (error) {\n try {\n await fs.unlink(tempPath);\n } catch {}\n throw error;\n }\n\n resetConfigCache();\n await loadConfig();\n }\n\n return {\n getConfig,\n loadConfig,\n resetConfigCache,\n updateConfigField,\n };\n}\n\nlet defaultLoader = createConfigLoader();\n\nexport function initCoreConfig(filename: string): void {\n defaultLoader = createConfigLoader(filename);\n}\n\nexport async function loadConfig(): Promise<PluginConfig> {\n return defaultLoader.loadConfig();\n}\n\nexport function getConfig(): PluginConfig {\n return defaultLoader.getConfig();\n}\n\nexport function resetConfigCache(): void {\n defaultLoader.resetConfigCache();\n}\n\n/**\n * @deprecated Provider-scoped config should use createConfigLoader() instead.\n * Kept as a no-op for backward compatibility with external consumers.\n */\nexport function setConfigGetter(_getter: () => PluginConfig): void {\n}\n\nexport async function updateConfigField<K extends keyof PluginConfig>(\n key: K,\n value: PluginConfig[K],\n): Promise<void> {\n await defaultLoader.updateConfigField(key, value);\n}\n","import * as v from \"valibot\";\n\nexport const OAuthCredentialsSchema = v.object({\n type: v.literal(\"oauth\"),\n refresh: v.string(),\n access: v.string(),\n expires: v.number(),\n});\n\nexport const UsageLimitEntrySchema = v.object({\n utilization: v.number(),\n resets_at: v.nullable(v.string()),\n});\n\nexport const UsageLimitsSchema = v.object({\n five_hour: v.optional(v.nullable(UsageLimitEntrySchema), null),\n seven_day: v.optional(v.nullable(UsageLimitEntrySchema), null),\n seven_day_sonnet: v.optional(v.nullable(UsageLimitEntrySchema), null),\n});\n\nexport const CredentialRefreshPatchSchema = v.object({\n accessToken: v.string(),\n expiresAt: v.number(),\n refreshToken: v.optional(v.string()),\n uuid: v.optional(v.string()),\n accountId: v.optional(v.string()),\n email: v.optional(v.string()),\n});\n\nexport const StoredAccountSchema = v.object({\n uuid: v.optional(v.string()),\n accountId: v.optional(v.string()),\n label: v.optional(v.string()),\n email: v.optional(v.string()),\n planTier: v.optional(v.string(), \"\"),\n refreshToken: v.string(),\n accessToken: v.optional(v.string()),\n expiresAt: v.optional(v.number()),\n addedAt: v.number(),\n lastUsed: v.number(),\n enabled: v.optional(v.boolean(), true),\n rateLimitResetAt: v.optional(v.number()),\n cachedUsage: v.optional(UsageLimitsSchema),\n cachedUsageAt: v.optional(v.number()),\n consecutiveAuthFailures: v.optional(v.number(), 0),\n isAuthDisabled: v.optional(v.boolean(), false),\n authDisabledReason: v.optional(v.string()),\n});\n\nexport const AccountStorageSchema = v.object({\n version: v.literal(1),\n accounts: v.optional(v.array(StoredAccountSchema), []),\n activeAccountUuid: v.optional(v.string()),\n});\n\nexport const AccountSelectionStrategySchema = v.picklist([\"sticky\", \"round-robin\", \"hybrid\"]);\n\nexport const PluginConfigSchema = v.object({\n account_selection_strategy: v.optional(AccountSelectionStrategySchema, \"sticky\"),\n cross_process_claims: v.optional(v.boolean(), true),\n soft_quota_threshold_percent: v.optional(v.pipe(v.number(), v.minValue(0), v.maxValue(100)), 100),\n rate_limit_min_backoff_ms: v.optional(v.pipe(v.number(), v.minValue(0)), 30_000),\n default_retry_after_ms: v.optional(v.pipe(v.number(), v.minValue(0)), 60_000),\n max_consecutive_auth_failures: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1)), 3),\n token_failure_backoff_ms: v.optional(v.pipe(v.number(), v.minValue(0)), 30_000),\n proactive_refresh: v.optional(v.boolean(), true),\n proactive_refresh_buffer_seconds: v.optional(v.pipe(v.number(), v.minValue(60)), 1800),\n proactive_refresh_interval_seconds: v.optional(v.pipe(v.number(), v.minValue(30)), 300),\n quiet_mode: v.optional(v.boolean(), false),\n debug: v.optional(v.boolean(), false),\n});\n\nexport type OAuthCredentials = v.InferOutput<typeof OAuthCredentialsSchema>;\nexport type UsageLimitEntry = v.InferOutput<typeof UsageLimitEntrySchema>;\nexport type UsageLimits = v.InferOutput<typeof UsageLimitsSchema>;\nexport type CredentialRefreshPatch = v.InferOutput<typeof CredentialRefreshPatchSchema>;\nexport type StoredAccount = v.InferOutput<typeof StoredAccountSchema>;\nexport type AccountStorage = v.InferOutput<typeof AccountStorageSchema>;\nexport type AccountSelectionStrategy = v.InferOutput<typeof AccountSelectionStrategySchema>;\nexport type PluginConfig = v.InferOutput<typeof PluginConfigSchema>;\n\nexport type TokenRefreshResult =\n | { ok: true; patch: CredentialRefreshPatch }\n | { ok: false; permanent: boolean; status?: number };\n\nexport class TokenRefreshError extends Error {\n readonly status?: number;\n readonly permanent: boolean;\n\n constructor(permanent: boolean, status?: number) {\n super(status === undefined ? \"Token refresh failed\" : `Token refresh failed: ${status}`);\n this.name = \"TokenRefreshError\";\n this.status = status;\n this.permanent = permanent;\n Object.setPrototypeOf(this, TokenRefreshError.prototype);\n }\n}\n\nexport function isTokenRefreshError(error: unknown): error is TokenRefreshError {\n if (error instanceof TokenRefreshError) return true;\n if (!(error instanceof Error)) return false;\n\n const candidate = error as Error & Partial<TokenRefreshError>;\n return (\n candidate.name === \"TokenRefreshError\"\n && typeof candidate.permanent === \"boolean\"\n && (candidate.status === undefined || typeof candidate.status === \"number\")\n );\n}\n\nexport interface ManagedAccount {\n index: number;\n uuid?: string;\n accountId?: string;\n label?: string;\n email?: string;\n planTier?: string;\n refreshToken: string;\n accessToken?: string;\n expiresAt?: number;\n addedAt: number;\n lastUsed: number;\n enabled: boolean;\n rateLimitResetAt?: number;\n last429At?: number;\n cachedUsage?: UsageLimits;\n cachedUsageAt?: number;\n consecutiveAuthFailures: number;\n isAuthDisabled: boolean;\n authDisabledReason?: string;\n}\n\nexport interface PluginClient {\n auth: {\n set: (params: {\n path: { id: string };\n body: {\n type: string;\n refresh: string;\n access: string;\n expires: number;\n };\n }) => Promise<void>;\n };\n tui: {\n showToast: (params: {\n body: {\n title?: string;\n message: string;\n variant: \"info\" | \"warning\" | \"success\" | \"error\";\n };\n }) => Promise<void>;\n };\n app: {\n log: (params: {\n body: {\n service: string;\n level: \"debug\" | \"info\" | \"warn\" | \"error\";\n message: string;\n extra?: Record<string, unknown>;\n };\n }) => Promise<void>;\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport { randomBytes } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\nimport * as v from \"valibot\";\nimport { loadAccounts, readStorageFromDisk } from \"./storage\";\nimport { ACCOUNTS_FILENAME } from \"./constants\";\nimport { withDirectoryLock } from \"./file-lock\";\nimport { AccountStorageSchema } from \"./types\";\nimport { getConfigDir, getErrorCode } from \"./utils\";\nimport type { AccountStorage, StoredAccount } from \"./types\";\n\nconst FILE_MODE = 0o600;\n\nfunction resolveStoragePath(filename: string): string {\n return join(getConfigDir(), filename);\n}\n\nfunction createEmptyStorage(): AccountStorage {\n return { version: 1, accounts: [] };\n}\n\nfunction buildTempPath(targetPath: string): string {\n return `${targetPath}.${randomBytes(8).toString(\"hex\")}.tmp`;\n}\n\nasync function writeAtomicText(targetPath: string, content: string): Promise<void> {\n await fs.mkdir(dirname(targetPath), { recursive: true });\n const tempPath = buildTempPath(targetPath);\n try {\n await fs.writeFile(tempPath, content, { encoding: \"utf-8\", mode: FILE_MODE });\n await fs.chmod(tempPath, FILE_MODE);\n await fs.rename(tempPath, targetPath);\n await fs.chmod(targetPath, FILE_MODE);\n } catch (error) {\n try {\n await fs.unlink(tempPath);\n } catch {}\n throw error;\n }\n}\n\nasync function writeStorageAtomic(targetPath: string, storage: AccountStorage): Promise<void> {\n const validation = v.safeParse(AccountStorageSchema, storage);\n if (!validation.success) {\n throw new Error(\"Invalid account storage payload\");\n }\n await writeAtomicText(targetPath, `${JSON.stringify(validation.output, null, 2)}\\n`);\n}\n\nasync function ensureStorageFileExists(targetPath: string): Promise<void> {\n await fs.mkdir(dirname(targetPath), { recursive: true });\n const emptyContent = `${JSON.stringify(createEmptyStorage(), null, 2)}\\n`;\n try {\n await fs.writeFile(targetPath, emptyContent, { flag: \"wx\", mode: FILE_MODE });\n } catch (error) {\n if (getErrorCode(error) !== \"EEXIST\") throw error;\n }\n}\n\nexport interface DiskCredentials {\n refreshToken: string;\n accessToken?: string;\n expiresAt?: number;\n accountId?: string;\n}\n\nexport class AccountStore {\n private readonly storagePath: string;\n\n constructor(filename?: string) {\n this.storagePath = resolveStoragePath(filename ?? ACCOUNTS_FILENAME);\n }\n\n private async withLock<T>(fn: (storagePath: string) => Promise<T>): Promise<T> {\n await ensureStorageFileExists(this.storagePath);\n return await withDirectoryLock(this.storagePath, () => fn(this.storagePath));\n }\n\n async load(): Promise<AccountStorage> {\n const storage = await loadAccounts(this.storagePath);\n return storage ?? createEmptyStorage();\n }\n\n async readCredentials(uuid: string): Promise<DiskCredentials | null> {\n const storage = await readStorageFromDisk(this.storagePath, false);\n if (!storage) return null;\n\n const account = storage.accounts.find((a) => a.uuid === uuid);\n if (!account) return null;\n\n return {\n refreshToken: account.refreshToken,\n accessToken: account.accessToken,\n expiresAt: account.expiresAt,\n accountId: account.accountId,\n };\n }\n\n async mutateAccount(\n uuid: string,\n fn: (account: StoredAccount) => void,\n ): Promise<StoredAccount | null> {\n return await this.withLock(async (storagePath) => {\n const current = await readStorageFromDisk(storagePath, false);\n if (!current) return null;\n\n const account = current.accounts.find((a) => a.uuid === uuid);\n if (!account) return null;\n\n fn(account);\n\n await writeStorageAtomic(storagePath, current);\n return { ...account };\n });\n }\n\n async mutateStorage(\n fn: (storage: AccountStorage) => void,\n ): Promise<void> {\n await this.withLock(async (storagePath) => {\n const current = await readStorageFromDisk(storagePath, false) ?? createEmptyStorage();\n fn(current);\n await writeStorageAtomic(storagePath, current);\n });\n }\n\n async addAccount(account: StoredAccount): Promise<void> {\n await this.withLock(async (storagePath) => {\n const current = await readStorageFromDisk(storagePath, false) ?? createEmptyStorage();\n const exists = current.accounts.some(\n (a) => a.uuid === account.uuid || a.refreshToken === account.refreshToken,\n );\n if (exists) return;\n\n current.accounts.push(account);\n await writeStorageAtomic(storagePath, current);\n });\n }\n\n async removeAccount(uuid: string): Promise<boolean> {\n return await this.withLock(async (storagePath) => {\n const current = await readStorageFromDisk(storagePath, false);\n if (!current) return false;\n\n const initialLength = current.accounts.length;\n current.accounts = current.accounts.filter((a) => a.uuid !== uuid);\n if (current.accounts.length === initialLength) return false;\n\n if (current.activeAccountUuid === uuid) {\n current.activeAccountUuid = current.accounts[0]?.uuid;\n }\n\n await writeStorageAtomic(storagePath, current);\n return true;\n });\n }\n\n async setActiveUuid(uuid: string | undefined): Promise<void> {\n await this.mutateStorage((storage) => {\n storage.activeAccountUuid = uuid;\n });\n }\n\n async clear(): Promise<void> {\n await this.withLock(async (storagePath) => {\n await writeStorageAtomic(storagePath, createEmptyStorage());\n });\n }\n}\n","import { promises as fs } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport * as v from \"valibot\";\nimport { ACCOUNTS_FILENAME } from \"./constants\";\nimport { AccountStorageSchema } from \"./types\";\nimport { getConfigDir, getErrorCode } from \"./utils\";\nimport type { AccountStorage, StoredAccount } from \"./types\";\n\nfunction getDefaultStoragePath(): string {\n return join(getConfigDir(), ACCOUNTS_FILENAME);\n}\n\nasync function backupCorruptFile(targetPath: string, content: string): Promise<void> {\n const backupPath = `${targetPath}.corrupt.${Date.now()}.bak`;\n await fs.mkdir(dirname(backupPath), { recursive: true });\n await fs.writeFile(backupPath, content, \"utf-8\");\n}\n\nexport async function readStorageFromDisk(\n targetPath: string,\n backupOnCorrupt: boolean,\n): Promise<AccountStorage | null> {\n let content: string;\n try {\n content = await fs.readFile(targetPath, \"utf-8\");\n } catch (error) {\n if (getErrorCode(error) === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(content);\n } catch {\n if (backupOnCorrupt) {\n try {\n await backupCorruptFile(targetPath, content);\n } catch {\n // best-effort backup\n }\n }\n return null;\n }\n\n const validation = v.safeParse(AccountStorageSchema, parsed);\n if (!validation.success) {\n if (backupOnCorrupt) {\n try {\n await backupCorruptFile(targetPath, content);\n } catch {\n // best-effort backup\n }\n }\n return null;\n }\n\n return validation.output;\n}\n\nexport function deduplicateAccounts(accounts: StoredAccount[]): StoredAccount[] {\n const deduplicated: StoredAccount[] = [];\n const indexByUuid = new Map<string, number>();\n\n for (const account of accounts) {\n if (!account.uuid) {\n deduplicated.push(account);\n continue;\n }\n\n const existingIndex = indexByUuid.get(account.uuid);\n if (existingIndex === undefined) {\n indexByUuid.set(account.uuid, deduplicated.length);\n deduplicated.push(account);\n continue;\n }\n\n const existingAccount = deduplicated[existingIndex];\n if (!existingAccount || account.lastUsed >= existingAccount.lastUsed) {\n deduplicated[existingIndex] = account;\n }\n }\n\n return deduplicated;\n}\n\nexport async function loadAccounts(storagePath?: string): Promise<AccountStorage | null> {\n const effectivePath = storagePath ?? getDefaultStoragePath();\n const storage = await readStorageFromDisk(effectivePath, true);\n if (!storage) {\n return null;\n }\n\n return {\n ...storage,\n accounts: deduplicateAccounts(storage.accounts || []),\n };\n}\n","const DEFAULT_ACCOUNTS_FILENAME = \"multiauth-accounts.json\";\n\n/**\n * @deprecated Use `new AccountStore(filename)` instead.\n * This global is kept only for backward-compatible test helpers.\n * When two plugins share the same core module instance, mutating\n * this global causes one plugin to read the other's account file.\n */\nexport let ACCOUNTS_FILENAME = DEFAULT_ACCOUNTS_FILENAME;\n\n/**\n * @deprecated Use `new AccountStore(filename)` instead.\n */\nexport function setAccountsFilename(filename: string): void {\n if (!filename) {\n ACCOUNTS_FILENAME = DEFAULT_ACCOUNTS_FILENAME;\n return;\n }\n\n ACCOUNTS_FILENAME = filename;\n}\n","import { promises as fs } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nconst DEFAULT_STALE_MS = 10_000;\nconst DEFAULT_RETRY_DELAY_MS = 50;\nconst DEFAULT_MAX_RETRIES = 10;\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function removeIfStale(lockPath: string, staleMs: number): Promise<void> {\n try {\n const stat = await fs.stat(lockPath);\n if (Date.now() - stat.mtimeMs > staleMs) {\n await fs.rm(lockPath, { recursive: true, force: true });\n }\n } catch {}\n}\n\nexport async function withDirectoryLock<T>(\n targetPath: string,\n fn: () => Promise<T>,\n options?: {\n staleMs?: number;\n retryDelayMs?: number;\n retries?: number;\n },\n): Promise<T> {\n const lockPath = `${targetPath}.lock`;\n const staleMs = options?.staleMs ?? DEFAULT_STALE_MS;\n const retryDelayMs = options?.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n const retries = options?.retries ?? DEFAULT_MAX_RETRIES;\n\n await fs.mkdir(dirname(targetPath), { recursive: true });\n\n for (let attempt = 0; ; attempt += 1) {\n try {\n await fs.mkdir(lockPath, { mode: 0o700 });\n break;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException | undefined)?.code;\n if (code !== \"EEXIST\") {\n throw error;\n }\n\n await removeIfStale(lockPath, staleMs);\n if (attempt >= retries) {\n throw new Error(`Failed to acquire lock for ${targetPath}`);\n }\n await sleep(retryDelayMs * (attempt + 1));\n }\n }\n\n try {\n return await fn();\n } finally {\n await fs.rm(lockPath, { recursive: true, force: true }).catch(() => {});\n }\n}\n","import {\n isTokenRefreshError,\n type ManagedAccount,\n type PluginClient,\n type TokenRefreshResult,\n} from \"./types\";\n\nconst MIN_MAX_RETRIES = 6;\nconst RETRIES_PER_ACCOUNT = 3;\nconst MAX_SERVER_RETRIES_PER_ATTEMPT = 2;\nconst MAX_RESOLVE_ATTEMPTS = 10;\nconst SERVER_RETRY_BASE_MS = 1_000;\nconst SERVER_RETRY_MAX_MS = 4_000;\nexport interface ExecutorAccountManager {\n getAccountCount(): number;\n refresh(): Promise<void>;\n selectAccount(): Promise<ManagedAccount | null>;\n markSuccess(uuid: string): Promise<void>;\n markAuthFailure(uuid: string, result: TokenRefreshResult): Promise<void>;\n markRevoked(uuid: string): Promise<void>;\n hasAnyUsableAccount(): boolean;\n getMinWaitTime(): number;\n}\n\nexport interface ExecutorRuntimeFactory {\n getRuntime(uuid: string): Promise<{ fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response> }>;\n invalidate(uuid: string): void;\n}\n\nexport interface ExecutorDependencies {\n handleRateLimitResponse: (\n manager: unknown,\n client: PluginClient,\n account: ManagedAccount,\n response: Response,\n ) => Promise<void>;\n formatWaitTime: (ms: number) => string;\n sleep: (ms: number) => Promise<void>;\n showToast: (\n client: PluginClient,\n message: string,\n variant: \"info\" | \"warning\" | \"success\" | \"error\",\n ) => Promise<void>;\n getAccountLabel: (account: ManagedAccount) => string;\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === \"AbortError\";\n}\n\nexport function createExecutorForProvider(\n providerName: string,\n dependencies: ExecutorDependencies,\n): {\n executeWithAccountRotation: (\n manager: ExecutorAccountManager,\n runtimeFactory: ExecutorRuntimeFactory,\n client: PluginClient,\n input: RequestInfo | URL,\n init?: RequestInit,\n ) => Promise<Response>;\n} {\n const {\n handleRateLimitResponse,\n formatWaitTime,\n sleep,\n showToast,\n getAccountLabel,\n } = dependencies;\n\n async function executeWithAccountRotation(\n manager: ExecutorAccountManager,\n runtimeFactory: ExecutorRuntimeFactory,\n client: PluginClient,\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> {\n const maxRetries = Math.max(MIN_MAX_RETRIES, manager.getAccountCount() * RETRIES_PER_ACCOUNT);\n let previousAccountUuid: string | undefined;\n\n type StatusTransition =\n | { type: \"success\"; response: Response }\n | { type: \"handled\"; response?: Response }\n | { type: \"retryOuter\" };\n\n async function retryServerErrors(\n account: ManagedAccount,\n runtime: Awaited<ReturnType<ExecutorRuntimeFactory[\"getRuntime\"]>>,\n ): Promise<Response | null> {\n for (let attempt = 0; attempt < MAX_SERVER_RETRIES_PER_ATTEMPT; attempt++) {\n const backoff = Math.min(SERVER_RETRY_BASE_MS * 2 ** attempt, SERVER_RETRY_MAX_MS);\n const jitteredBackoff = backoff * (0.5 + Math.random() * 0.5);\n await sleep(jitteredBackoff);\n\n let retryResponse: Response;\n try {\n retryResponse = await runtime.fetch(input, init);\n } catch (error) {\n if (isAbortError(error)) throw error;\n if (await handleRuntimeFetchFailure(manager, runtimeFactory, client, account, error)) {\n return null;\n }\n void showToast(client, `${getAccountLabel(account)} network error — switching`, \"warning\");\n return null;\n }\n\n if (retryResponse.status < 500) return retryResponse;\n }\n\n return null;\n }\n\n const dispatchResponseStatus = async (\n account: ManagedAccount,\n accountUuid: string,\n runtime: Awaited<ReturnType<ExecutorRuntimeFactory[\"getRuntime\"]>>,\n response: Response,\n allow401Retry: boolean,\n from401RefreshRetry: boolean,\n ): Promise<StatusTransition> => {\n if (response.status >= 500) {\n const recovered = await retryServerErrors(account, runtime);\n if (recovered === null) {\n return { type: \"retryOuter\" };\n }\n response = recovered;\n }\n\n if (response.status === 401) {\n if (allow401Retry) {\n runtimeFactory.invalidate(accountUuid);\n try {\n const retryRuntime = await runtimeFactory.getRuntime(accountUuid);\n const retryResponse = await retryRuntime.fetch(input, init);\n return dispatchResponseStatus(account, accountUuid, retryRuntime, retryResponse, false, true);\n } catch (error) {\n if (isAbortError(error)) throw error;\n if (await handleRuntimeFetchFailure(manager, runtimeFactory, client, account, error)) {\n return { type: \"retryOuter\" };\n }\n return { type: \"retryOuter\" };\n }\n }\n\n await manager.markAuthFailure(accountUuid, { ok: false, permanent: false });\n await manager.refresh();\n\n if (!manager.hasAnyUsableAccount()) {\n void showToast(client, \"All accounts have auth failures.\", \"error\");\n throw new Error(\n `All ${providerName} accounts have authentication failures. Re-authenticate with \\`opencode auth login\\`.`,\n );\n }\n\n void showToast(client, `${getAccountLabel(account)} auth failed — switching to next account.`, \"warning\");\n return { type: \"retryOuter\" };\n }\n\n if (response.status === 403) {\n const revoked = await isRevokedTokenResponse(response);\n if (revoked) {\n await manager.markRevoked(accountUuid);\n await manager.refresh();\n void showToast(\n client,\n `${getAccountLabel(account)} disabled: OAuth token revoked.`,\n \"error\",\n );\n\n if (!manager.hasAnyUsableAccount()) {\n throw new Error(\n `All ${providerName} accounts have been revoked or disabled. Re-authenticate with \\`opencode auth login\\`.`,\n );\n }\n return { type: \"retryOuter\" };\n }\n\n if (from401RefreshRetry) {\n return { type: \"handled\", response };\n }\n }\n\n if (response.status === 429) {\n await handleRateLimitResponse(manager, client, account, response);\n return { type: \"handled\" };\n }\n\n return { type: \"success\", response };\n };\n\n for (let retries = 1; retries <= maxRetries; retries++) {\n await manager.refresh();\n const account = await resolveAccount(manager, client);\n const accountUuid = account.uuid;\n if (!accountUuid) continue;\n\n if (previousAccountUuid && accountUuid !== previousAccountUuid && manager.getAccountCount() > 1) {\n void showToast(client, `Switched to ${getAccountLabel(account)}`, \"info\");\n }\n previousAccountUuid = accountUuid;\n\n let runtime: Awaited<ReturnType<ExecutorRuntimeFactory[\"getRuntime\"]>>;\n let response: Response;\n try {\n runtime = await runtimeFactory.getRuntime(accountUuid);\n response = await runtime.fetch(input, init);\n } catch (error) {\n if (isAbortError(error)) throw error;\n if (await handleRuntimeFetchFailure(manager, runtimeFactory, client, account, error)) {\n continue;\n }\n void showToast(client, `${getAccountLabel(account)} network error — switching`, \"warning\");\n continue;\n }\n\n const transition = await dispatchResponseStatus(account, accountUuid, runtime, response, true, false);\n if (transition.type === \"retryOuter\" || transition.type === \"handled\") {\n if (transition.type === \"handled\" && transition.response) {\n return transition.response;\n }\n continue;\n }\n\n await manager.markSuccess(accountUuid);\n return transition.response;\n }\n\n throw new Error(\n `Exhausted ${maxRetries} retries across all accounts. All attempts failed due to auth errors, rate limits, or token issues.`,\n );\n }\n\n async function handleRuntimeFetchFailure(\n manager: ExecutorAccountManager,\n runtimeFactory: ExecutorRuntimeFactory,\n client: PluginClient,\n account: ManagedAccount,\n error: unknown,\n ): Promise<boolean> {\n if (!isTokenRefreshError(error)) return false;\n if (!account.uuid) return false;\n\n const accountUuid = account.uuid;\n runtimeFactory.invalidate(accountUuid);\n await manager.markAuthFailure(accountUuid, {\n ok: false,\n permanent: error.permanent,\n });\n await manager.refresh();\n\n if (!manager.hasAnyUsableAccount()) {\n void showToast(client, \"All accounts have auth failures.\", \"error\");\n throw new Error(\n `All ${providerName} accounts have authentication failures. Re-authenticate with \\`opencode auth login\\`.`,\n );\n }\n\n void showToast(client, `${getAccountLabel(account)} auth failed — switching to next account.`, \"warning\");\n return true;\n }\n\n async function resolveAccount(\n manager: ExecutorAccountManager,\n client: PluginClient,\n ): Promise<ManagedAccount> {\n let attempts = 0;\n\n while (true) {\n if (++attempts > MAX_RESOLVE_ATTEMPTS) {\n throw new Error(\n `Failed to resolve an available account after ${MAX_RESOLVE_ATTEMPTS} attempts. All accounts may be rate-limited or disabled.`,\n );\n }\n\n const account = await manager.selectAccount();\n if (account) return account;\n\n if (!manager.hasAnyUsableAccount()) {\n throw new Error(\n `All ${providerName} accounts are disabled. Re-authenticate with \\`opencode auth login\\`.`,\n );\n }\n\n const waitMs = manager.getMinWaitTime();\n if (waitMs <= 0) {\n throw new Error(\n `All ${providerName} accounts are rate-limited. Add more accounts with \\`opencode auth login\\` or wait.`,\n );\n }\n\n await showToast(\n client,\n `All ${manager.getAccountCount()} account(s) rate-limited. Waiting ${formatWaitTime(waitMs)}...`,\n \"warning\",\n );\n await sleep(waitMs);\n }\n }\n\n return {\n executeWithAccountRotation,\n };\n}\n\nasync function isRevokedTokenResponse(response: Response): Promise<boolean> {\n try {\n const cloned = response.clone();\n const body = await cloned.text();\n return body.includes(\"revoked\");\n } catch {\n return false;\n }\n}\n","import { AccountStore } from \"./account-store\";\nimport type { PluginClient, PluginConfig, StoredAccount, TokenRefreshResult } from \"./types\";\nimport { getClearedOAuthBody } from \"./utils\";\n\nconst INITIAL_DELAY_MS = 5_000;\n\nexport interface ProactiveRefreshDependencies {\n providerAuthId: string;\n getConfig: () => PluginConfig;\n refreshToken: (\n currentRefreshToken: string,\n accountId: string,\n client: PluginClient,\n ) => Promise<TokenRefreshResult>;\n isTokenExpired: (account: Pick<StoredAccount, \"accessToken\" | \"expiresAt\">) => boolean;\n debugLog: (client: PluginClient, message: string, extra?: Record<string, unknown>) => void;\n}\n\nexport interface ProactiveRefreshQueueInstance {\n start(): void;\n stop(): Promise<void>;\n}\n\nexport interface ProactiveRefreshQueueClass {\n new (\n client: PluginClient,\n store: AccountStore,\n onInvalidate?: (uuid: string) => void,\n ): ProactiveRefreshQueueInstance;\n}\n\nexport function createProactiveRefreshQueueForProvider(dependencies: ProactiveRefreshDependencies): ProactiveRefreshQueueClass {\n const {\n providerAuthId,\n getConfig,\n refreshToken,\n isTokenExpired,\n debugLog,\n } = dependencies;\n\n return class ProactiveRefreshQueue {\n private timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n private runToken = 0;\n private inFlight: Promise<void> | null = null;\n\n constructor(\n private readonly client: PluginClient,\n private readonly store: AccountStore,\n private readonly onInvalidate?: (uuid: string) => void,\n ) {}\n\n start(): void {\n const config = getConfig();\n if (!config.proactive_refresh) return;\n\n this.runToken++;\n if (this.timeoutHandle) {\n clearTimeout(this.timeoutHandle);\n this.timeoutHandle = null;\n }\n this.scheduleNext(this.runToken, INITIAL_DELAY_MS);\n\n debugLog(this.client, \"Proactive refresh started\", {\n intervalSeconds: config.proactive_refresh_interval_seconds,\n bufferSeconds: config.proactive_refresh_buffer_seconds,\n });\n }\n\n async stop(): Promise<void> {\n this.runToken++;\n if (this.timeoutHandle) {\n clearTimeout(this.timeoutHandle);\n this.timeoutHandle = null;\n }\n if (this.inFlight) {\n await this.inFlight;\n this.inFlight = null;\n }\n debugLog(this.client, \"Proactive refresh stopped\");\n }\n\n private scheduleNext(token: number, delayMs: number): void {\n this.timeoutHandle = setTimeout(() => {\n if (token !== this.runToken) return;\n this.inFlight = this.runCheck(token).finally(() => {\n this.inFlight = null;\n });\n }, delayMs);\n }\n\n private needsProactiveRefresh(account: Pick<StoredAccount, \"accessToken\" | \"expiresAt\">): boolean {\n if (!account.accessToken || !account.expiresAt) return false;\n if (isTokenExpired(account)) return false;\n const bufferMs = getConfig().proactive_refresh_buffer_seconds * 1000;\n return account.expiresAt <= Date.now() + bufferMs;\n }\n\n private async runCheck(token: number): Promise<void> {\n try {\n const stored = await this.store.load();\n if (token !== this.runToken) return;\n\n const candidates = stored.accounts.filter((a) =>\n a.enabled !== false\n && !a.isAuthDisabled\n && a.uuid\n && this.needsProactiveRefresh(a),\n );\n\n if (candidates.length === 0) return;\n\n debugLog(this.client, `Proactive refresh: ${candidates.length} account(s) approaching expiry`);\n\n for (const account of candidates) {\n if (token !== this.runToken) return;\n\n const credentials = await this.store.readCredentials(account.uuid!);\n if (!credentials || !this.needsProactiveRefresh(credentials)) continue;\n\n const result = await refreshToken(credentials.refreshToken, account.uuid!, this.client);\n if (result.ok) {\n await this.store.mutateAccount(account.uuid!, (target) => {\n target.accessToken = result.patch.accessToken;\n target.expiresAt = result.patch.expiresAt;\n if (result.patch.refreshToken) target.refreshToken = result.patch.refreshToken;\n if (result.patch.uuid) target.uuid = result.patch.uuid;\n if (result.patch.email) target.email = result.patch.email;\n if (result.patch.accountId) target.accountId = result.patch.accountId;\n target.consecutiveAuthFailures = 0;\n target.isAuthDisabled = false;\n target.authDisabledReason = undefined;\n });\n this.onInvalidate?.(account.uuid!);\n } else {\n await this.persistFailure(account, result.permanent);\n }\n }\n } catch (error) {\n debugLog(this.client, `Proactive refresh check error: ${error}`);\n } finally {\n if (token === this.runToken) {\n const intervalMs = getConfig().proactive_refresh_interval_seconds * 1000;\n this.scheduleNext(token, intervalMs);\n }\n }\n }\n\n private async persistFailure(account: StoredAccount, permanent: boolean): Promise<void> {\n try {\n const accountUuid = account.uuid;\n if (!accountUuid) return;\n\n if (permanent) {\n const removed = await this.store.removeAccount(accountUuid);\n if (!removed) return;\n\n this.onInvalidate?.(accountUuid);\n await this.clearOpenCodeAuthIfNoAccountsRemain();\n return;\n }\n\n await this.store.mutateStorage((storage) => {\n const target = storage.accounts.find((entry) => entry.uuid === accountUuid);\n if (!target) return;\n\n target.consecutiveAuthFailures = (target.consecutiveAuthFailures ?? 0) + 1;\n const maxFailures = getConfig().max_consecutive_auth_failures;\n const usableCount = storage.accounts.filter(\n (entry) => entry.enabled && !entry.isAuthDisabled && entry.uuid !== accountUuid,\n ).length;\n\n if (target.consecutiveAuthFailures >= maxFailures && usableCount > 0) {\n target.isAuthDisabled = true;\n target.authDisabledReason = `${maxFailures} consecutive auth failures (proactive refresh)`;\n }\n });\n } catch {\n debugLog(this.client, `Failed to persist auth failure for ${account.uuid}`);\n }\n }\n\n private async clearOpenCodeAuthIfNoAccountsRemain(): Promise<void> {\n const storage = await this.store.load();\n if (storage.accounts.length > 0) return;\n\n await this.client.auth\n .set({\n path: { id: providerAuthId },\n body: getClearedOAuthBody(),\n })\n .catch(() => {});\n }\n };\n}\n","import type { ManagedAccount, PluginClient, PluginConfig, UsageLimits } from \"./types\";\n\nconst USAGE_FETCH_COOLDOWN_MS = 30_000;\n\nexport interface RateLimitDependencies {\n fetchUsage: (accessToken: string, accountId?: string) => Promise<{ ok: true; data: UsageLimits } | { ok: false; reason: string }>;\n getConfig: () => Pick<PluginConfig, \"default_retry_after_ms\">;\n formatWaitTime: (ms: number) => string;\n getAccountLabel: (account: ManagedAccount) => string;\n showToast: (\n client: PluginClient,\n message: string,\n variant: \"info\" | \"warning\" | \"success\" | \"error\",\n ) => Promise<void>;\n}\n\nexport interface RateLimitAccountManager {\n markRateLimited(uuid: string, backoffMs?: number): Promise<void>;\n applyUsageCache(uuid: string, usage: UsageLimits): Promise<void>;\n getAccountCount(): number;\n}\n\nexport function createRateLimitHandlers(dependencies: RateLimitDependencies) {\n const {\n fetchUsage,\n getConfig,\n formatWaitTime,\n getAccountLabel,\n showToast,\n } = dependencies;\n\n function retryAfterMsFromResponse(response: Response): number {\n const retryAfterMs = response.headers.get(\"retry-after-ms\");\n if (retryAfterMs) {\n const parsed = parseInt(retryAfterMs, 10);\n if (!isNaN(parsed) && parsed > 0) return parsed;\n }\n\n const retryAfter = response.headers.get(\"retry-after\");\n if (retryAfter) {\n const parsed = parseInt(retryAfter, 10);\n if (!isNaN(parsed) && parsed > 0) return parsed * 1000;\n }\n\n return getConfig().default_retry_after_ms;\n }\n\n function getResetMsFromUsage(account: ManagedAccount): number | null {\n const usage = account.cachedUsage;\n if (!usage) return null;\n\n const now = Date.now();\n const candidates: number[] = [];\n\n if (usage.five_hour?.resets_at) {\n const ms = Date.parse(usage.five_hour.resets_at) - now;\n if (ms > 0) candidates.push(ms);\n }\n if (usage.seven_day?.resets_at) {\n const ms = Date.parse(usage.seven_day.resets_at) - now;\n if (ms > 0) candidates.push(ms);\n }\n\n return candidates.length > 0 ? Math.min(...candidates) : null;\n }\n\n async function fetchUsageLimits(accessToken: string, accountId?: string): Promise<UsageLimits | null> {\n if (!accessToken) return null;\n try {\n const result = await fetchUsage(accessToken, accountId);\n return result.ok ? result.data : null;\n } catch {\n return null;\n }\n }\n\n async function handleRateLimitResponse(\n manager: RateLimitAccountManager,\n client: PluginClient,\n account: ManagedAccount,\n response: Response,\n ): Promise<void> {\n if (!account.uuid) return;\n\n const resetMs = getResetMsFromUsage(account) ?? retryAfterMsFromResponse(response);\n await manager.markRateLimited(account.uuid, resetMs);\n\n const shouldFetchUsage = account.accessToken\n && (!account.cachedUsageAt || Date.now() - account.cachedUsageAt > USAGE_FETCH_COOLDOWN_MS);\n\n if (shouldFetchUsage) {\n const usage = await fetchUsageLimits(account.accessToken!, account.accountId);\n if (usage) {\n await manager.applyUsageCache(account.uuid, usage);\n }\n }\n\n if (manager.getAccountCount() > 1) {\n void showToast(\n client,\n `${getAccountLabel(account)} rate-limited (resets in ${formatWaitTime(resetMs)}). Switching...`,\n \"warning\",\n );\n }\n }\n\n return {\n retryAfterMsFromResponse,\n getResetMsFromUsage,\n fetchUsageLimits,\n handleRateLimitResponse,\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getConfigDir } from \"./utils\";\nimport type { AccountStore } from \"./account-store\";\n\nconst AUTH_JSON_FILENAME = \"auth.json\";\n\ninterface AuthJsonCredential {\n type: string;\n refresh: string;\n access?: string;\n expires?: number;\n}\n\nfunction isValidOAuthCredential(value: unknown): value is AuthJsonCredential {\n if (typeof value !== \"object\" || value === null) return false;\n\n const candidate = value as Record<string, unknown>;\n return (\n candidate.type === \"oauth\" &&\n typeof candidate.refresh === \"string\" &&\n candidate.refresh.length > 0\n );\n}\n\nfunction resolveAuthJsonPath(): string {\n return join(getConfigDir(), AUTH_JSON_FILENAME);\n}\n\nasync function readAuthJson(): Promise<Record<string, unknown> | null> {\n const authPath = resolveAuthJsonPath();\n\n let content: string;\n try {\n content = await fs.readFile(authPath, \"utf-8\");\n } catch {\n return null;\n }\n\n try {\n const parsed = JSON.parse(content);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return null;\n }\n return parsed as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\n/**\n * Imports an existing OAuth credential from OpenCode's auth.json\n * into the multi-account storage on first use.\n *\n * Only runs when storage has zero accounts. Does not modify auth.json.\n *\n * @param providerKey - The key in auth.json (\"anthropic\" or \"openai\")\n * @param store - The AccountStore instance to import into\n * @returns true if a credential was imported, false otherwise\n */\nexport async function migrateFromAuthJson(\n providerKey: string,\n store: AccountStore,\n): Promise<boolean> {\n const storage = await store.load();\n const hasExistingAccounts = storage.accounts.length > 0;\n if (hasExistingAccounts) return false;\n\n const authData = await readAuthJson();\n if (!authData) return false;\n\n const providerCredential = authData[providerKey];\n if (!isValidOAuthCredential(providerCredential)) return false;\n\n const now = Date.now();\n const newAccount = {\n uuid: crypto.randomUUID(),\n refreshToken: providerCredential.refresh,\n accessToken: providerCredential.access,\n expiresAt: providerCredential.expires,\n addedAt: now,\n lastUsed: now,\n enabled: true,\n planTier: \"\",\n consecutiveAuthFailures: 0,\n isAuthDisabled: false,\n };\n\n await store.addAccount(newAccount);\n await store.setActiveUuid(newAccount.uuid);\n\n return true;\n}\n","export const ANSI = {\n hide: \"\\x1b[?25l\",\n show: \"\\x1b[?25h\",\n up: (n = 1) => `\\x1b[${n}A`,\n down: (n = 1) => `\\x1b[${n}B`,\n clearLine: \"\\x1b[2K\",\n\n cyan: \"\\x1b[36m\",\n green: \"\\x1b[32m\",\n red: \"\\x1b[31m\",\n yellow: \"\\x1b[33m\",\n dim: \"\\x1b[2m\",\n bold: \"\\x1b[1m\",\n reset: \"\\x1b[0m\",\n} as const;\n\nexport type KeyAction = \"up\" | \"down\" | \"enter\" | \"escape\" | \"escape-start\" | null;\n\nexport function parseKey(data: Buffer): KeyAction {\n const s = data.toString();\n\n // Standard: \\x1b[A / Application mode: \\x1bOA\n if (s === \"\\x1b[A\" || s === \"\\x1bOA\") return \"up\";\n if (s === \"\\x1b[B\" || s === \"\\x1bOB\") return \"down\";\n\n if (s === \"\\r\" || s === \"\\n\") return \"enter\";\n if (s === \"\\x03\") return \"escape\";\n\n // Bare escape byte — may be start of arrow key sequence\n if (s === \"\\x1b\") return \"escape-start\";\n\n return null;\n}\n\nexport function isTTY(): boolean {\n return Boolean(process.stdin.isTTY);\n}\n","import { ANSI, isTTY, parseKey } from \"./ansi\";\n\nexport interface MenuItem<T = string> {\n label: string;\n value: T;\n hint?: string;\n disabled?: boolean;\n separator?: boolean;\n color?: \"red\" | \"green\" | \"yellow\" | \"cyan\";\n}\n\nexport interface SelectOptions {\n message: string;\n subtitle?: string;\n}\n\nconst ESCAPE_TIMEOUT_MS = 50;\n\nconst COLOR_MAP: Record<string, string> = {\n red: ANSI.red,\n green: ANSI.green,\n yellow: ANSI.yellow,\n cyan: ANSI.cyan,\n};\n\nexport async function select<T>(\n items: MenuItem<T>[],\n options: SelectOptions,\n): Promise<T | null> {\n if (!isTTY()) {\n throw new Error(\"Interactive select requires a TTY terminal\");\n }\n\n const enabledItems = items.filter((i) => !i.disabled && !i.separator);\n if (enabledItems.length === 0) {\n throw new Error(\"All items disabled\");\n }\n\n if (enabledItems.length === 1) {\n return enabledItems[0]!.value;\n }\n\n const { message, subtitle } = options;\n const { stdin, stdout } = process;\n\n let cursor = items.findIndex((i) => !i.disabled && !i.separator);\n if (cursor === -1) cursor = 0;\n let escapeTimeout: ReturnType<typeof setTimeout> | null = null;\n let isCleanedUp = false;\n let isFirstRender = true;\n\n const getTotalLines = (): number => {\n const subtitleLines = subtitle ? 3 : 0;\n return 1 + subtitleLines + items.length + 1 + 1;\n };\n\n const renderItemLabel = (item: MenuItem<T>, isSelected: boolean): string => {\n const colorCode = item.color ? (COLOR_MAP[item.color] ?? \"\") : \"\";\n\n if (item.disabled) {\n return `${ANSI.dim}${item.label} (unavailable)${ANSI.reset}`;\n }\n\n const hintSuffix = item.hint ? ` ${ANSI.dim}${item.hint}${ANSI.reset}` : \"\";\n\n if (isSelected) {\n const label = colorCode ? `${colorCode}${item.label}${ANSI.reset}` : item.label;\n return `${label}${hintSuffix}`;\n }\n\n const dimLabel = colorCode\n ? `${ANSI.dim}${colorCode}${item.label}${ANSI.reset}`\n : `${ANSI.dim}${item.label}${ANSI.reset}`;\n return `${dimLabel}${hintSuffix}`;\n };\n\n const render = () => {\n const totalLines = getTotalLines();\n\n if (!isFirstRender) {\n stdout.write(ANSI.up(totalLines) + \"\\r\");\n }\n isFirstRender = false;\n\n stdout.write(`${ANSI.clearLine}${ANSI.dim}\\u250c ${ANSI.reset}${message}\\n`);\n\n if (subtitle) {\n stdout.write(`${ANSI.clearLine}${ANSI.dim}\\u2502${ANSI.reset}\\n`);\n stdout.write(`${ANSI.clearLine}${ANSI.cyan}\\u25c6${ANSI.reset} ${subtitle}\\n`);\n stdout.write(`${ANSI.clearLine}\\n`);\n }\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (!item) continue;\n\n if (item.separator) {\n stdout.write(`${ANSI.clearLine}${ANSI.dim}\\u2502${ANSI.reset}\\n`);\n continue;\n }\n\n const isSelected = i === cursor;\n const labelText = renderItemLabel(item, isSelected);\n const bullet = isSelected\n ? `${ANSI.green}\\u25cf${ANSI.reset}`\n : `${ANSI.dim}\\u25cb${ANSI.reset}`;\n\n stdout.write(`${ANSI.clearLine}${ANSI.cyan}\\u2502${ANSI.reset} ${bullet} ${labelText}\\n`);\n }\n\n stdout.write(`${ANSI.clearLine}${ANSI.cyan}\\u2502${ANSI.reset} ${ANSI.dim}\\u2191/\\u2193 to select \\u2022 Enter: confirm${ANSI.reset}\\n`);\n stdout.write(`${ANSI.clearLine}${ANSI.cyan}\\u2514${ANSI.reset}\\n`);\n };\n\n return new Promise((resolve) => {\n const wasRaw = stdin.isRaw ?? false;\n\n const cleanup = () => {\n if (isCleanedUp) return;\n isCleanedUp = true;\n\n if (escapeTimeout) {\n clearTimeout(escapeTimeout);\n escapeTimeout = null;\n }\n\n try {\n stdin.removeListener(\"data\", onKey);\n stdin.setRawMode(wasRaw);\n stdin.pause();\n stdout.write(ANSI.show);\n } catch {\n // best-effort cleanup\n }\n\n process.removeListener(\"SIGINT\", onSignal);\n process.removeListener(\"SIGTERM\", onSignal);\n };\n\n const onSignal = () => {\n cleanup();\n resolve(null);\n };\n\n const finishWithValue = (value: T | null) => {\n cleanup();\n resolve(value);\n };\n\n const findNextSelectable = (from: number, direction: 1 | -1): number => {\n if (items.length === 0) return from;\n let next = from;\n do {\n next = (next + direction + items.length) % items.length;\n } while (items[next]?.disabled || items[next]?.separator);\n return next;\n };\n\n const onKey = (data: Buffer) => {\n if (escapeTimeout) {\n clearTimeout(escapeTimeout);\n escapeTimeout = null;\n }\n\n const action = parseKey(data);\n\n switch (action) {\n case \"up\":\n cursor = findNextSelectable(cursor, -1);\n render();\n return;\n case \"down\":\n cursor = findNextSelectable(cursor, 1);\n render();\n return;\n case \"enter\":\n finishWithValue(items[cursor]?.value ?? null);\n return;\n case \"escape\":\n finishWithValue(null);\n return;\n case \"escape-start\":\n escapeTimeout = setTimeout(() => {\n finishWithValue(null);\n }, ESCAPE_TIMEOUT_MS);\n return;\n default:\n return;\n }\n };\n\n process.once(\"SIGINT\", onSignal);\n process.once(\"SIGTERM\", onSignal);\n\n try {\n stdin.setRawMode(true);\n } catch {\n cleanup();\n resolve(null);\n return;\n }\n\n stdin.resume();\n stdout.write(ANSI.hide);\n render();\n\n stdin.on(\"data\", onKey);\n });\n}\n","import { select } from \"./select\";\n\nexport async function confirm(message: string, defaultYes = false): Promise<boolean> {\n const items = defaultYes\n ? [\n { label: \"Yes\", value: true },\n { label: \"No\", value: false },\n ]\n : [\n { label: \"No\", value: false },\n { label: \"Yes\", value: true },\n ];\n\n const result = await select(items, { message });\n return result ?? false;\n}\n","import type { OAuthAdapter } from \"./types\";\n\nexport const anthropicOAuthAdapter: OAuthAdapter = {\n id: \"anthropic\",\n authProviderId: \"anthropic\",\n modelDisplayName: \"Claude\",\n statusToolName: \"claude_multiauth_status\",\n authMethodLabel: \"Claude Pro/Max (Multi-Auth)\",\n serviceLogName: \"claude-multiauth\",\n oauthClientId: \"9d1c250a-e61b-44d9-88ed-5944d1962f5e\",\n tokenEndpoint: \"https://console.anthropic.com/v1/oauth/token\",\n usageEndpoint: \"https://api.anthropic.com/api/oauth/usage\",\n profileEndpoint: \"https://api.anthropic.com/api/oauth/profile\",\n oauthBetaHeader: \"oauth-2025-04-20\",\n requestBetaHeader: \"oauth-2025-04-20,interleaved-thinking-2025-05-14\",\n cliUserAgent: \"claude-cli/2.1.2 (external, cli)\",\n cliVersion: \"2.1.80\",\n billingSalt: \"59cf53e54c78\",\n toolPrefix: \"mcp_\",\n accountStorageFilename: \"anthropic-multi-account-accounts.json\",\n transform: {\n rewriteOpenCodeBranding: true,\n addToolPrefix: true,\n stripToolPrefixInResponse: true,\n enableMessagesBetaQuery: true,\n },\n planLabels: {\n max: \"Claude Max\",\n pro: \"Claude Pro\",\n free: \"Free\",\n },\n supported: true,\n};\n","import type { OAuthAdapter } from \"./types\";\n\nconst ISSUER = \"https://auth.openai.com\";\n\nexport const openAIOAuthAdapter: OAuthAdapter = {\n id: \"openai\",\n authProviderId: \"openai\",\n modelDisplayName: \"ChatGPT\",\n statusToolName: \"chatgpt_multiauth_status\",\n authMethodLabel: \"ChatGPT Plus/Pro (Multi-Auth)\",\n serviceLogName: \"chatgpt-multiauth\",\n oauthClientId: \"app_EMoamEEZ73f0CkXaXp7hrann\",\n tokenEndpoint: `${ISSUER}/oauth/token`,\n usageEndpoint: \"\",\n profileEndpoint: \"\",\n oauthBetaHeader: \"\",\n requestBetaHeader: \"\",\n cliUserAgent: \"opencode/1.1.53\",\n cliVersion: \"\",\n billingSalt: \"\",\n toolPrefix: \"mcp_\",\n accountStorageFilename: \"openai-multi-account-accounts.json\",\n transform: {\n rewriteOpenCodeBranding: false,\n addToolPrefix: false,\n stripToolPrefixInResponse: false,\n enableMessagesBetaQuery: false,\n },\n planLabels: {\n pro: \"ChatGPT Pro\",\n plus: \"ChatGPT Plus\",\n go: \"ChatGPT Go\",\n free: \"Free\",\n },\n supported: true,\n};\n","import * as v from \"valibot\";\n\n// ─── Valibot Schemas (disk-persisted config) ─────────────────────\n\nexport const PoolConfigSchema = v.object({\n name: v.string(),\n baseProvider: v.string(),\n members: v.array(v.string()),\n enabled: v.boolean(),\n});\n\nexport const ChainEntryConfigSchema = v.object({\n pool: v.string(),\n model: v.optional(v.string()),\n enabled: v.boolean(),\n});\n\nexport const ChainConfigSchema = v.object({\n name: v.string(),\n entries: v.array(ChainEntryConfigSchema),\n enabled: v.boolean(),\n});\n\nexport const PoolChainConfigSchema = v.object({\n pools: v.optional(v.array(PoolConfigSchema), []),\n chains: v.optional(v.array(ChainConfigSchema), []),\n});\n\n// ─── Inferred Types (from schemas) ───────────────────────────────\n\nexport type PoolConfig = v.InferOutput<typeof PoolConfigSchema>;\nexport type ChainEntryConfig = v.InferOutput<typeof ChainEntryConfigSchema>;\nexport type ChainConfig = v.InferOutput<typeof ChainConfigSchema>;\nexport type PoolChainConfig = v.InferOutput<typeof PoolChainConfigSchema>;\n\n// In-memory cascade state (NOT persisted)\nexport interface CascadeState {\n prompt: string;\n attemptedAccounts: Set<string>;\n visitedChainIndexes: Set<number>;\n}\n\n// Candidate for failover rotation\nexport interface FailoverCandidate {\n poolName: string;\n accountUuid: string;\n source: \"pool\" | \"chain\";\n chainIndex?: number;\n}\n\n// Skipped entry during failover planning\nexport interface FailoverSkip {\n type: \"pool_exhausted\" | \"chain_disabled\" | \"account_attempted\" | \"account_unavailable\";\n poolName: string;\n reason: string;\n detail?: string;\n}\n","import { promises as fs } from \"node:fs\";\nimport { randomBytes } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\nimport * as v from \"valibot\";\nimport { withDirectoryLock } from \"./file-lock\";\nimport { getConfigDir, getErrorCode } from \"./utils\";\nimport { PoolChainConfigSchema } from \"./pool-types\";\nimport type { PoolChainConfig } from \"./pool-types\";\n\nconst POOL_CONFIG_FILENAME = \"multiauth-pools.json\";\nconst FILE_MODE = 0o600;\n\nfunction createEmptyConfig(): PoolChainConfig {\n return { pools: [], chains: [] };\n}\n\nfunction getGlobalConfigPath(): string {\n return join(getConfigDir(), POOL_CONFIG_FILENAME);\n}\n\nfunction buildTempPath(targetPath: string): string {\n return `${targetPath}.${randomBytes(8).toString(\"hex\")}.tmp`;\n}\n\nasync function resolveConfigPath(): Promise<string> {\n const projectPath = join(process.cwd(), \".opencode\", POOL_CONFIG_FILENAME);\n try {\n await fs.access(projectPath);\n return projectPath;\n } catch {\n }\n return getGlobalConfigPath();\n}\n\nasync function ensureConfigFileExists(targetPath: string): Promise<void> {\n await fs.mkdir(dirname(targetPath), { recursive: true });\n const emptyContent = `${JSON.stringify(createEmptyConfig(), null, 2)}\\n`;\n try {\n await fs.writeFile(targetPath, emptyContent, { flag: \"wx\", mode: FILE_MODE });\n } catch (error) {\n if (getErrorCode(error) !== \"EEXIST\") throw error;\n }\n}\n\nasync function writeAtomicText(targetPath: string, content: string): Promise<void> {\n await fs.mkdir(dirname(targetPath), { recursive: true });\n const tempPath = buildTempPath(targetPath);\n try {\n await fs.writeFile(tempPath, content, { encoding: \"utf-8\", mode: FILE_MODE });\n await fs.chmod(tempPath, FILE_MODE);\n await fs.rename(tempPath, targetPath);\n await fs.chmod(targetPath, FILE_MODE);\n } catch (error) {\n try {\n await fs.unlink(tempPath);\n } catch {}\n throw error;\n }\n}\n\nasync function withConfigLock<T>(fn: (configPath: string) => Promise<T>): Promise<T> {\n const configPath = await resolveConfigPath();\n await ensureConfigFileExists(configPath);\n return await withDirectoryLock(configPath, () => fn(configPath));\n}\n\nfunction parsePoolChainConfig(content: string): PoolChainConfig | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(content);\n } catch {\n return null;\n }\n\n const validation = v.safeParse(PoolChainConfigSchema, parsed);\n return validation.success ? validation.output : null;\n}\n\nexport async function loadPoolChainConfig(): Promise<PoolChainConfig> {\n const path = await resolveConfigPath();\n try {\n const content = await fs.readFile(path, \"utf-8\");\n return parsePoolChainConfig(content) ?? createEmptyConfig();\n } catch {\n return createEmptyConfig();\n }\n}\n\nexport async function savePoolChainConfig(config: PoolChainConfig): Promise<void> {\n await withConfigLock(async (configPath) => {\n const validation = v.safeParse(PoolChainConfigSchema, config);\n if (!validation.success) {\n throw new Error(\"Invalid pool/chain config payload\");\n }\n await writeAtomicText(configPath, `${JSON.stringify(validation.output, null, 2)}\\n`);\n });\n}\n","import type { ManagedAccount } from \"./types\";\nimport type { FailoverCandidate, FailoverSkip, PoolChainConfig, PoolConfig } from \"./pool-types\";\n\nconst DEFAULT_EXHAUSTED_COOLDOWN_MS = 5 * 60 * 1000;\n\ninterface PoolAwareAccountManager {\n getAccounts(): ManagedAccount[];\n isRateLimited(account: ManagedAccount): boolean;\n selectAccount(): Promise<ManagedAccount | null>;\n}\n\nexport interface BuildFailoverPlanOptions {\n attemptedAccounts?: Set<string>;\n visitedChainIndexes?: Set<number>;\n}\n\nexport interface FailoverPlan {\n candidates: FailoverCandidate[];\n skips: FailoverSkip[];\n}\n\nexport class PoolManager {\n private poolsByName = new Map<string, PoolConfig>();\n private exhaustedUntilByAccount = new Map<string, number>();\n private exhaustedCooldownMs: number;\n\n constructor(options?: { exhaustedCooldownMs?: number }) {\n this.exhaustedCooldownMs = options?.exhaustedCooldownMs ?? DEFAULT_EXHAUSTED_COOLDOWN_MS;\n }\n\n loadPools(configs: PoolConfig[]): void {\n this.poolsByName.clear();\n for (const pool of configs) {\n this.poolsByName.set(pool.name, pool);\n }\n }\n\n getPoolForAccount(accountUuid: string): PoolConfig | null {\n for (const pool of this.poolsByName.values()) {\n if (!pool.enabled) continue;\n if (pool.members.includes(accountUuid)) return pool;\n }\n return null;\n }\n\n getAvailableMembers(pool: PoolConfig, accountManager: PoolAwareAccountManager): string[] {\n if (!pool.enabled) return [];\n this.clearExpiredExhausted();\n\n const accountsByUuid = new Map<string, ManagedAccount>();\n for (const account of accountManager.getAccounts()) {\n if (!account.uuid) continue;\n accountsByUuid.set(account.uuid, account);\n }\n\n return pool.members.filter((accountUuid) => {\n const account = accountsByUuid.get(accountUuid);\n if (!account) return false;\n if (!account.enabled || account.isAuthDisabled) return false;\n if (this.isExhausted(accountUuid)) return false;\n if (accountManager.isRateLimited(account)) return false;\n return true;\n });\n }\n\n markExhausted(accountUuid: string): void {\n this.exhaustedUntilByAccount.set(accountUuid, Date.now() + this.exhaustedCooldownMs);\n }\n\n async getNextMember(\n pool: PoolConfig,\n currentUuid: string | undefined,\n accountManager: PoolAwareAccountManager,\n ): Promise<string | null> {\n const availableMembers = this.getAvailableMembers(pool, accountManager);\n if (availableMembers.length === 0) return null;\n\n const excluded = new Set<string>();\n if (currentUuid) excluded.add(currentUuid);\n\n const preferred = await this.selectPreferredMember(availableMembers, excluded, accountManager);\n if (preferred) return preferred;\n\n for (const candidate of availableMembers) {\n if (candidate !== currentUuid) return candidate;\n }\n\n return null;\n }\n\n async buildFailoverPlan(\n currentAccount: Pick<ManagedAccount, \"uuid\" | \"accountId\"> | null,\n config: PoolChainConfig,\n accountManager: PoolAwareAccountManager,\n options?: BuildFailoverPlanOptions,\n ): Promise<FailoverPlan> {\n this.loadPools(config.pools ?? []);\n\n if ((config.pools?.length ?? 0) === 0 && (config.chains?.length ?? 0) === 0) {\n return { candidates: [], skips: [] };\n }\n\n const attemptedAccounts = options?.attemptedAccounts ?? new Set<string>();\n const visitedChainIndexes = options?.visitedChainIndexes ?? new Set<number>();\n const currentUuid = currentAccount?.uuid;\n\n const candidates: FailoverCandidate[] = [];\n const skips: FailoverSkip[] = [];\n const addedCandidateUuids = new Set<string>();\n\n const appendPoolCandidates = async (\n poolName: string,\n source: \"pool\" | \"chain\",\n chainIndex?: number,\n ): Promise<void> => {\n const pool = this.poolsByName.get(poolName);\n if (!pool || !pool.enabled) {\n skips.push({\n type: \"chain_disabled\",\n poolName,\n reason: \"Pool is missing or disabled\",\n });\n return;\n }\n\n const available = this.getAvailableMembers(pool, accountManager);\n if (available.length === 0) {\n skips.push({\n type: \"pool_exhausted\",\n poolName,\n reason: \"No available members\",\n });\n return;\n }\n\n const poolExclusions = new Set<string>();\n if (currentUuid) poolExclusions.add(currentUuid);\n\n while (poolExclusions.size < available.length + (currentUuid ? 1 : 0)) {\n const nextMember = await this.selectPreferredMember(available, poolExclusions, accountManager);\n if (!nextMember) break;\n\n poolExclusions.add(nextMember);\n\n if (attemptedAccounts.has(nextMember)) {\n skips.push({\n type: \"account_attempted\",\n poolName,\n reason: \"Already attempted in this cascade\",\n detail: nextMember,\n });\n continue;\n }\n\n if (addedCandidateUuids.has(nextMember)) continue;\n\n candidates.push({\n poolName,\n accountUuid: nextMember,\n source,\n chainIndex,\n });\n addedCandidateUuids.add(nextMember);\n }\n\n for (const memberUuid of available) {\n if (poolExclusions.has(memberUuid)) continue;\n if (attemptedAccounts.has(memberUuid)) {\n skips.push({\n type: \"account_attempted\",\n poolName,\n reason: \"Already attempted in this cascade\",\n detail: memberUuid,\n });\n continue;\n }\n if (addedCandidateUuids.has(memberUuid)) continue;\n\n candidates.push({\n poolName,\n accountUuid: memberUuid,\n source,\n chainIndex,\n });\n addedCandidateUuids.add(memberUuid);\n }\n };\n\n if (currentUuid) {\n const currentPool = this.getPoolForAccount(currentUuid);\n if (currentPool) {\n await appendPoolCandidates(currentPool.name, \"pool\");\n }\n }\n\n let flattenedChainIndex = 0;\n for (const chain of config.chains ?? []) {\n if (!chain.enabled) {\n for (let i = 0; i < chain.entries.length; i++) {\n skips.push({\n type: \"chain_disabled\",\n poolName: chain.entries[i]?.pool ?? chain.name,\n reason: `Chain '${chain.name}' is disabled`,\n });\n flattenedChainIndex += 1;\n }\n continue;\n }\n\n for (const entry of chain.entries) {\n if (visitedChainIndexes.has(flattenedChainIndex)) {\n skips.push({\n type: \"chain_disabled\",\n poolName: entry.pool,\n reason: \"Chain entry already visited in this cascade\",\n detail: `${flattenedChainIndex}`,\n });\n flattenedChainIndex += 1;\n continue;\n }\n\n if (!entry.enabled) {\n skips.push({\n type: \"chain_disabled\",\n poolName: entry.pool,\n reason: \"Chain entry is disabled\",\n detail: `${flattenedChainIndex}`,\n });\n flattenedChainIndex += 1;\n continue;\n }\n\n await appendPoolCandidates(entry.pool, \"chain\", flattenedChainIndex);\n flattenedChainIndex += 1;\n }\n }\n\n return { candidates, skips };\n }\n\n private isExhausted(accountUuid: string): boolean {\n const exhaustedUntil = this.exhaustedUntilByAccount.get(accountUuid);\n if (!exhaustedUntil) return false;\n if (Date.now() >= exhaustedUntil) {\n this.exhaustedUntilByAccount.delete(accountUuid);\n return false;\n }\n return true;\n }\n\n private clearExpiredExhausted(): void {\n const now = Date.now();\n for (const [accountUuid, exhaustedUntil] of this.exhaustedUntilByAccount.entries()) {\n if (now >= exhaustedUntil) this.exhaustedUntilByAccount.delete(accountUuid);\n }\n }\n\n private async selectPreferredMember(\n availableMembers: string[],\n excludedMembers: Set<string>,\n accountManager: PoolAwareAccountManager,\n ): Promise<string | null> {\n const availableSet = new Set(availableMembers);\n const maxAttempts = Math.max(availableMembers.length * 2, 6);\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const selected = await accountManager.selectAccount();\n if (!selected?.uuid) continue;\n if (!availableSet.has(selected.uuid)) continue;\n if (excludedMembers.has(selected.uuid)) continue;\n return selected.uuid;\n }\n\n for (const memberUuid of availableMembers) {\n if (!excludedMembers.has(memberUuid)) return memberUuid;\n }\n return null;\n }\n}\n","import type { CascadeState } from \"./pool-types\";\n\nfunction createCascadeState(prompt: string, currentAccountUuid?: string): CascadeState {\n const attemptedAccounts = new Set<string>();\n if (currentAccountUuid) {\n attemptedAccounts.add(currentAccountUuid);\n }\n\n return {\n prompt,\n attemptedAccounts,\n visitedChainIndexes: new Set<number>(),\n };\n}\n\nexport class CascadeStateManager {\n public suppressNextStartTurn = false;\n private cascadeState: CascadeState | null = null;\n\n startTurn(prompt: string, currentAccountUuid?: string): CascadeState {\n if (this.suppressNextStartTurn) {\n this.suppressNextStartTurn = false;\n return this.ensureCascadeState(prompt, currentAccountUuid);\n }\n\n const shouldReset = !this.cascadeState || this.cascadeState.prompt !== prompt;\n if (shouldReset) {\n this.cascadeState = createCascadeState(prompt, currentAccountUuid);\n return this.cascadeState;\n }\n\n return this.ensureCascadeState(prompt, currentAccountUuid);\n }\n\n ensureCascadeState(prompt: string, currentAccountUuid?: string): CascadeState {\n if (!this.cascadeState || this.cascadeState.prompt !== prompt) {\n this.cascadeState = createCascadeState(prompt, currentAccountUuid);\n return this.cascadeState;\n }\n\n if (currentAccountUuid) {\n this.cascadeState.attemptedAccounts.add(currentAccountUuid);\n }\n\n return this.cascadeState;\n }\n\n markAttempted(accountUuid: string): void {\n if (!this.cascadeState) return;\n this.cascadeState.attemptedAccounts.add(accountUuid);\n }\n\n markVisitedChainIndex(index: number): void {\n if (!this.cascadeState) return;\n this.cascadeState.visitedChainIndexes.add(index);\n }\n\n clearCascadeState(): void {\n this.cascadeState = null;\n this.suppressNextStartTurn = false;\n }\n\n getSnapshot(): CascadeState | null {\n if (!this.cascadeState) return null;\n return {\n prompt: this.cascadeState.prompt,\n attemptedAccounts: new Set(this.cascadeState.attemptedAccounts),\n visitedChainIndexes: new Set(this.cascadeState.visitedChainIndexes),\n };\n }\n}\n"],"mappings":"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","names":["fs","randomBytes","dirname","join","join","homedir","v","loadConfig","getConfig","resetConfigCache","updateConfigField","content","getConfigDir","join","homedir","join","getConfigDir","randomBytes","fs","dirname","readClaims","writeClaim","releaseClaim","isClaimedByOther","fs","randomBytes","dirname","join","v","fs","dirname","join","v","join","getConfigDir","fs","dirname","fs","dirname","sleep","join","getConfigDir","randomBytes","fs","dirname","formatWaitTime","sleep","showToast","getAccountLabel","getConfig","debugLog","getConfig","formatWaitTime","getAccountLabel","showToast","fs","join","join","getConfigDir","fs","v","fs","randomBytes","dirname","join","v","FILE_MODE","join","getConfigDir","buildTempPath","randomBytes","fs","dirname","writeAtomicText"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-multi-account-core",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
4
4
  "description": "Shared core for multi-account OpenCode plugins",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",