opencode-multi-account-core 0.2.10 → 0.2.12
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 +20 -2
- package/dist/index.js +98 -79
- package/dist/index.js.map +1 -1
- package/package.json +1 -3
package/dist/index.d.ts
CHANGED
|
@@ -200,6 +200,9 @@ interface DiskCredentials {
|
|
|
200
200
|
accountId?: string;
|
|
201
201
|
}
|
|
202
202
|
declare class AccountStore {
|
|
203
|
+
private readonly storagePath;
|
|
204
|
+
constructor(filename?: string);
|
|
205
|
+
private withLock;
|
|
203
206
|
load(): Promise<AccountStorage>;
|
|
204
207
|
readCredentials(uuid: string): Promise<DiskCredentials | null>;
|
|
205
208
|
mutateAccount(uuid: string, fn: (account: StoredAccount) => void): Promise<StoredAccount | null>;
|
|
@@ -273,7 +276,16 @@ declare function resetConfigCache(): void;
|
|
|
273
276
|
declare function setConfigGetter(getter: () => PluginConfig): void;
|
|
274
277
|
declare function updateConfigField<K extends keyof PluginConfig>(key: K, value: PluginConfig[K]): Promise<void>;
|
|
275
278
|
|
|
279
|
+
/**
|
|
280
|
+
* @deprecated Use `new AccountStore(filename)` instead.
|
|
281
|
+
* This global is kept only for backward-compatible test helpers.
|
|
282
|
+
* When two plugins share the same core module instance, mutating
|
|
283
|
+
* this global causes one plugin to read the other's account file.
|
|
284
|
+
*/
|
|
276
285
|
declare let ACCOUNTS_FILENAME: string;
|
|
286
|
+
/**
|
|
287
|
+
* @deprecated Use `new AccountStore(filename)` instead.
|
|
288
|
+
*/
|
|
277
289
|
declare function setAccountsFilename(filename: string): void;
|
|
278
290
|
|
|
279
291
|
interface ExecutorAccountManager {
|
|
@@ -303,6 +315,12 @@ declare function createExecutorForProvider(providerName: string, dependencies: E
|
|
|
303
315
|
executeWithAccountRotation: (manager: ExecutorAccountManager, runtimeFactory: ExecutorRuntimeFactory, client: PluginClient, input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
304
316
|
};
|
|
305
317
|
|
|
318
|
+
declare function withDirectoryLock<T>(targetPath: string, fn: () => Promise<T>, options?: {
|
|
319
|
+
staleMs?: number;
|
|
320
|
+
retryDelayMs?: number;
|
|
321
|
+
retries?: number;
|
|
322
|
+
}): Promise<T>;
|
|
323
|
+
|
|
306
324
|
interface ProactiveRefreshDependencies {
|
|
307
325
|
providerAuthId: string;
|
|
308
326
|
getConfig: () => PluginConfig;
|
|
@@ -346,7 +364,7 @@ declare function createRateLimitHandlers(dependencies: RateLimitDependencies): {
|
|
|
346
364
|
|
|
347
365
|
declare function readStorageFromDisk(targetPath: string, backupOnCorrupt: boolean): Promise<AccountStorage | null>;
|
|
348
366
|
declare function deduplicateAccounts(accounts: StoredAccount[]): StoredAccount[];
|
|
349
|
-
declare function loadAccounts(): Promise<AccountStorage | null>;
|
|
367
|
+
declare function loadAccounts(storagePath?: string): Promise<AccountStorage | null>;
|
|
350
368
|
|
|
351
369
|
declare function getConfigDir(): string;
|
|
352
370
|
declare function getErrorCode(error: unknown): string | undefined;
|
|
@@ -548,4 +566,4 @@ declare class CascadeStateManager {
|
|
|
548
566
|
getSnapshot(): CascadeState | null;
|
|
549
567
|
}
|
|
550
568
|
|
|
551
|
-
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, writeClaim };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -929,10 +929,9 @@ function createAccountManagerForProvider(dependencies) {
|
|
|
929
929
|
}
|
|
930
930
|
|
|
931
931
|
// src/account-store.ts
|
|
932
|
-
import { promises as
|
|
932
|
+
import { promises as fs5 } from "fs";
|
|
933
933
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
934
|
-
import { dirname as
|
|
935
|
-
import * as lockfile from "proper-lockfile";
|
|
934
|
+
import { dirname as dirname5, join as join5 } from "path";
|
|
936
935
|
import * as v4 from "valibot";
|
|
937
936
|
|
|
938
937
|
// src/storage.ts
|
|
@@ -952,7 +951,7 @@ function setAccountsFilename(filename) {
|
|
|
952
951
|
}
|
|
953
952
|
|
|
954
953
|
// src/storage.ts
|
|
955
|
-
function
|
|
954
|
+
function getDefaultStoragePath() {
|
|
956
955
|
return join4(getConfigDir2(), ACCOUNTS_FILENAME);
|
|
957
956
|
}
|
|
958
957
|
async function backupCorruptFile(targetPath, content) {
|
|
@@ -1015,9 +1014,9 @@ function deduplicateAccounts(accounts) {
|
|
|
1015
1014
|
}
|
|
1016
1015
|
return deduplicated;
|
|
1017
1016
|
}
|
|
1018
|
-
async function loadAccounts() {
|
|
1019
|
-
const
|
|
1020
|
-
const storage = await readStorageFromDisk(
|
|
1017
|
+
async function loadAccounts(storagePath) {
|
|
1018
|
+
const effectivePath = storagePath ?? getDefaultStoragePath();
|
|
1019
|
+
const storage = await readStorageFromDisk(effectivePath, true);
|
|
1021
1020
|
if (!storage) {
|
|
1022
1021
|
return null;
|
|
1023
1022
|
}
|
|
@@ -1027,14 +1026,58 @@ async function loadAccounts() {
|
|
|
1027
1026
|
};
|
|
1028
1027
|
}
|
|
1029
1028
|
|
|
1029
|
+
// src/file-lock.ts
|
|
1030
|
+
import { promises as fs4 } from "fs";
|
|
1031
|
+
import { dirname as dirname4 } from "path";
|
|
1032
|
+
var DEFAULT_STALE_MS = 1e4;
|
|
1033
|
+
var DEFAULT_RETRY_DELAY_MS = 50;
|
|
1034
|
+
var DEFAULT_MAX_RETRIES = 10;
|
|
1035
|
+
function sleep2(ms) {
|
|
1036
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1037
|
+
}
|
|
1038
|
+
async function removeIfStale(lockPath, staleMs) {
|
|
1039
|
+
try {
|
|
1040
|
+
const stat = await fs4.stat(lockPath);
|
|
1041
|
+
if (Date.now() - stat.mtimeMs > staleMs) {
|
|
1042
|
+
await fs4.rm(lockPath, { recursive: true, force: true });
|
|
1043
|
+
}
|
|
1044
|
+
} catch {
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
async function withDirectoryLock(targetPath, fn, options) {
|
|
1048
|
+
const lockPath = `${targetPath}.lock`;
|
|
1049
|
+
const staleMs = options?.staleMs ?? DEFAULT_STALE_MS;
|
|
1050
|
+
const retryDelayMs = options?.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
1051
|
+
const retries = options?.retries ?? DEFAULT_MAX_RETRIES;
|
|
1052
|
+
await fs4.mkdir(dirname4(targetPath), { recursive: true });
|
|
1053
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
1054
|
+
try {
|
|
1055
|
+
await fs4.mkdir(lockPath, { mode: 448 });
|
|
1056
|
+
break;
|
|
1057
|
+
} catch (error) {
|
|
1058
|
+
const code = error?.code;
|
|
1059
|
+
if (code !== "EEXIST") {
|
|
1060
|
+
throw error;
|
|
1061
|
+
}
|
|
1062
|
+
await removeIfStale(lockPath, staleMs);
|
|
1063
|
+
if (attempt >= retries) {
|
|
1064
|
+
throw new Error(`Failed to acquire lock for ${targetPath}`);
|
|
1065
|
+
}
|
|
1066
|
+
await sleep2(retryDelayMs * (attempt + 1));
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
try {
|
|
1070
|
+
return await fn();
|
|
1071
|
+
} finally {
|
|
1072
|
+
await fs4.rm(lockPath, { recursive: true, force: true }).catch(() => {
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1030
1077
|
// src/account-store.ts
|
|
1031
1078
|
var FILE_MODE = 384;
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
retries: { retries: 10, minTimeout: 50, maxTimeout: 2e3, factor: 2 }
|
|
1035
|
-
};
|
|
1036
|
-
function getStoragePath2() {
|
|
1037
|
-
return join5(getConfigDir2(), ACCOUNTS_FILENAME);
|
|
1079
|
+
function resolveStoragePath(filename) {
|
|
1080
|
+
return join5(getConfigDir2(), filename);
|
|
1038
1081
|
}
|
|
1039
1082
|
function createEmptyStorage() {
|
|
1040
1083
|
return { version: 1, accounts: [] };
|
|
@@ -1043,16 +1086,16 @@ function buildTempPath(targetPath) {
|
|
|
1043
1086
|
return `${targetPath}.${randomBytes3(8).toString("hex")}.tmp`;
|
|
1044
1087
|
}
|
|
1045
1088
|
async function writeAtomicText(targetPath, content) {
|
|
1046
|
-
await
|
|
1089
|
+
await fs5.mkdir(dirname5(targetPath), { recursive: true });
|
|
1047
1090
|
const tempPath = buildTempPath(targetPath);
|
|
1048
1091
|
try {
|
|
1049
|
-
await
|
|
1050
|
-
await
|
|
1051
|
-
await
|
|
1052
|
-
await
|
|
1092
|
+
await fs5.writeFile(tempPath, content, { encoding: "utf-8", mode: FILE_MODE });
|
|
1093
|
+
await fs5.chmod(tempPath, FILE_MODE);
|
|
1094
|
+
await fs5.rename(tempPath, targetPath);
|
|
1095
|
+
await fs5.chmod(targetPath, FILE_MODE);
|
|
1053
1096
|
} catch (error) {
|
|
1054
1097
|
try {
|
|
1055
|
-
await
|
|
1098
|
+
await fs5.unlink(tempPath);
|
|
1056
1099
|
} catch {
|
|
1057
1100
|
}
|
|
1058
1101
|
throw error;
|
|
@@ -1067,39 +1110,30 @@ async function writeStorageAtomic(targetPath, storage) {
|
|
|
1067
1110
|
`);
|
|
1068
1111
|
}
|
|
1069
1112
|
async function ensureStorageFileExists(targetPath) {
|
|
1070
|
-
await
|
|
1113
|
+
await fs5.mkdir(dirname5(targetPath), { recursive: true });
|
|
1071
1114
|
const emptyContent = `${JSON.stringify(createEmptyStorage(), null, 2)}
|
|
1072
1115
|
`;
|
|
1073
1116
|
try {
|
|
1074
|
-
await
|
|
1117
|
+
await fs5.writeFile(targetPath, emptyContent, { flag: "wx", mode: FILE_MODE });
|
|
1075
1118
|
} catch (error) {
|
|
1076
1119
|
if (getErrorCode(error) !== "EEXIST") throw error;
|
|
1077
1120
|
}
|
|
1078
1121
|
}
|
|
1079
|
-
async function withFileLock(fn) {
|
|
1080
|
-
const storagePath = getStoragePath2();
|
|
1081
|
-
await ensureStorageFileExists(storagePath);
|
|
1082
|
-
let release = null;
|
|
1083
|
-
try {
|
|
1084
|
-
release = await lockfile.lock(storagePath, LOCK_OPTIONS);
|
|
1085
|
-
return await fn(storagePath);
|
|
1086
|
-
} finally {
|
|
1087
|
-
if (release) {
|
|
1088
|
-
try {
|
|
1089
|
-
await release();
|
|
1090
|
-
} catch {
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
1122
|
var AccountStore = class {
|
|
1123
|
+
storagePath;
|
|
1124
|
+
constructor(filename) {
|
|
1125
|
+
this.storagePath = resolveStoragePath(filename ?? ACCOUNTS_FILENAME);
|
|
1126
|
+
}
|
|
1127
|
+
async withLock(fn) {
|
|
1128
|
+
await ensureStorageFileExists(this.storagePath);
|
|
1129
|
+
return await withDirectoryLock(this.storagePath, () => fn(this.storagePath));
|
|
1130
|
+
}
|
|
1096
1131
|
async load() {
|
|
1097
|
-
const storage = await loadAccounts();
|
|
1132
|
+
const storage = await loadAccounts(this.storagePath);
|
|
1098
1133
|
return storage ?? createEmptyStorage();
|
|
1099
1134
|
}
|
|
1100
1135
|
async readCredentials(uuid) {
|
|
1101
|
-
const
|
|
1102
|
-
const storage = await readStorageFromDisk(storagePath, false);
|
|
1136
|
+
const storage = await readStorageFromDisk(this.storagePath, false);
|
|
1103
1137
|
if (!storage) return null;
|
|
1104
1138
|
const account = storage.accounts.find((a) => a.uuid === uuid);
|
|
1105
1139
|
if (!account) return null;
|
|
@@ -1111,7 +1145,7 @@ var AccountStore = class {
|
|
|
1111
1145
|
};
|
|
1112
1146
|
}
|
|
1113
1147
|
async mutateAccount(uuid, fn) {
|
|
1114
|
-
return await
|
|
1148
|
+
return await this.withLock(async (storagePath) => {
|
|
1115
1149
|
const current = await readStorageFromDisk(storagePath, false);
|
|
1116
1150
|
if (!current) return null;
|
|
1117
1151
|
const account = current.accounts.find((a) => a.uuid === uuid);
|
|
@@ -1122,14 +1156,14 @@ var AccountStore = class {
|
|
|
1122
1156
|
});
|
|
1123
1157
|
}
|
|
1124
1158
|
async mutateStorage(fn) {
|
|
1125
|
-
await
|
|
1159
|
+
await this.withLock(async (storagePath) => {
|
|
1126
1160
|
const current = await readStorageFromDisk(storagePath, false) ?? createEmptyStorage();
|
|
1127
1161
|
fn(current);
|
|
1128
1162
|
await writeStorageAtomic(storagePath, current);
|
|
1129
1163
|
});
|
|
1130
1164
|
}
|
|
1131
1165
|
async addAccount(account) {
|
|
1132
|
-
await
|
|
1166
|
+
await this.withLock(async (storagePath) => {
|
|
1133
1167
|
const current = await readStorageFromDisk(storagePath, false) ?? createEmptyStorage();
|
|
1134
1168
|
const exists = current.accounts.some(
|
|
1135
1169
|
(a) => a.uuid === account.uuid || a.refreshToken === account.refreshToken
|
|
@@ -1140,7 +1174,7 @@ var AccountStore = class {
|
|
|
1140
1174
|
});
|
|
1141
1175
|
}
|
|
1142
1176
|
async removeAccount(uuid) {
|
|
1143
|
-
return await
|
|
1177
|
+
return await this.withLock(async (storagePath) => {
|
|
1144
1178
|
const current = await readStorageFromDisk(storagePath, false);
|
|
1145
1179
|
if (!current) return false;
|
|
1146
1180
|
const initialLength = current.accounts.length;
|
|
@@ -1159,7 +1193,7 @@ var AccountStore = class {
|
|
|
1159
1193
|
});
|
|
1160
1194
|
}
|
|
1161
1195
|
async clear() {
|
|
1162
|
-
await
|
|
1196
|
+
await this.withLock(async (storagePath) => {
|
|
1163
1197
|
await writeStorageAtomic(storagePath, createEmptyStorage());
|
|
1164
1198
|
});
|
|
1165
1199
|
}
|
|
@@ -1179,7 +1213,7 @@ function createExecutorForProvider(providerName, dependencies) {
|
|
|
1179
1213
|
const {
|
|
1180
1214
|
handleRateLimitResponse,
|
|
1181
1215
|
formatWaitTime: formatWaitTime2,
|
|
1182
|
-
sleep:
|
|
1216
|
+
sleep: sleep3,
|
|
1183
1217
|
showToast: showToast2,
|
|
1184
1218
|
getAccountLabel: getAccountLabel2
|
|
1185
1219
|
} = dependencies;
|
|
@@ -1190,7 +1224,7 @@ function createExecutorForProvider(providerName, dependencies) {
|
|
|
1190
1224
|
for (let attempt = 0; attempt < MAX_SERVER_RETRIES_PER_ATTEMPT; attempt++) {
|
|
1191
1225
|
const backoff = Math.min(SERVER_RETRY_BASE_MS * 2 ** attempt, SERVER_RETRY_MAX_MS);
|
|
1192
1226
|
const jitteredBackoff = backoff * (0.5 + Math.random() * 0.5);
|
|
1193
|
-
await
|
|
1227
|
+
await sleep3(jitteredBackoff);
|
|
1194
1228
|
let retryResponse;
|
|
1195
1229
|
try {
|
|
1196
1230
|
retryResponse = await runtime.fetch(input, init);
|
|
@@ -1348,7 +1382,7 @@ function createExecutorForProvider(providerName, dependencies) {
|
|
|
1348
1382
|
`All ${manager.getAccountCount()} account(s) rate-limited. Waiting ${formatWaitTime2(waitMs)}...`,
|
|
1349
1383
|
"warning"
|
|
1350
1384
|
);
|
|
1351
|
-
await
|
|
1385
|
+
await sleep3(waitMs);
|
|
1352
1386
|
}
|
|
1353
1387
|
}
|
|
1354
1388
|
return {
|
|
@@ -1582,7 +1616,7 @@ function createRateLimitHandlers(dependencies) {
|
|
|
1582
1616
|
}
|
|
1583
1617
|
|
|
1584
1618
|
// src/auth-migration.ts
|
|
1585
|
-
import { promises as
|
|
1619
|
+
import { promises as fs6 } from "fs";
|
|
1586
1620
|
import { join as join6 } from "path";
|
|
1587
1621
|
var AUTH_JSON_FILENAME = "auth.json";
|
|
1588
1622
|
function isValidOAuthCredential(value) {
|
|
@@ -1597,7 +1631,7 @@ async function readAuthJson() {
|
|
|
1597
1631
|
const authPath = resolveAuthJsonPath();
|
|
1598
1632
|
let content;
|
|
1599
1633
|
try {
|
|
1600
|
-
content = await
|
|
1634
|
+
content = await fs6.readFile(authPath, "utf-8");
|
|
1601
1635
|
} catch {
|
|
1602
1636
|
return null;
|
|
1603
1637
|
}
|
|
@@ -1929,17 +1963,12 @@ var PoolChainConfigSchema = v5.object({
|
|
|
1929
1963
|
});
|
|
1930
1964
|
|
|
1931
1965
|
// src/pool-config-store.ts
|
|
1932
|
-
import { promises as
|
|
1966
|
+
import { promises as fs7 } from "fs";
|
|
1933
1967
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
1934
|
-
import { dirname as
|
|
1935
|
-
import * as lockfile2 from "proper-lockfile";
|
|
1968
|
+
import { dirname as dirname6, join as join7 } from "path";
|
|
1936
1969
|
import * as v6 from "valibot";
|
|
1937
1970
|
var POOL_CONFIG_FILENAME = "multiauth-pools.json";
|
|
1938
1971
|
var FILE_MODE2 = 384;
|
|
1939
|
-
var LOCK_OPTIONS2 = {
|
|
1940
|
-
stale: 1e4,
|
|
1941
|
-
retries: { retries: 10, minTimeout: 50, maxTimeout: 2e3, factor: 2 }
|
|
1942
|
-
};
|
|
1943
1972
|
function createEmptyConfig() {
|
|
1944
1973
|
return { pools: [], chains: [] };
|
|
1945
1974
|
}
|
|
@@ -1952,33 +1981,33 @@ function buildTempPath2(targetPath) {
|
|
|
1952
1981
|
async function resolveConfigPath() {
|
|
1953
1982
|
const projectPath = join7(process.cwd(), ".opencode", POOL_CONFIG_FILENAME);
|
|
1954
1983
|
try {
|
|
1955
|
-
await
|
|
1984
|
+
await fs7.access(projectPath);
|
|
1956
1985
|
return projectPath;
|
|
1957
1986
|
} catch {
|
|
1958
1987
|
}
|
|
1959
1988
|
return getGlobalConfigPath();
|
|
1960
1989
|
}
|
|
1961
1990
|
async function ensureConfigFileExists(targetPath) {
|
|
1962
|
-
await
|
|
1991
|
+
await fs7.mkdir(dirname6(targetPath), { recursive: true });
|
|
1963
1992
|
const emptyContent = `${JSON.stringify(createEmptyConfig(), null, 2)}
|
|
1964
1993
|
`;
|
|
1965
1994
|
try {
|
|
1966
|
-
await
|
|
1995
|
+
await fs7.writeFile(targetPath, emptyContent, { flag: "wx", mode: FILE_MODE2 });
|
|
1967
1996
|
} catch (error) {
|
|
1968
1997
|
if (getErrorCode(error) !== "EEXIST") throw error;
|
|
1969
1998
|
}
|
|
1970
1999
|
}
|
|
1971
2000
|
async function writeAtomicText2(targetPath, content) {
|
|
1972
|
-
await
|
|
2001
|
+
await fs7.mkdir(dirname6(targetPath), { recursive: true });
|
|
1973
2002
|
const tempPath = buildTempPath2(targetPath);
|
|
1974
2003
|
try {
|
|
1975
|
-
await
|
|
1976
|
-
await
|
|
1977
|
-
await
|
|
1978
|
-
await
|
|
2004
|
+
await fs7.writeFile(tempPath, content, { encoding: "utf-8", mode: FILE_MODE2 });
|
|
2005
|
+
await fs7.chmod(tempPath, FILE_MODE2);
|
|
2006
|
+
await fs7.rename(tempPath, targetPath);
|
|
2007
|
+
await fs7.chmod(targetPath, FILE_MODE2);
|
|
1979
2008
|
} catch (error) {
|
|
1980
2009
|
try {
|
|
1981
|
-
await
|
|
2010
|
+
await fs7.unlink(tempPath);
|
|
1982
2011
|
} catch {
|
|
1983
2012
|
}
|
|
1984
2013
|
throw error;
|
|
@@ -1987,18 +2016,7 @@ async function writeAtomicText2(targetPath, content) {
|
|
|
1987
2016
|
async function withConfigLock(fn) {
|
|
1988
2017
|
const configPath = await resolveConfigPath();
|
|
1989
2018
|
await ensureConfigFileExists(configPath);
|
|
1990
|
-
|
|
1991
|
-
try {
|
|
1992
|
-
release = await lockfile2.lock(configPath, LOCK_OPTIONS2);
|
|
1993
|
-
return await fn(configPath);
|
|
1994
|
-
} finally {
|
|
1995
|
-
if (release) {
|
|
1996
|
-
try {
|
|
1997
|
-
await release();
|
|
1998
|
-
} catch {
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
}
|
|
2019
|
+
return await withDirectoryLock(configPath, () => fn(configPath));
|
|
2002
2020
|
}
|
|
2003
2021
|
function parsePoolChainConfig(content) {
|
|
2004
2022
|
let parsed;
|
|
@@ -2013,7 +2031,7 @@ function parsePoolChainConfig(content) {
|
|
|
2013
2031
|
async function loadPoolChainConfig() {
|
|
2014
2032
|
const path = await resolveConfigPath();
|
|
2015
2033
|
try {
|
|
2016
|
-
const content = await
|
|
2034
|
+
const content = await fs7.readFile(path, "utf-8");
|
|
2017
2035
|
return parsePoolChainConfig(content) ?? createEmptyConfig();
|
|
2018
2036
|
} catch {
|
|
2019
2037
|
return createEmptyConfig();
|
|
@@ -2350,6 +2368,7 @@ export {
|
|
|
2350
2368
|
showToast,
|
|
2351
2369
|
sleep,
|
|
2352
2370
|
updateConfigField,
|
|
2371
|
+
withDirectoryLock,
|
|
2353
2372
|
writeClaim
|
|
2354
2373
|
};
|
|
2355
2374
|
//# sourceMappingURL=index.js.map
|
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/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 lockfile from \"proper-lockfile\";\nimport * as v from \"valibot\";\nimport { loadAccounts, readStorageFromDisk } from \"./storage\";\nimport { ACCOUNTS_FILENAME } from \"./constants\";\nimport { AccountStorageSchema } from \"./types\";\nimport { getConfigDir, getErrorCode } from \"./utils\";\nimport type { AccountStorage, StoredAccount } from \"./types\";\n\nconst FILE_MODE = 0o600;\nconst LOCK_OPTIONS = {\n stale: 10_000,\n retries: { retries: 10, minTimeout: 50, maxTimeout: 2000, factor: 2 },\n};\n\nfunction getStoragePath(): string {\n return join(getConfigDir(), ACCOUNTS_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\nasync function withFileLock<T>(fn: (storagePath: string) => Promise<T>): Promise<T> {\n const storagePath = getStoragePath();\n await ensureStorageFileExists(storagePath);\n\n let release: (() => Promise<void>) | null = null;\n try {\n release = await lockfile.lock(storagePath, LOCK_OPTIONS);\n return await fn(storagePath);\n } finally {\n if (release) {\n try {\n await release();\n } catch {}\n }\n }\n}\n\nexport interface DiskCredentials {\n refreshToken: string;\n accessToken?: string;\n expiresAt?: number;\n accountId?: string;\n}\n\nexport class AccountStore {\n async load(): Promise<AccountStorage> {\n const storage = await loadAccounts();\n return storage ?? createEmptyStorage();\n }\n\n async readCredentials(uuid: string): Promise<DiskCredentials | null> {\n const storagePath = getStoragePath();\n const storage = await readStorageFromDisk(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 withFileLock(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 withFileLock(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 withFileLock(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 withFileLock(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 withFileLock(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 getStoragePath(): 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(): Promise<AccountStorage | null> {\n const storagePath = getStoragePath();\n const storage = await readStorageFromDisk(storagePath, 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\nexport let ACCOUNTS_FILENAME = DEFAULT_ACCOUNTS_FILENAME;\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 {\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 lockfile from \"proper-lockfile\";\nimport * as v from \"valibot\";\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;\nconst LOCK_OPTIONS = {\n stale: 10_000,\n retries: { retries: 10, minTimeout: 50, maxTimeout: 2000, factor: 2 },\n};\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\n let release: (() => Promise<void>) | null = null;\n try {\n release = await lockfile.lock(configPath, LOCK_OPTIONS);\n return await fn(configPath);\n } finally {\n if (release) {\n try {\n await release();\n } catch {}\n }\n }\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","getStoragePath","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","lockfile","v","FILE_MODE","LOCK_OPTIONS","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 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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-multi-account-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12",
|
|
4
4
|
"description": "Shared core for multi-account OpenCode plugins",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -39,13 +39,11 @@
|
|
|
39
39
|
"directory": "packages/multi-account-core"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"proper-lockfile": "^4.1.2",
|
|
43
42
|
"valibot": "^1.2.0"
|
|
44
43
|
},
|
|
45
44
|
"devDependencies": {
|
|
46
45
|
"@opencode-ai/plugin": "^0.15.30",
|
|
47
46
|
"@types/node": "^25.2.2",
|
|
48
|
-
"@types/proper-lockfile": "^4.1.4",
|
|
49
47
|
"typescript": "^5.8.0"
|
|
50
48
|
},
|
|
51
49
|
"publishConfig": {
|