@bman654/clodex 2.11.4 → 2.11.5

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/oauth-account-selection.ts","../src/registry/io.ts","../src/paths.ts","../src/registry/types.ts","../src/registry/lock.ts","../src/registry/oauth-account-storage.ts","../src/registry/migrate.ts","../src/registry/validate.ts","../src/config.ts","../src/claude-binary.ts","../src/binary-lookup.ts","../src/listener-ready.ts","../src/server-runtime.ts","../src/network-env.ts","../src/wrapper-env.ts"],"sourcesContent":["/** Environment override for selecting one named OAuth account slot. */\nexport const OAUTH_ACCOUNT_ENV = 'CLODEX_OAUTH_ACCOUNT';\n","// src/registry/io.ts — load/save providers.json with secure permissions\n\nimport { randomUUID } from 'node:crypto';\nimport {\n chmodSync,\n closeSync,\n copyFileSync,\n existsSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeSync,\n} from 'node:fs';\nimport { dirname } from 'node:path';\nimport { isDeepStrictEqual } from 'node:util';\nimport { getAppHome, getProvidersPath } from '../paths.js';\nimport type { ProviderRegistry, RegistryModelsCache, RegistryProvider } from './types.js';\nimport {\n OAUTH_ACCOUNT_NAME_RE,\n REGISTRY_SCHEMA_VERSION,\n REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_SLOTS,\n REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT,\n REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES,\n REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT,\n} from './types.js';\nimport {\n assertRegistryWriteOwnership,\n RegistryLockLostError,\n withRegistryWriteLockSync,\n} from './lock.js';\nimport { migrateRegistry } from './migrate.js';\nimport {\n getOAuthAccountSlot,\n migrateActiveOAuthAccountStorage,\n} from './oauth-account-storage.js';\nimport { isValidProviderId } from './validate.js';\n\nconst DIR_MODE = 0o700;\nconst FILE_MODE = 0o600;\n\nexport function ensureSecureAppHome(): void {\n const home = getAppHome();\n mkdirSync(home, { recursive: true, mode: DIR_MODE });\n try {\n chmodSync(home, DIR_MODE);\n } catch {\n // best-effort on platforms that restrict chmod\n }\n}\n\nexport function writeSecureFile(path: string, content: string): void {\n ensureSecureAppHome();\n mkdirSync(dirname(path), { recursive: true, mode: DIR_MODE });\n const fd = openSync(path, 'wx', FILE_MODE);\n try {\n const payload = Buffer.from(content);\n let offset = 0;\n while (offset < payload.length) {\n const written = writeSync(fd, payload, offset, payload.length - offset);\n if (written <= 0) {\n throw new Error(`Could not complete secure file write: ${path}`);\n }\n offset += written;\n }\n fsyncSync(fd);\n } finally {\n closeSync(fd);\n }\n try {\n chmodSync(path, FILE_MODE);\n } catch {\n // best-effort\n }\n}\n\nexport function syncParentDirectory(path: string): void {\n let fd: number | undefined;\n try {\n fd = openSync(dirname(path), 'r');\n fsyncSync(fd);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== 'EINVAL' && code !== 'ENOTSUP' && code !== 'EPERM') throw error;\n } finally {\n if (fd !== undefined) closeSync(fd);\n }\n}\n\nfunction parseProvider(\n raw: unknown,\n diag?: (message: string) => void,\n): RegistryProvider | null {\n if (!raw || typeof raw !== 'object') return null;\n const p = raw as Record<string, unknown>;\n if (typeof p.id !== 'string' || !isValidProviderId(p.id)) return null;\n if (typeof p.templateId !== 'string' || !p.templateId) return null;\n if (typeof p.name !== 'string' || !p.name) return null;\n if (typeof p.enabled !== 'boolean') return null;\n if (typeof p.authRef !== 'string' || !p.authRef) return null;\n if (typeof p.addedAt !== 'string' || !p.addedAt) return null;\n const api = p.api;\n if (!api || typeof api !== 'object') return null;\n\n const provider: RegistryProvider = {\n id: p.id,\n templateId: p.templateId,\n name: p.name,\n enabled: p.enabled,\n authRef: p.authRef,\n api: api as RegistryProvider['api'],\n addedAt: p.addedAt,\n };\n\n if (hasOwn(p, 'defaultAuthRef')) {\n if (typeof p.defaultAuthRef !== 'string' || !p.defaultAuthRef) return null;\n provider.defaultAuthRef = p.defaultAuthRef;\n }\n\n if (p.subscriptionFilter === 'free') {\n provider.subscriptionFilter = p.subscriptionFilter;\n }\n if (typeof p.preserveModelPricing === 'boolean') {\n provider.preserveModelPricing = p.preserveModelPricing;\n }\n if (p.authType === 'api' || p.authType === 'oauth' || p.authType === 'none') {\n provider.authType = p.authType;\n }\n if (hasOwn(p, 'authAccounts')) {\n const slots = parseAuthAccounts(p.authAccounts);\n if (slots === null) return null;\n provider.authAccounts = slots;\n }\n if (hasOwn(p, 'activeAuthAccount')) {\n if (!isAccountName(p.activeAuthAccount)) return null;\n provider.activeAuthAccount = p.activeAuthAccount;\n }\n if (typeof p.refreshedAt === 'string') provider.refreshedAt = p.refreshedAt;\n if (hasOwn(p, 'defaultModelsCache')) {\n const defaultModelsCache = parseModelsCache(p.defaultModelsCache);\n if (!defaultModelsCache) return null;\n provider.defaultModelsCache = defaultModelsCache;\n }\n const modelsCache = parseModelsCache(p.modelsCache);\n if (modelsCache) provider.modelsCache = modelsCache;\n else if (hasOwn(p, 'modelsCache')) {\n diag?.(`Provider registry dropped an invalid model cache for provider \"${p.id}\".`);\n }\n return provider;\n}\n\nfunction hasOwn(record: Record<string, unknown>, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(record, key);\n}\n\n/**\n * Shape check only, deliberately not a slot-membership check: see the\n * `activeAuthAccount` doc comment on RegistryProvider for why a stale-but-\n * well-formed name must survive the load and fail at apply time instead.\n */\nfunction isAccountName(raw: unknown): raw is string {\n return typeof raw === 'string' && OAUTH_ACCOUNT_NAME_RE.test(raw);\n}\n\nfunction parseModelsCache(raw: unknown): RegistryModelsCache | null {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;\n const cache = raw as Record<string, unknown>;\n if (typeof cache.fetchedAt !== 'string' || !Array.isArray(cache.models)) return null;\n if (cache.models.some(model => !model || typeof model !== 'object' || Array.isArray(model))) {\n return null;\n }\n return {\n fetchedAt: cache.fetchedAt,\n models: cache.models as RegistryModelsCache['models'],\n };\n}\n\n/**\n * Named OAuth account slots must survive a registry load intact and are\n * fail-closed: a silently dropped slot would revert a CLODEX_OAUTH_ACCOUNT\n * launch to the default identity and let credential reconciliation delete the\n * slot's tokens as unreferenced. A malformed slot therefore invalidates the\n * whole provider record instead of being skipped.\n */\nfunction parseAuthAccounts(raw: unknown): RegistryProvider['authAccounts'] | null {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;\n const out: NonNullable<RegistryProvider['authAccounts']> = {};\n for (const [name, value] of Object.entries(raw as Record<string, unknown>)) {\n if (!OAUTH_ACCOUNT_NAME_RE.test(name)) return null;\n if (!value || typeof value !== 'object' || Array.isArray(value)) return null;\n const slot = value as Record<string, unknown>;\n if (typeof slot.authRef !== 'string' || !slot.authRef) return null;\n if (typeof slot.addedAt !== 'string' || !slot.addedAt) return null;\n const modelsCache = hasOwn(slot, 'modelsCache')\n ? parseModelsCache(slot.modelsCache)\n : undefined;\n if (hasOwn(slot, 'modelsCache') && !modelsCache) return null;\n out[name] = {\n authRef: slot.authRef,\n addedAt: slot.addedAt,\n ...(modelsCache ? { modelsCache } : {}),\n };\n }\n return out;\n}\n\nfunction hasValidStrictProviderFields(raw: unknown): boolean {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return false;\n const provider = raw as Record<string, unknown>;\n if (hasOwn(provider, 'subscriptionFilter') && provider.subscriptionFilter !== 'free') {\n return false;\n }\n if (hasOwn(provider, 'preserveModelPricing') && typeof provider.preserveModelPricing !== 'boolean') {\n return false;\n }\n if (\n hasOwn(provider, 'authType')\n && provider.authType !== 'api'\n && provider.authType !== 'oauth'\n && provider.authType !== 'none'\n ) {\n return false;\n }\n if (hasOwn(provider, 'refreshedAt') && typeof provider.refreshedAt !== 'string') {\n return false;\n }\n if (hasOwn(provider, 'authAccounts') && parseAuthAccounts(provider.authAccounts) === null) {\n return false;\n }\n if (hasOwn(provider, 'activeAuthAccount') && !isAccountName(provider.activeAuthAccount)) {\n return false;\n }\n if (hasOwn(provider, 'defaultAuthRef')\n && (typeof provider.defaultAuthRef !== 'string' || !provider.defaultAuthRef)) {\n return false;\n }\n if (hasOwn(provider, 'defaultModelsCache')\n && parseModelsCache(provider.defaultModelsCache) === null) {\n return false;\n }\n if (hasOwn(provider, 'modelsCache')) {\n if (parseModelsCache(provider.modelsCache) === null) return false;\n }\n return true;\n}\n\nfunction hasPresentInvalidAuthType(raw: unknown): boolean {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return false;\n const provider = raw as Record<string, unknown>;\n return hasOwn(provider, 'authType')\n && provider.authType !== 'api'\n && provider.authType !== 'oauth'\n && provider.authType !== 'none';\n}\n\n/**\n * Validate the cross-field credential-storage contract for the schema that\n * supplied it. Versions 1-4 are valid migration input only when the parked\n * field is absent. Version 5 requires every live OAuth selector to name a slot\n * and to materialize that exact slot in `authRef`; otherwise launch must fail\n * closed rather than falling back to the provider default.\n */\nfunction hasValidSelectionStorage(\n provider: RegistryProvider,\n schemaVersion: number,\n): boolean {\n const name = provider.activeAuthAccount?.trim();\n const hasDefault = provider.defaultAuthRef !== undefined;\n const hasDefaultCache = provider.defaultModelsCache !== undefined;\n\n if (schemaVersion < REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES\n && Object.values(provider.authAccounts ?? {}).some(account => account.modelsCache !== undefined)) {\n return false;\n }\n if (name && schemaVersion < REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT) {\n return false;\n }\n if (schemaVersion <= REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES\n && (hasDefault || hasDefaultCache)) {\n return false;\n }\n if (!name) return !hasDefault && !hasDefaultCache;\n if (provider.authType !== 'oauth') return !hasDefault && !hasDefaultCache;\n if (schemaVersion <= REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES) {\n // A well-formed but missing legacy slot remains repairable. Migration does\n // not materialize it, and current launch-time selection still throws.\n return true;\n }\n if (schemaVersion !== REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT) {\n // Preserve the lenient reader's forward-compatible behavior. Strict reads\n // reject unsupported versions before reaching this branch.\n return true;\n }\n const selected = getOAuthAccountSlot(provider, name);\n return hasDefault\n && selected !== undefined\n && provider.authRef === selected.authRef\n // A downgraded launch consumes top-level authRef AND modelsCache. Require\n // the cache to be the selected slot's proven cache (or both absent), or it\n // could launch the right credential with another account's entitlements.\n && isDeepStrictEqual(provider.modelsCache, selected.modelsCache);\n}\n\nfunction parseRegistry(\n raw: unknown,\n diag?: (message: string) => void,\n): ProviderRegistry {\n const empty: ProviderRegistry = { schemaVersion: REGISTRY_SCHEMA_VERSION, providers: [] };\n if (!raw || typeof raw !== 'object') return empty;\n const data = raw as Record<string, unknown>;\n const schemaVersion =\n typeof data.schemaVersion === 'number' ? data.schemaVersion : REGISTRY_SCHEMA_VERSION;\n const providers: RegistryProvider[] = [];\n if (Array.isArray(data.providers)) {\n for (const [index, entry] of data.providers.entries()) {\n const parsed = parseProvider(entry, diag);\n const invalidKnownSelectionAuthType = schemaVersion >= REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT\n && schemaVersion <= REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT\n && parsed?.activeAuthAccount !== undefined\n && hasPresentInvalidAuthType(entry);\n const validSelectionStorage = parsed\n ? hasValidSelectionStorage(parsed, schemaVersion)\n : false;\n if (parsed && !invalidKnownSelectionAuthType && validSelectionStorage) {\n providers.push(parsed);\n } else {\n const id = entry && typeof entry === 'object' && typeof (entry as Record<string, unknown>).id === 'string'\n ? ` \"${(entry as Record<string, unknown>).id}\"`\n : ` at index ${index}`;\n const reason = parsed && !validSelectionStorage\n ? ' because its OAuth account selection storage is inconsistent'\n : '';\n diag?.(`Provider registry dropped invalid provider${id}${reason}.`);\n }\n }\n }\n const registry: ProviderRegistry = {\n schemaVersion,\n providers,\n };\n if (typeof data.importedAt === 'string') registry.importedAt = data.importedAt;\n if (typeof data.pricingCacheAt === 'string') registry.pricingCacheAt = data.pricingCacheAt;\n return registry;\n}\n\nfunction parseRegistryStrict(raw: unknown): ProviderRegistry {\n if (!raw || typeof raw !== 'object') {\n throw new Error('Provider registry must be a JSON object.');\n }\n const data = raw as Record<string, unknown>;\n if (\n data.schemaVersion !== REGISTRY_SCHEMA_VERSION\n && data.schemaVersion !== REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_SLOTS\n && data.schemaVersion !== REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT\n && data.schemaVersion !== REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES\n && data.schemaVersion !== REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT\n ) {\n throw new Error('Provider registry has an unsupported schema version.');\n }\n if (!Array.isArray(data.providers)) {\n throw new Error('Provider registry is missing its providers list.');\n }\n for (const entry of data.providers) {\n const provider = parseProvider(entry);\n if (!provider || !hasValidStrictProviderFields(entry)\n || !hasValidSelectionStorage(provider, data.schemaVersion)) {\n throw new Error('Provider registry contains an invalid provider entry.');\n }\n }\n return parseRegistry(raw);\n}\n\nfunction readRegistryStrict(path: string): ProviderRegistry {\n return parseRegistryStrict(JSON.parse(readFileSync(path, 'utf8')));\n}\n\nclass RegistryMigrationValidationError extends Error {\n constructor(\n readonly registryPath: string,\n cause: unknown,\n ) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n super(detail, { cause });\n this.name = 'RegistryMigrationValidationError';\n }\n}\n\nclass RegistryMigrationReadError extends Error {\n constructor(\n readonly registryPath: string,\n cause: unknown,\n ) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n super(detail, { cause });\n this.name = 'RegistryMigrationReadError';\n }\n}\n\nclass RegistrySaveValidationError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'RegistrySaveValidationError';\n }\n}\n\nclass RegistryPersistenceError extends Error {\n constructor(\n readonly registryPath: string,\n cause: unknown,\n ) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n super(detail, { cause });\n this.name = 'RegistryPersistenceError';\n }\n}\n\nclass RegistryDurabilityCheckError extends Error {\n constructor(\n readonly registryPath: string,\n cause: unknown,\n ) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n super(detail, { cause });\n this.name = 'RegistryDurabilityCheckError';\n }\n}\n\nfunction selectedAccountFilesystemError(\n path: string,\n cause: unknown,\n action: string,\n): Error {\n const detail = cause instanceof Error ? cause.message : String(cause);\n return new Error(\n 'Could not safely persist the selected OAuth account before launch. '\n + `Could not ${action} the provider registry at ${path}: ${detail} `\n + 'Check filesystem permissions, storage health, and free disk space, then retry.',\n { cause },\n );\n}\n\nfunction hasMaterializedActiveAccount(registry: ProviderRegistry): boolean {\n return registry.schemaVersion === REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT\n && registry.providers.some(provider => provider.defaultAuthRef !== undefined);\n}\n\nexport function loadRegistry(\n path = getProvidersPath(),\n diag?: (message: string) => void,\n): ProviderRegistry {\n if (!existsSync(path)) {\n return { schemaVersion: REGISTRY_SCHEMA_VERSION, providers: [] };\n }\n let registry: ProviderRegistry;\n try {\n const raw = JSON.parse(readFileSync(path, 'utf8'));\n registry = parseRegistry(raw, diag);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n diag?.(`Could not read the provider registry at ${path}; treating it as empty: ${detail}`);\n return { schemaVersion: REGISTRY_SCHEMA_VERSION, providers: [] };\n }\n\n const migration = migrateRegistry(registry);\n if (!migration.changed) {\n // A previous publication may have renamed ANY schema version before its\n // parent-directory durability barrier failed. This includes clearing a v5\n // selection back to v1/v2. Re-sync every successfully parsed winner so a\n // plain retry repairs both selection and downgrade transitions.\n try {\n syncParentDirectory(path);\n } catch (error) {\n if (hasMaterializedActiveAccount(registry)) {\n throw selectedAccountFilesystemError(path, error, 'durably sync');\n }\n const detail = error instanceof Error ? error.message : String(error);\n diag?.(`Could not durably sync the unchanged provider registry at ${path}; continuing read-only: ${detail}`);\n }\n return registry;\n }\n\n let winner = registry;\n let materializedActiveAccount = migration.materializedActiveAccount;\n try {\n withRegistryWriteLockSync(() => {\n if (!existsSync(path)) {\n if (materializedActiveAccount) {\n throw new Error('the provider registry disappeared during migration');\n }\n return;\n }\n // The lock may have been contended. Re-read and migrate the winner rather\n // than publishing or returning the stale pre-lock snapshot.\n let serialized: string;\n try {\n serialized = readFileSync(path, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error('the provider registry disappeared during migration', { cause: error });\n }\n throw new RegistryMigrationReadError(path, error);\n }\n let raw: unknown;\n try {\n raw = JSON.parse(serialized);\n } catch (error) {\n throw new RegistryMigrationValidationError(path, error);\n }\n // Classify the winner's identity requirement before strict validation.\n // A malformed sibling can make the strict parse throw, but it must not\n // hide a valid selected provider whose downgrade-visible projection\n // would otherwise remain in memory only.\n const lenientCurrent = parseRegistry(raw);\n const lenientMigration = migrateRegistry(lenientCurrent);\n winner = lenientCurrent;\n materializedActiveAccount = lenientMigration.materializedActiveAccount\n || hasMaterializedActiveAccount(lenientCurrent);\n\n let current: ProviderRegistry;\n try {\n current = parseRegistryStrict(raw);\n } catch (error) {\n throw new RegistryMigrationValidationError(path, error);\n }\n const currentMigration = migrateRegistry(current);\n winner = current;\n // The winner under the lock, not the stale pre-lock snapshot, decides\n // whether a failed write could split launch identity across processes.\n materializedActiveAccount = currentMigration.materializedActiveAccount\n || hasMaterializedActiveAccount(current);\n if (currentMigration.changed) {\n try {\n saveRegistry(current, path);\n } catch (error) {\n if (error instanceof RegistrySaveValidationError) {\n throw new RegistryMigrationValidationError(path, error);\n }\n throw error;\n }\n } else {\n // Another process may have renamed this already-migrated winner but\n // failed its parent-directory fsync before we acquired the lock. The\n // authoritative reread must repair that barrier too, not only the\n // optimistic no-migration read above.\n try {\n syncParentDirectory(path);\n } catch (error) {\n throw new RegistryDurabilityCheckError(path, error);\n }\n }\n }, { lockPath: `${path}.lock` });\n return winner;\n } catch (error) {\n if (error instanceof RegistryDurabilityCheckError) {\n if (materializedActiveAccount) {\n throw selectedAccountFilesystemError(\n error.registryPath,\n error,\n 'durably sync',\n );\n }\n throw new Error(\n `Could not durably sync the provider registry at ${error.registryPath}: ${error.message} `\n + 'Check filesystem permissions, storage health, and free disk space, then retry.',\n { cause: error },\n );\n }\n if (materializedActiveAccount) {\n if (error instanceof RegistryMigrationValidationError) {\n throw new Error(\n 'Could not safely persist the selected OAuth account before launch. '\n + `The provider registry at ${error.registryPath} is invalid: ${error.message} `\n + `Repair it or restore ${error.registryPath}.bak, then retry.`,\n { cause: error },\n );\n }\n if (error instanceof RegistryMigrationReadError) {\n throw selectedAccountFilesystemError(\n error.registryPath,\n error,\n 'read',\n );\n }\n if (error instanceof RegistryPersistenceError) {\n throw selectedAccountFilesystemError(\n error.registryPath,\n error,\n 'durably write',\n );\n }\n if (error && typeof error === 'object'\n && typeof (error as NodeJS.ErrnoException).code === 'string') {\n // Lock timeout/lost-lease errors are intentionally untyped and retain\n // the process-contention guidance below. Raw errno failures from lock\n // directory/file I/O need filesystem recovery instead.\n throw selectedAccountFilesystemError(path, error, 'access the lock for');\n }\n const detail = error instanceof Error ? ` ${error.message}` : '';\n throw new Error(\n 'Could not safely persist the selected OAuth account before launch.'\n + `${detail} Stop other Clodex processes and retry.`,\n { cause: error },\n );\n }\n // The historical provider-id rename is presentation-only and remains a\n // best-effort migration. Identity materialization above is not.\n return winner;\n }\n}\n\n/**\n * Load a registry for destructive decisions. Unlike `loadRegistry`, read,\n * parse, and provider-shape errors propagate so callers cannot confuse an\n * unreadable registry with an empty one.\n */\nexport function loadRegistryStrict(path = getProvidersPath()): ProviderRegistry {\n if (!existsSync(path)) {\n return { schemaVersion: REGISTRY_SCHEMA_VERSION, providers: [] };\n }\n const registry = readRegistryStrict(path);\n migrateRegistry(registry);\n return registry;\n}\n\nexport function saveRegistry(registry: ProviderRegistry, path = getProvidersPath()): void {\n assertRegistryWriteOwnership(path);\n // Programmatic callers and strict legacy loads may hand this function a\n // v3/v4 selector. Upgrade it under the same write lock so this build never\n // publishes a selector that a downgraded launch will ignore.\n if (registry.schemaVersion >= REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT\n && registry.schemaVersion <= REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES) {\n migrateActiveOAuthAccountStorage(registry);\n }\n for (const provider of registry.providers) {\n if (!hasValidSelectionStorage(\n provider,\n REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT,\n )) {\n throw new RegistrySaveValidationError(\n 'Provider registry contains invalid OAuth account selection storage.',\n );\n }\n }\n // Slot state fences older writers via the schema version (see types.ts);\n // slot-free registries return to v1 so old builds interoperate again.\n // Highest state present wins. Version 3 fences the selector from older\n // writers; version 5 also projects it into `authRef`, which older lenient\n // launchers already read.\n const hasMaterializedSelector = registry.providers.some(\n provider => provider.defaultAuthRef !== undefined,\n );\n const hasAccountModelCaches = registry.providers.some(provider => (\n Object.values(provider.authAccounts ?? {}).some(account => account.modelsCache !== undefined)\n ));\n const hasSelector = registry.providers.some(provider => provider.activeAuthAccount !== undefined);\n const hasSlots = registry.providers.some(\n provider => provider.authAccounts && Object.keys(provider.authAccounts).length > 0,\n );\n const schemaVersion = hasMaterializedSelector\n ? REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT\n : hasAccountModelCaches\n ? REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES\n : hasSelector\n ? REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT\n : hasSlots\n ? REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_SLOTS\n : REGISTRY_SCHEMA_VERSION;\n const serializedRegistry = { ...registry, schemaVersion };\n // Validate the exact JSON shape about to be published. This catches values\n // omitted by JSON.stringify (for example an accidentally undefined authRef)\n // instead of letting the next load discover the provider has disappeared.\n try {\n parseRegistryStrict(JSON.parse(JSON.stringify(serializedRegistry)));\n } catch (error) {\n throw new RegistrySaveValidationError(\n error instanceof Error ? error.message : String(error),\n { cause: error },\n );\n }\n const payload = `${JSON.stringify(serializedRegistry, null, 2)}\\n`;\n const backup = `${path}.bak`;\n if (existsSync(path)) {\n try {\n copyFileSync(path, backup);\n } catch {\n // backup is best-effort\n }\n }\n const tmp = `${path}.${process.pid}.${randomUUID()}.tmp`;\n try {\n writeSecureFile(tmp, payload);\n assertRegistryWriteOwnership(path);\n renameSync(tmp, path);\n syncParentDirectory(path);\n } catch (error) {\n if (error instanceof RegistryLockLostError) throw error;\n throw new RegistryPersistenceError(path, error);\n } finally {\n try {\n unlinkSync(tmp);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw new RegistryPersistenceError(path, err);\n }\n }\n }\n}\n\nexport function emptyRegistry(): ProviderRegistry {\n return { schemaVersion: REGISTRY_SCHEMA_VERSION, providers: [] };\n}\n","import { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nexport const APP_DIR_NAME = 'clodex';\n\ninterface HomeEnv {\n HOME?: string;\n CLODEX_HOME?: string;\n USERPROFILE?: string;\n}\n\nfunction userHome(env: HomeEnv = process.env): string {\n return env.HOME ?? env.USERPROFILE ?? homedir();\n}\n\nexport function resolveAppHomeOverride(env: HomeEnv = process.env): string | undefined {\n const override = env.CLODEX_HOME;\n return override?.trim() || undefined;\n}\n\nexport function getAppHome(env: HomeEnv = process.env): string {\n const override = resolveAppHomeOverride(env);\n if (override) return override;\n return join(userHome(env), `.${APP_DIR_NAME}`);\n}\n\nexport function getConfigPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'config.json');\n}\n\nexport function getLocalPatchesPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'local-patches.mjs');\n}\n\nexport function getProvidersPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'providers.json');\n}\n\nexport function getCredentialCleanupPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'credential-cleanup.json');\n}\n\nexport function getLogsPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'logs');\n}\n","// src/registry/types.ts — native provider registry schema (no secrets)\n\nimport type { FreeStatus } from '../free-models.js';\nimport type { ModelRuntimeCompatibility } from '../model-runtime-compatibility.js';\n\nexport const REGISTRY_SCHEMA_VERSION = 1;\n\n/**\n * Written whenever any provider carries named OAuth account slots. Builds\n * >= 1.3.0 fail closed on an unknown schema version in every MUTATING path\n * (parseRegistryStrict throws), so those builds cannot load a slot-bearing\n * registry, drop the unknown field, and save the providers back slot-less.\n * Releases 0.1.0-1.2.2 have no strict loader and silently strip slot state;\n * the credentials remain recoverable in the credential store. A registry\n * whose last slot is removed is written back at version 1, so older builds\n * interoperate again the moment no slot state exists.\n */\nexport const REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_SLOTS = 2;\n\n/**\n * Written whenever any provider carries `activeAuthAccount`.\n *\n * A DISTINCT version, not a reuse of the slot version: a build from before the\n * stored selector existed accepts version 2, parses the slots, silently\n * ignores the unknown `activeAuthAccount`, and saves the registry back without\n * it. Version 3 stops that, because its strict loader throws on a version it\n * does not know. A registry whose selector is cleared falls back to 2 (or 1),\n * so older builds interoperate again as soon as no selector state exists.\n *\n * Versions 3 and 4 are also migration sources for downgrade-safe selection\n * storage. They still carry the provider default in `authRef`; current builds\n * project the selected slot into that field and park the default separately\n * before writing version 5.\n */\nexport const REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT = 3;\n\n/**\n * Written when a named OAuth slot carries its own model-entitlement cache.\n * A cache is not a credential, but silently dropping it would make a temporary\n * account reuse the persisted account's catalog. Version 4 therefore fences\n * older mutating builds that know about slots but not their cache isolation.\n */\nexport const REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES = 4;\n\n/**\n * Written whenever `defaultAuthRef` parks a provider's own OAuth credential\n * while `authRef` points at the selected named slot. A pre-selector build's\n * lenient loader ignores both the version and the new fields, but already\n * reads `authRef`, so it launches as the selected identity. Its strict\n * mutation paths reject version 5 and cannot discard the parked default.\n */\nexport const REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT = 5;\n\n/**\n * Shape rule for a named OAuth account-slot name — the single home. Slot\n * names land in credential-store scopes and env values, and the registry\n * parser must accept exactly what `validateOAuthAccountName` admits, or a\n * saved slot fails to survive a load.\n */\nexport const OAUTH_ACCOUNT_NAME_RE = /^[a-z0-9][a-z0-9_-]{0,31}$/;\n\nexport type RegistrySubscriptionFilter = 'free';\n\nexport interface CachedModel {\n id: string;\n name: string;\n upstreamModelId: string;\n family?: string;\n brand?: string;\n contextWindow?: number;\n /** Highest input window the model accepts, reachable via the `max` context stop. */\n maxContextWindow?: number;\n /** Share of the raw window a client fills; mirrors the Codex catalog field. */\n effectiveContextPercent?: number;\n /** Input size above which the provider bills the whole request at a higher rate. */\n pricingBoundary?: number;\n /** How the provider prices above the boundary, for the user-facing warning. */\n pricingBoundaryNote?: string;\n /** Largest output the model accepts, independent of the input window. */\n maxOutputTokens?: number;\n cost?: { input: number; output: number; cache_read?: number; cache_write?: number };\n isFree?: boolean;\n freeStatus?: FreeStatus;\n modelFormat: 'anthropic' | 'openai' | 'cloud-code';\n /** Per-model override — wins over provider-level api.npm */\n npm?: string;\n /** Per-model override — wins over provider-level api.url */\n apiUrl?: string;\n sourceBackend?: string;\n /** Provider-reported request parameters, e.g. OpenRouter supported_parameters. */\n supportedParameters?: string[];\n /** Broad model metadata: model can produce reasoning/thinking output. */\n reasoning?: boolean;\n /** Streaming/interleaved reasoning field name from metadata, e.g. reasoning_content. */\n interleavedReasoningField?: string;\n /** Backend capability: model requires the Responses-Lite request shape (x-openai-internal-codex-responses-lite). */\n useResponsesLite?: boolean;\n /** Backend capability: model must use the WebSocket Responses transport instead of HTTP. */\n preferWebSockets?: boolean;\n /** Supported input modalities preserved from curated provider metadata. */\n modalities?: ('text' | 'image')[];\n /** Provider-neutral per-model wire quirks. */\n compatibility?: ModelRuntimeCompatibility;\n}\n\nexport interface RegistryModelsCache {\n fetchedAt: string;\n models: CachedModel[];\n}\n\nexport interface RegistryOAuthAccount {\n authRef: string;\n addedAt: string;\n /** Catalog discovered with this named slot's credential. */\n modelsCache?: RegistryModelsCache;\n}\n\nexport interface RegistryProvider {\n id: string;\n templateId: string;\n name: string;\n enabled: boolean;\n authRef: string;\n /**\n * The provider's own OAuth credential while a named slot is selected.\n * During that time `authRef` deliberately points at the selected slot so a\n * downgraded pre-selector build launches as the same identity. Clearing the\n * selection restores this value to `authRef` and removes the field.\n */\n defaultAuthRef?: string;\n /** Catalog discovered with the provider default while a named slot is selected. */\n defaultModelsCache?: RegistryModelsCache;\n authType?: 'api' | 'oauth' | 'none';\n /**\n * Named OAuth account slots beyond the default credential\n * (`clodex providers auth openai --account <name>`). Each slot owns a\n * disjoint credential-store lineage; CLODEX_OAUTH_ACCOUNT selects one for a\n * launch without replacing the provider-owned default credential.\n */\n authAccounts?: Record<string, RegistryOAuthAccount>;\n /**\n * The `authAccounts` slot every launch uses, so the running identity does not\n * depend on remembering an environment variable. Absent means the provider's\n * own default credential. CLODEX_OAUTH_ACCOUNT still overrides it for a\n * single run. While present on an OAuth provider, persisted `authRef` is the\n * selected slot and `defaultAuthRef` parks the provider default for rollback.\n *\n * Legacy v3/v4 bytes enforce only the name shape so a missing slot remains\n * loadable and repairable; applying it still fails loud. V5 additionally\n * requires membership and exact authRef/cache projection, because a missing\n * materialized slot is corruption rather than a legacy repair state.\n */\n activeAuthAccount?: string;\n subscriptionFilter?: RegistrySubscriptionFilter;\n /** Keep provider/curated costs instead of replacing them with the global pricing cache. */\n preserveModelPricing?: boolean;\n api: {\n npm?: string;\n url?: string;\n id?: string;\n /** Static headers sent on every upstream request (e.g. a plan/auth-tracking header a custom endpoint requires). */\n headers?: Record<string, string>;\n };\n modelsCache?: RegistryModelsCache;\n addedAt: string;\n refreshedAt?: string;\n}\n\nexport interface ProviderRegistry {\n schemaVersion: number;\n providers: RegistryProvider[];\n importedAt?: string;\n pricingCacheAt?: string;\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport { createHash, randomUUID } from 'node:crypto';\nimport {\n closeSync,\n fstatSync,\n fsyncSync,\n linkSync,\n mkdirSync,\n openSync,\n readFileSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { userInfo } from 'node:os';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport { getProvidersPath } from '../paths.js';\n\nconst DEFAULT_WAIT_MS = 30_000;\nconst DEFAULT_CREDENTIAL_MUTATION_WAIT_MS = 150_000;\nconst DEFAULT_RETRY_MS = 25;\n\ninterface RegistryLockOwner {\n pid: number;\n startedAt: number;\n token: string;\n}\n\ninterface RegistryLockSnapshot {\n raw: string;\n device: number;\n inode: number;\n modifiedAt: number;\n}\n\ninterface RegistryLockOptions {\n lockPath?: string;\n waitMs?: number;\n retryMs?: number;\n now?: () => number;\n isAlive?: (pid: number) => boolean;\n}\n\ninterface RegistryLockContext {\n leases: ReadonlyMap<string, RegistryLockLease>;\n}\n\nexport interface RegistryLockLease {\n active: boolean;\n readonly lockPath: string;\n readonly token: string;\n readonly device: number;\n readonly inode: number;\n assertOwned: () => void;\n release: () => void;\n}\n\nconst registryLockContext = new AsyncLocalStorage<RegistryLockContext>();\n\nexport class RegistryLockLostError extends Error {\n constructor(lockPath: string) {\n super(`Provider registry lock ownership was lost before write: ${lockPath}`);\n this.name = 'RegistryLockLostError';\n }\n}\n\nexport function getRegistryLockPath(): string {\n return `${getProvidersPath()}.lock`;\n}\n\nfunction isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code === 'EPERM';\n }\n}\n\nfunction parseLockOwner(raw: string): RegistryLockOwner | null {\n try {\n const parsed = JSON.parse(raw) as Partial<RegistryLockOwner>;\n if (!Number.isInteger(parsed.pid) || (parsed.pid ?? 0) <= 0) return null;\n if (\n typeof parsed.startedAt !== 'number' ||\n !Number.isFinite(parsed.startedAt)\n )\n return null;\n if (typeof parsed.token !== 'string' || parsed.token.length === 0)\n return null;\n return parsed as RegistryLockOwner;\n } catch {\n return null;\n }\n}\n\nfunction createLockRecord(\n lockPath: string,\n owner: RegistryLockOwner,\n): RegistryLockSnapshot | null {\n const raw = JSON.stringify(owner);\n const tempPath = `${lockPath}.${process.pid}.${owner.token}.tmp`;\n let fd: number | undefined;\n try {\n fd = openSync(tempPath, 'wx', 0o600);\n writeFileSync(fd, raw);\n fsyncSync(fd);\n const stats = fstatSync(fd);\n try {\n linkSync(tempPath, lockPath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') return null;\n throw err;\n }\n return {\n raw,\n device: stats.dev,\n inode: stats.ino,\n modifiedAt: stats.mtimeMs,\n };\n } finally {\n if (fd !== undefined) closeSync(fd);\n try {\n unlinkSync(tempPath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n }\n}\n\nfunction lockFileMatchesLease(lease: RegistryLockLease): boolean {\n let fd: number | undefined;\n try {\n fd = openSync(lease.lockPath, 'r');\n const openedStats = fstatSync(fd);\n const owner = parseLockOwner(readFileSync(fd, 'utf8'));\n const pathStats = statSync(lease.lockPath);\n return (\n owner?.token === lease.token &&\n openedStats.dev === lease.device &&\n openedStats.ino === lease.inode &&\n pathStats.dev === lease.device &&\n pathStats.ino === lease.inode\n );\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return false;\n throw err;\n } finally {\n if (fd !== undefined) closeSync(fd);\n }\n}\n\nfunction createLease(\n lockPath: string,\n owner: RegistryLockOwner,\n snapshot: RegistryLockSnapshot,\n): RegistryLockLease {\n const lease: RegistryLockLease = {\n active: true,\n lockPath,\n token: owner.token,\n device: snapshot.device,\n inode: snapshot.inode,\n assertOwned: () => {\n if (!lease.active || !lockFileMatchesLease(lease)) {\n lease.active = false;\n throw new RegistryLockLostError(lockPath);\n }\n },\n release: () => {\n if (!lease.active) return;\n lease.active = false;\n if (lockFileMatchesLease(lease)) unlinkSync(lockPath);\n },\n };\n return lease;\n}\n\nexport function assertRegistryWriteOwnership(\n registryPath = getProvidersPath(),\n): void {\n const lockPath = `${registryPath}.lock`;\n const lease = registryLockContext.getStore()?.leases.get(lockPath);\n if (!lease) throw new RegistryLockLostError(lockPath);\n lease.assertOwned();\n}\n\nfunction getStaleLockSnapshot(\n lockPath: string,\n alive: (pid: number) => boolean,\n): RegistryLockSnapshot | null {\n const raw = readFileSync(lockPath, 'utf8');\n const stats = statSync(lockPath);\n const snapshot: RegistryLockSnapshot = {\n raw,\n device: stats.dev,\n inode: stats.ino,\n modifiedAt: stats.mtimeMs,\n };\n const owner = parseLockOwner(raw);\n if (owner) return alive(owner.pid) ? null : snapshot;\n return snapshot;\n}\n\nfunction removeStaleLock(\n lockPath: string,\n expected?: RegistryLockSnapshot,\n): boolean {\n try {\n if (expected) {\n const raw = readFileSync(lockPath, 'utf8');\n const stats = statSync(lockPath);\n if (\n raw !== expected.raw ||\n stats.dev !== expected.device ||\n stats.ino !== expected.inode ||\n stats.mtimeMs !== expected.modifiedAt\n )\n return false;\n }\n unlinkSync(lockPath);\n return true;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n return false;\n }\n}\n\nfunction tryAcquireReaperGuard(\n lockPath: string,\n now: number,\n alive: (pid: number) => boolean,\n): RegistryLockLease | null {\n const guardPath = `${lockPath}.reap`;\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const owner: RegistryLockOwner = {\n pid: process.pid,\n startedAt: now,\n token: randomUUID(),\n };\n try {\n const snapshot = createLockRecord(guardPath, owner);\n if (snapshot) return createLease(guardPath, owner, snapshot);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw err;\n }\n\n let stale: RegistryLockSnapshot | null = null;\n try {\n stale = getStaleLockSnapshot(guardPath, alive);\n } catch (readErr) {\n if ((readErr as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw readErr;\n }\n if (!stale) return null;\n if (!removeStaleLock(guardPath, stale)) continue;\n }\n return null;\n}\n\nexport function tryAcquireRegistryLock(\n lockPath = getRegistryLockPath(),\n options: Pick<RegistryLockOptions, 'now' | 'isAlive'> = {},\n): RegistryLockLease | null {\n const now = options.now?.() ?? Date.now();\n const alive = options.isAlive ?? isPidAlive;\n mkdirSync(dirname(lockPath), { recursive: true, mode: 0o700 });\n\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const owner: RegistryLockOwner = {\n pid: process.pid,\n startedAt: now,\n token: randomUUID(),\n };\n try {\n const snapshot = createLockRecord(lockPath, owner);\n if (snapshot) return createLease(lockPath, owner, snapshot);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw err;\n }\n\n let stale: RegistryLockSnapshot | null = null;\n try {\n stale = getStaleLockSnapshot(lockPath, alive);\n } catch (readErr) {\n if ((readErr as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw readErr;\n }\n if (!stale) return null;\n const reaperLease = tryAcquireReaperGuard(lockPath, now, alive);\n if (!reaperLease) return null;\n try {\n let currentStale: RegistryLockSnapshot | null = null;\n try {\n currentStale = getStaleLockSnapshot(lockPath, alive);\n } catch (readErr) {\n if ((readErr as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw readErr;\n }\n if (!currentStale) return null;\n if (!removeStaleLock(lockPath, currentStale)) continue;\n } finally {\n reaperLease.release();\n }\n }\n return null;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction sleepSync(ms: number): void {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\nfunction lockTimeoutError(\n lockPath: string,\n waitMs: number,\n alive: (pid: number) => boolean,\n): Error {\n let owner: RegistryLockOwner | null = null;\n try {\n owner = parseLockOwner(readFileSync(lockPath, 'utf8'));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n if (owner && alive(owner.pid)) {\n return new Error(\n `Timed out after ${waitMs}ms waiting for lock held by clodex process ` +\n `(pid ${owner.pid}): ${lockPath}`,\n );\n }\n return new Error(\n `Timed out after ${waitMs}ms waiting for lock: ${lockPath}`,\n );\n}\n\nexport async function withRegistryWriteLock<T>(\n operation: () => Promise<T> | T,\n options: RegistryLockOptions = {},\n): Promise<T> {\n const lockPath = options.lockPath ?? getRegistryLockPath();\n const inheritedLeases = registryLockContext.getStore()?.leases;\n if (inheritedLeases?.get(lockPath)?.active) return operation();\n\n const waitMs = options.waitMs ?? DEFAULT_WAIT_MS;\n const retryMs = options.retryMs ?? DEFAULT_RETRY_MS;\n const now = options.now ?? Date.now;\n const deadline = now() + waitMs;\n let lease: RegistryLockLease | null = null;\n\n while (!lease) {\n lease = tryAcquireRegistryLock(lockPath, {\n now,\n isAlive: options.isAlive,\n });\n if (lease) break;\n if (now() >= deadline)\n throw lockTimeoutError(lockPath, waitMs, options.isAlive ?? isPidAlive);\n await sleep(retryMs);\n }\n\n const leases = new Map(inheritedLeases);\n leases.set(lockPath, lease);\n const context: RegistryLockContext = { leases };\n return registryLockContext.run(context, async () => {\n try {\n return await operation();\n } finally {\n lease.release();\n }\n });\n}\n\nexport function withRegistryWriteLockSync<T>(\n operation: () => T,\n options: RegistryLockOptions = {},\n): T {\n const lockPath = options.lockPath ?? getRegistryLockPath();\n const inheritedLeases = registryLockContext.getStore()?.leases;\n if (inheritedLeases?.get(lockPath)?.active) return operation();\n\n const waitMs = options.waitMs ?? DEFAULT_WAIT_MS;\n const retryMs = options.retryMs ?? DEFAULT_RETRY_MS;\n const now = options.now ?? Date.now;\n const deadline = now() + waitMs;\n let lease: RegistryLockLease | null = null;\n\n while (!lease) {\n lease = tryAcquireRegistryLock(lockPath, {\n now,\n isAlive: options.isAlive,\n });\n if (lease) break;\n if (now() >= deadline)\n throw lockTimeoutError(lockPath, waitMs, options.isAlive ?? isPidAlive);\n sleepSync(retryMs);\n }\n\n const leases = new Map(inheritedLeases);\n leases.set(lockPath, lease);\n const context: RegistryLockContext = { leases };\n return registryLockContext.run(context, () => {\n try {\n return operation();\n } finally {\n lease.release();\n }\n });\n}\n\nexport function getCredentialMutationLockPath(authRef: string): string {\n const digest = createHash('sha256')\n .update('clodex-credential-mutation\\0')\n .update(authRef)\n .digest('hex');\n return join(getCredentialLockRoot(), `${digest}.lock`);\n}\n\nfunction getNativeCredentialRoot(): string {\n const nativeHome = userInfo().homedir;\n if (!nativeHome || !isAbsolute(nativeHome)) {\n throw new Error('Could not determine the native user home for credential coordination');\n }\n return join(nativeHome, '.clodex');\n}\n\nexport function getCredentialLockRoot(): string {\n return join(getNativeCredentialRoot(), 'credential-locks');\n}\n\nexport function getCredentialStateRoot(): string {\n return join(getNativeCredentialRoot(), 'keyring-state');\n}\n\nexport function withCredentialMutationLock<T>(\n authRef: string,\n operation: () => Promise<T> | T,\n options: Pick<RegistryLockOptions, 'waitMs' | 'retryMs'> = {},\n): Promise<T> {\n return withRegistryWriteLock(operation, {\n ...options,\n lockPath: getCredentialMutationLockPath(authRef),\n waitMs: options.waitMs ?? DEFAULT_CREDENTIAL_MUTATION_WAIT_MS,\n });\n}\n\nexport function getProviderMutationLockPath(providerSlot: string): string {\n const digest = createHash('sha256')\n .update('clodex-provider-mutation\\0')\n .update(providerSlot)\n .digest('hex');\n return `${getProvidersPath()}.provider-${digest}.lock`;\n}\n\nexport function withProviderMutationLock<T>(\n providerSlot: string,\n operation: () => Promise<T> | T,\n): Promise<T> {\n return withRegistryWriteLock(operation, {\n lockPath: getProviderMutationLockPath(providerSlot),\n });\n}\n","import type { ProviderRegistry, RegistryProvider } from './types.js';\n\n/**\n * Resolve only an account slot the registry actually owns. Account names such\n * as `constructor` are valid, so ordinary bracket lookup can otherwise return\n * an inherited Object.prototype member and turn a stale selector into data.\n */\nexport function getOAuthAccountSlot(\n provider: Pick<RegistryProvider, 'authAccounts'>,\n name: string,\n): NonNullable<RegistryProvider['authAccounts']>[string] | undefined {\n const accounts = provider.authAccounts;\n return accounts && Object.prototype.hasOwnProperty.call(accounts, name)\n ? accounts[name]\n : undefined;\n}\n\n/** The provider-owned credential, whether or not a named slot is selected. */\nexport function providerDefaultAuthRef(\n provider: Pick<RegistryProvider, 'authRef' | 'defaultAuthRef'>,\n): string {\n return provider.defaultAuthRef ?? provider.authRef;\n}\n\n/**\n * Persist one named selection in the downgrade-visible `authRef` field while\n * retaining the provider default for an exact rollback.\n */\nexport function storeActiveOAuthAccount(\n provider: RegistryProvider,\n name: string,\n selectedAuthRef: string,\n): boolean {\n const previousAuthRef = provider.authRef;\n const previousDefaultAuthRef = provider.defaultAuthRef;\n const previousDefaultModelsCache = provider.defaultModelsCache;\n const previousAccount = provider.activeAuthAccount;\n if (provider.defaultAuthRef === undefined) {\n provider.defaultAuthRef = provider.authRef;\n if (provider.modelsCache) provider.defaultModelsCache = provider.modelsCache;\n }\n provider.authRef = selectedAuthRef;\n provider.activeAuthAccount = name;\n return previousAuthRef !== provider.authRef\n || previousDefaultAuthRef !== provider.defaultAuthRef\n || previousDefaultModelsCache !== provider.defaultModelsCache\n || previousAccount !== provider.activeAuthAccount;\n}\n\n/** Restore the parked provider default and remove all persisted selection state. */\nexport function clearActiveOAuthAccount(provider: RegistryProvider): boolean {\n const previousAuthRef = provider.authRef;\n const previousDefaultAuthRef = provider.defaultAuthRef;\n const previousDefaultModelsCache = provider.defaultModelsCache;\n const previousAccount = provider.activeAuthAccount;\n const hasMaterializedSelection = provider.defaultAuthRef !== undefined;\n provider.authRef = providerDefaultAuthRef(provider);\n if (hasMaterializedSelection) {\n if (provider.defaultModelsCache) {\n provider.modelsCache = provider.defaultModelsCache;\n provider.refreshedAt = provider.defaultModelsCache.fetchedAt;\n } else {\n delete provider.modelsCache;\n delete provider.refreshedAt;\n }\n }\n delete provider.defaultAuthRef;\n delete provider.defaultModelsCache;\n delete provider.activeAuthAccount;\n return previousAuthRef !== provider.authRef\n || previousDefaultAuthRef !== provider.defaultAuthRef\n || previousDefaultModelsCache !== provider.defaultModelsCache\n || previousAccount !== provider.activeAuthAccount;\n}\n\n/**\n * Upgrade OAuth selectors written before schema v5. In v3/v4, `authRef` is\n * defined as the provider default, so it is safe to park. The top-level model\n * cache is not proof of account ownership, however: only a v4 slot cache is.\n * Never copy an ambiguous top cache into the selected slot. Project the slot's\n * proven cache when one exists, otherwise clear the top cache and fail closed\n * until that account is refreshed.\n *\n * A selector whose slot is missing is deliberately left untouched. There is\n * no selected credential to materialize, and guessing the default would turn\n * a broken selection into a silent identity fallback.\n */\nexport function migrateActiveOAuthAccountStorage(registry: ProviderRegistry): boolean {\n let changed = false;\n for (const provider of registry.providers) {\n const name = provider.activeAuthAccount?.trim();\n if (provider.authType !== 'oauth' || !name || provider.defaultAuthRef !== undefined) continue;\n const selected = getOAuthAccountSlot(provider, name);\n if (!selected) continue;\n\n provider.defaultAuthRef = provider.authRef;\n provider.authRef = selected.authRef;\n // Account-owned caches did not exist until v4. A stray cache in older\n // bytes has no schema-backed ownership provenance and must not be paired\n // with the selected credential.\n if (registry.schemaVersion >= 4 && selected.modelsCache) {\n provider.modelsCache = selected.modelsCache;\n provider.refreshedAt = selected.modelsCache.fetchedAt;\n } else {\n delete provider.modelsCache;\n delete provider.refreshedAt;\n }\n changed = true;\n }\n return changed;\n}\n","import {\n REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT,\n REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES,\n type ProviderRegistry,\n} from './types.js';\nimport { migrateActiveOAuthAccountStorage } from './oauth-account-storage.js';\n\n// Rename {id:'openai', authType:'oauth'} → {id:'openai-oauth'} so it can coexist\n// with the API-key 'openai' provider. Preserves the original authRef so the\n// keyring credential isn't orphaned.\nexport function migrateOAuthOpenAiProvider(registry: ProviderRegistry): boolean {\n if (registry.providers.some(p => p.id === 'openai-oauth')) return false;\n\n const idx = registry.providers.findIndex(\n p => p.id === 'openai' && p.authType === 'oauth',\n );\n if (idx < 0) return false;\n\n const existing = registry.providers[idx]!;\n registry.providers[idx] = {\n ...existing,\n id: 'openai-oauth',\n templateId: existing.templateId || 'openai',\n name: existing.name === 'OpenAI' ? 'OpenAI (ChatGPT)' : existing.name,\n };\n return true;\n}\n\nexport interface RegistryMigrationResult {\n changed: boolean;\n /**\n * The selected credential/cache identity was projected into downgrade-visible\n * top-level fields. Returning those bytes before they are durable would put\n * the current process and an older process on different identities.\n */\n materializedActiveAccount: boolean;\n}\n\n/** Apply every supported in-memory registry migration. */\nexport function migrateRegistry(registry: ProviderRegistry): RegistryMigrationResult {\n const renamed = migrateOAuthOpenAiProvider(registry);\n // Schema v5 is authoritative. Never infer a missing parked default there:\n // its top-level authRef is already the selected slot, not the value to park.\n const materialized = registry.schemaVersion >= REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT\n && registry.schemaVersion <= REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES\n ? migrateActiveOAuthAccountStorage(registry)\n : false;\n return {\n changed: renamed || materialized,\n materializedActiveAccount: materialized,\n };\n}\n","// src/registry/validate.ts\n\n/** Stable provider slug: lowercase alphanumeric + internal hyphens. */\nexport const PROVIDER_ID_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\n\nexport function isValidProviderId(id: string): boolean {\n return PROVIDER_ID_PATTERN.test(id);\n}\n\nexport function slugifyProviderId(displayName: string): string {\n const base = displayName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n if (!base) return 'custom-provider';\n if (isValidProviderId(base)) return base;\n const trimmed = base.replace(/^-+|-+$/g, '');\n return isValidProviderId(trimmed) ? trimmed : `custom-${trimmed.slice(0, 40)}`;\n}\n\nexport function customProviderId(displayName: string): string {\n const slug = slugifyProviderId(displayName);\n return slug.startsWith('custom-') ? slug : `custom-${slug}`;\n}\n","import type { UserPreferences } from './types.js';\nimport { randomUUID } from 'node:crypto';\nimport { readFileSync, renameSync, unlinkSync } from 'node:fs';\nimport { getConfigPath } from './paths.js';\nimport { syncParentDirectory, writeSecureFile } from './registry/io.js';\nimport {\n assertRegistryWriteOwnership,\n withRegistryWriteLock,\n withRegistryWriteLockSync,\n} from './registry/lock.js';\n\nfunction readJsonFile(path: string): UserPreferences | null {\n try {\n const parsed = JSON.parse(readFileSync(path, 'utf8'));\n return parsed && typeof parsed === 'object' ? parsed as UserPreferences : null;\n } catch {\n return null;\n }\n}\n\nfunction readConfig(): UserPreferences {\n return readJsonFile(getConfigPath()) ?? {};\n}\n\nfunction writeConfig(config: UserPreferences): void {\n const configPath = getConfigPath();\n assertRegistryWriteOwnership(configPath);\n const payload = `${JSON.stringify(config, null, 2)}\\n`;\n const tmp = `${configPath}.${process.pid}.${randomUUID()}.tmp`;\n try {\n writeSecureFile(tmp, payload);\n assertRegistryWriteOwnership(configPath);\n renameSync(tmp, configPath);\n syncParentDirectory(configPath);\n } finally {\n try {\n unlinkSync(tmp);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n }\n}\n\nfunction updateConfig<T>(mutate: (config: UserPreferences) => T): T {\n const configPath = getConfigPath();\n return withRegistryWriteLockSync(() => {\n const config = readJsonFile(configPath) ?? {};\n const result = mutate(config);\n writeConfig(config);\n return result;\n }, { lockPath: `${configPath}.lock` });\n}\n\ninterface AsyncConfigUpdate<T> {\n result: T;\n write: boolean;\n}\n\nasync function updateConfigAsync<T>(\n mutate: (\n config: UserPreferences,\n ) => Promise<AsyncConfigUpdate<T>> | AsyncConfigUpdate<T>,\n): Promise<T> {\n const configPath = getConfigPath();\n return withRegistryWriteLock(async () => {\n const config = readJsonFile(configPath) ?? {};\n const update = await mutate(config);\n if (update.write) writeConfig(config);\n return update.result;\n }, { lockPath: `${configPath}.lock` });\n}\n\nexport function loadPreferences(): UserPreferences {\n const config = readConfig();\n return {\n lastModel: config.lastModel,\n lastProvider: config.lastProvider,\n recentModelsByProvider: config.recentModelsByProvider,\n favoriteModels: config.favoriteModels,\n modelAliases: config.modelAliases,\n modelContextModes: config.modelContextModes,\n claudeBridgeMode: config.claudeBridgeMode,\n serverBridgeMode: config.serverBridgeMode,\n appPathOverrides: config.appPathOverrides,\n localPatchesEnabled: config.localPatchesEnabled,\n recentLaunchFolders: config.recentLaunchFolders,\n server: config.server,\n };\n}\n\nexport function savePreferences(prefs: Partial<Pick<UserPreferences, 'lastModel' | 'lastProvider' | 'recentModelsByProvider' | 'favoriteModels' | 'modelAliases' | 'modelContextModes' | 'claudeBridgeMode' | 'serverBridgeMode' | 'appPathOverrides' | 'localPatchesEnabled' | 'recentLaunchFolders'>>): void {\n updateConfig(config => {\n if (prefs.lastModel !== undefined) config.lastModel = prefs.lastModel;\n if (prefs.lastProvider !== undefined) config.lastProvider = prefs.lastProvider;\n if (prefs.recentModelsByProvider !== undefined) config.recentModelsByProvider = prefs.recentModelsByProvider;\n if (prefs.favoriteModels !== undefined) config.favoriteModels = prefs.favoriteModels;\n if (prefs.modelAliases !== undefined) config.modelAliases = prefs.modelAliases;\n if (prefs.modelContextModes !== undefined) config.modelContextModes = prefs.modelContextModes;\n if (prefs.claudeBridgeMode !== undefined) config.claudeBridgeMode = prefs.claudeBridgeMode;\n if (prefs.serverBridgeMode !== undefined) config.serverBridgeMode = prefs.serverBridgeMode;\n if (prefs.appPathOverrides !== undefined) config.appPathOverrides = prefs.appPathOverrides;\n if (prefs.localPatchesEnabled !== undefined) config.localPatchesEnabled = prefs.localPatchesEnabled;\n if (prefs.recentLaunchFolders !== undefined) config.recentLaunchFolders = prefs.recentLaunchFolders;\n });\n}\n\nexport function getAppPathOverride(appId: string): string | undefined {\n const value = loadPreferences().appPathOverrides?.[appId];\n return typeof value === 'string' && value.trim() ? value : undefined;\n}\n\nexport function setAppPathOverride(appId: string, path: string | null): Record<string, string> {\n return updateConfig(config => {\n const next = { ...(config.appPathOverrides ?? {}) };\n const trimmed = path?.trim() ?? '';\n if (trimmed) next[appId] = trimmed;\n else delete next[appId];\n config.appPathOverrides = next;\n if (Object.keys(next).length === 0) delete config.appPathOverrides;\n return next;\n });\n}\n\n/**\n * Resolve the bridge mode for a command. An explicit flag applies to that run only —\n * it is persisted as the command's default ONLY when the caller opts in (--save-mode).\n * With no flag, the saved per-command default applies; with no saved default, proxy.\n */\nexport function resolveBridgeMode(\n command: 'claude' | 'server',\n explicit: import('./types.js').BridgeMode | undefined,\n opts: { persist?: boolean } = {},\n): import('./types.js').BridgeMode {\n const key = command === 'claude' ? 'claudeBridgeMode' : 'serverBridgeMode';\n if (explicit) {\n if (opts.persist === true) savePreferences({ [key]: explicit });\n return explicit;\n }\n return loadPreferences()[key] ?? 'proxy';\n}\n\nconst MAX_RECENT_MODELS = 3;\nconst MAX_RECENT_LAUNCH_FOLDERS = 6;\n\nexport function recordLaunchFolder(folder: string): string[] {\n const trimmed = folder.trim();\n if (!trimmed) return loadPreferences().recentLaunchFolders ?? [];\n return updateConfig(config => {\n const prev = config.recentLaunchFolders ?? [];\n const next = [trimmed, ...prev.filter(path => path !== trimmed)].slice(0, MAX_RECENT_LAUNCH_FOLDERS);\n config.recentLaunchFolders = next;\n return next;\n });\n}\n\nexport function recordLaunchSelection(\n _agent: 'claude',\n providerId: string,\n modelId: string,\n prefs: UserPreferences,\n): void {\n const prevRecent = prefs.recentModelsByProvider?.[providerId] ?? [];\n const updatedRecent = [modelId, ...prevRecent.filter(id => id !== modelId)].slice(0, MAX_RECENT_MODELS);\n savePreferences({\n lastProvider: providerId,\n lastModel: modelId,\n recentModelsByProvider: { ...prefs.recentModelsByProvider, [providerId]: updatedRecent },\n });\n}\n\nconst SERVER_PASSWORD_SERVICE = 'clodex-server-password';\nconst SERVER_PASSWORD_ACCOUNT = 'server-password';\n\nasync function getServerPasswordKeyring(): Promise<any | null> {\n try {\n const { Entry } = await import('@napi-rs/keyring');\n return new Entry(SERVER_PASSWORD_SERVICE, SERVER_PASSWORD_ACCOUNT);\n } catch {\n return null;\n }\n}\n\nexport async function getSavedServerPassword(): Promise<string | null> {\n const keyring = await getServerPasswordKeyring();\n if (!keyring) return readConfig().server?.savedPassword ?? null;\n\n const savedPassword = await updateConfigAsync(async config => {\n const server = config.server;\n const password = server?.savedPassword;\n if (!password) return { result: null, write: false };\n try {\n await keyring.setPassword(password);\n delete server.savedPassword;\n if (Object.keys(server).length === 0) delete config.server;\n return { result: password, write: true };\n } catch {\n // Fallback: keep in config.json if keyring fails\n return { result: password, write: false };\n }\n });\n if (savedPassword) return savedPassword;\n\n try {\n return await keyring.getPassword();\n } catch {\n return null;\n }\n}\n\nexport async function setSavedServerPassword(password: string): Promise<void> {\n const keyring = await getServerPasswordKeyring();\n if (keyring) {\n try {\n await keyring.setPassword(password);\n return;\n } catch {\n // Fallback\n }\n }\n await updateConfigAsync(config => {\n config.server = {\n ...(config.server ?? {}),\n savedPassword: password,\n };\n return { result: undefined, write: true };\n });\n}\n\nexport async function clearSavedServerPassword(): Promise<void> {\n const keyring = await getServerPasswordKeyring();\n if (keyring) {\n try {\n await keyring.deletePassword();\n } catch {\n // Ignore\n }\n }\n await updateConfigAsync(config => {\n if (!config.server) return { result: undefined, write: false };\n delete config.server.savedPassword;\n if (Object.keys(config.server).length === 0) delete config.server;\n return { result: undefined, write: true };\n });\n}\n\nexport function getServerExposedProviders(): string[] | null {\n const list = readConfig().server?.exposedProviders;\n return list && list.length > 0 ? list : null;\n}\n\nexport function setServerExposedProviders(providerIds: string[]): void {\n updateConfig(config => {\n config.server = {\n ...(config.server ?? {}),\n exposedProviders: providerIds,\n };\n });\n}\n\nexport function getServerMaskGatewayIds(): boolean {\n return readConfig().server?.maskGatewayIds ?? true;\n}\n\nexport function setServerMaskGatewayIds(mask: boolean): void {\n updateConfig(config => {\n config.server = {\n ...(config.server ?? {}),\n maskGatewayIds: mask,\n };\n });\n}\n\nexport function getServerFavoritesOnly(): boolean {\n return readConfig().server?.favoritesOnly ?? false;\n}\n\nexport function setServerFavoritesOnly(favoritesOnly: boolean): void {\n updateConfig(config => {\n config.server = {\n ...(config.server ?? {}),\n favoritesOnly,\n };\n });\n}\n\nexport function getServerListenMode(): 'local' | 'network' {\n return readConfig().server?.listenMode === 'network' ? 'network' : 'local';\n}\n\nexport function setServerListenMode(listenMode: 'local' | 'network'): void {\n updateConfig(config => {\n config.server = {\n ...(config.server ?? {}),\n listenMode,\n };\n });\n}\n","// src/claude-binary.ts\n//\n// Claude Code binary discovery and version probing, kept OUT of launch.ts so the\n// `clodex-claude` wrapper can import discovery without pulling in launchClaude\n// and everything the launch path needs. The wrapper runs for every spawned agent\n// process, so its import graph is an invariant (see CLAUDE.md), and tsup places\n// anything both entry points touch in the shared chunk they both load.\nimport { execFileSync, execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { getAppPathOverride } from './config.js';\nimport { findBinaryOnPath } from './binary-lookup.js';\n\nconst isWindows = process.platform === 'win32';\n\nconst FALLBACK_PATHS = isWindows\n ? [\n join(process.env['APPDATA'] ?? homedir(), 'npm', 'claude.cmd'),\n join(process.env['APPDATA'] ?? homedir(), 'npm', 'claude'),\n join(homedir(), 'AppData', 'Roaming', 'npm', 'claude.cmd'),\n ]\n : [\n join(homedir(), '.local', 'bin', 'claude'),\n join(homedir(), '.npm', 'bin', 'claude'),\n '/usr/local/bin/claude',\n '/opt/homebrew/bin/claude',\n ];\n\nexport function findClaudeBinary(): string | null {\n const environmentOverride = process.env['CLODEX_CLAUDE_PATH'];\n if (environmentOverride?.trim()) {\n return existsSync(environmentOverride) ? environmentOverride : null;\n }\n\n const override = getAppPathOverride('claude');\n if (override) return existsSync(override) ? override : null;\n\n return findBinaryOnPath('claude', FALLBACK_PATHS);\n}\n\n/** Version reported when the installed claude cannot be probed. */\nconst FALLBACK_CLAUDE_VERSION = '2.1.183';\n\nconst VERSION_PROBE_TIMEOUT_MS = 15_000;\n\n/**\n * Probe `--version` of ONE SPECIFIC claude binary, returning null when it cannot\n * be executed or prints nothing version-shaped.\n *\n * Callers that key destructive state on the answer — the patcher names its\n * pristine backups after this version and restores them over the live install —\n * MUST use this and fail loudly on null. A guessed version tags a backup with\n * bytes it does not contain, and restoring it downgrades the user's Claude Code.\n */\nexport function getClaudeVersionForBinary(binaryPath: string): string | null {\n try {\n // POSIX: exec the file directly so a path containing spaces still works.\n // Windows: `claude` is often a .cmd shim, which needs a shell — keep the\n // quoted shell invocation there.\n const result = isWindows\n ? execSync(`\"${binaryPath}\" --version`, {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: VERSION_PROBE_TIMEOUT_MS,\n })\n : execFileSync(binaryPath, ['--version'], {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: VERSION_PROBE_TIMEOUT_MS,\n });\n return result.match(/(\\d+\\.\\d+\\.\\d+)/)?.[1] ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Version of the claude found on PATH (or via the configured overrides), with a\n * known-good fallback. This is a best-effort string for request metadata — it is\n * NOT the version of any particular file, because `findClaudeBinary()` can\n * return a wrapper shim that differs from the real installation.\n */\nexport function getInstalledClaudeVersion(): string {\n const claudePath = findClaudeBinary();\n if (!claudePath) return FALLBACK_CLAUDE_VERSION;\n return getClaudeVersionForBinary(claudePath) ?? FALLBACK_CLAUDE_VERSION;\n}\n","import { execFileSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\n\nexport interface FindBinaryOnPathOptions {\n verifyWhichResult?: boolean;\n isWindows?: boolean;\n exists?: (path: string) => boolean;\n runWhich?: (name: string, isWindows: boolean) => string;\n}\n\nexport function findBinaryOnPath(\n name: string,\n fallbackPaths: string[],\n options: FindBinaryOnPathOptions = {},\n): string | null {\n const isWindows = options.isWindows ?? process.platform === 'win32';\n const exists = options.exists ?? existsSync;\n // argv form, never a shell string — the binary name must not be shell-interpretable\n // (defense-in-depth originally added in d887984, must survive refactors).\n const runWhich = options.runWhich ?? ((binary, win) =>\n execFileSync(win ? 'where.exe' : 'which', [binary], {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }));\n\n try {\n const lines = runWhich(name, isWindows)\n .trim()\n .split('\\n')\n .map(line => line.trim())\n .filter(Boolean);\n const path = (isWindows ? lines.find(line => line.toLowerCase().endsWith('.cmd')) : null)\n ?? lines[0];\n if (path && (!options.verifyWhichResult || exists(path))) return path;\n } catch {\n // Fall through to fallback paths.\n }\n\n for (const path of fallbackPaths) {\n if (exists(path)) return path;\n }\n return null;\n}\n","import { connect, type AddressInfo, type Server } from 'node:net';\nimport { setTimeout as delay } from 'node:timers/promises';\n\nconst LISTENER_READY_TIMEOUT_MS = 1_000;\nconst LISTENER_READY_RETRY_MS = 5;\nconst TCP_PROBE_TIMEOUT_MS = 50;\n\nfunction connectHost(address: string): string {\n if (address === '0.0.0.0') return '127.0.0.1';\n if (address === '::') return '::1';\n return address;\n}\n\n/** Return a reachable host formatted for use in an HTTP URL. */\nexport function tcpListenerUrlHost(address: string): string {\n const host = connectHost(address);\n return host.includes(':') ? `[${host}]` : host;\n}\n\ntype TcpListenerProbeResult = 'ready' | 'timeout' | 'unreachable';\n\nfunction probeTcpListener(\n host: string,\n port: number,\n timeoutMs: number,\n): Promise<TcpListenerProbeResult> {\n return new Promise(resolve => {\n const socket = connect({ host, port });\n let settled = false;\n const finish = (result: TcpListenerProbeResult) => {\n if (settled) return;\n settled = true;\n socket.destroy();\n resolve(result);\n };\n socket.once('connect', () => finish('ready'));\n socket.once('error', error => {\n finish(\n (error as NodeJS.ErrnoException).code === 'ETIMEDOUT'\n ? 'timeout'\n : 'unreachable',\n );\n });\n socket.setTimeout(timeoutMs, () => finish('timeout'));\n });\n}\n\ninterface TcpListenerWaitOptions {\n now?: () => number;\n probe?: (\n host: string,\n port: number,\n timeoutMs: number,\n ) => Promise<TcpListenerProbeResult>;\n retryFailure?: (result: Exclude<TcpListenerProbeResult, 'ready'>) => boolean;\n delay?: (ms: number) => Promise<void>;\n}\n\n/**\n * Probe every candidate once per round and return the first reachable\n * candidate in caller-provided priority order. All retry rounds share one\n * overall deadline.\n */\nexport async function waitForTcpListenerCandidate<T extends { port: number }>(\n host: string,\n candidates: readonly T[],\n timeoutMs = LISTENER_READY_TIMEOUT_MS,\n options: TcpListenerWaitOptions = {},\n): Promise<T | null> {\n if (candidates.length === 0) return null;\n\n const now = options.now ?? Date.now;\n const probe = options.probe ?? probeTcpListener;\n const retryFailure = options.retryFailure ?? (() => true);\n const wait = options.delay ?? (ms => delay(ms));\n const deadline = now() + timeoutMs;\n let pendingCandidates = [...candidates];\n\n do {\n const remaining = Math.max(1, deadline - now());\n const results = await Promise.all(\n pendingCandidates.map(candidate => probe(\n host,\n candidate.port,\n Math.min(remaining, TCP_PROBE_TIMEOUT_MS),\n )),\n );\n const readyIndex = results.findIndex(result => result === 'ready');\n if (readyIndex >= 0) return pendingCandidates[readyIndex] ?? null;\n\n pendingCandidates = pendingCandidates.filter((_candidate, index) => {\n const result = results[index];\n return result !== undefined && result !== 'ready' && retryFailure(result);\n });\n if (pendingCandidates.length === 0) return null;\n\n const retryDelay = Math.min(LISTENER_READY_RETRY_MS, deadline - now());\n if (retryDelay <= 0) return null;\n await wait(retryDelay);\n } while (now() < deadline);\n\n return null;\n}\n\n/** Retry a TCP probe until the listener answers or the deadline expires. */\nexport async function waitForTcpListener(\n host: string,\n port: number,\n timeoutMs = LISTENER_READY_TIMEOUT_MS,\n options: TcpListenerWaitOptions = {},\n): Promise<boolean> {\n return (await waitForTcpListenerCandidate(host, [{ port }], timeoutMs, options)) !== null;\n}\n\nasync function closeAfterReadinessFailure(server: Server): Promise<void> {\n if (!server.listening) return;\n await new Promise<void>(resolve => server.close(() => resolve()));\n}\n\n/** Bind a TCP server and wait until the bound socket accepts connections. */\nexport async function listenTcpServer(\n server: Server,\n port: number,\n host: string,\n): Promise<AddressInfo> {\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => server.off('error', onError);\n const onError = (error: Error) => {\n cleanup();\n reject(error);\n };\n server.once('error', onError);\n try {\n server.listen(port, host, () => {\n cleanup();\n resolve();\n });\n } catch (error) {\n cleanup();\n reject(error);\n }\n });\n\n const address = server.address();\n if (!address || typeof address === 'string') {\n await closeAfterReadinessFailure(server);\n throw new Error('TCP server did not bind to a network address');\n }\n\n const probeHost = connectHost(address.address);\n if (await waitForTcpListener(probeHost, address.port)) return address;\n\n await closeAfterReadinessFailure(server);\n throw new Error(\n `TCP listener did not become reachable within ${LISTENER_READY_TIMEOUT_MS}ms: `\n + `${probeHost}:${address.port}`,\n );\n}\n","// src/server-runtime.ts\n//\n// Runtime-state advertisement for the standalone `clodex server` command.\n// Each registering server ADDS its own record (keyed by pid) to\n// ~/.clodex/server-runtime.json on startup and removes ONLY its own record on\n// graceful shutdown, so other processes (notably the `clodex-claude` wrapper\n// bin) can discover every running server's mode, port, and CA path without any\n// hardcoding. The file holds an ARRAY of records; the legacy single-object\n// shape (pre multi-server) is tolerated on read as a one-element list. Stale\n// detection is the READER's job: a crashed server leaves its record behind, so\n// readers must validate pid liveness before trusting it. Writers additionally\n// prune dead-pid records while they hold the write lock.\n//\n// Concurrency: read-modify-write cycles are serialized by a short-lived pid\n// lock (~/.clodex/server-runtime.lock — same pattern as the patcher's\n// patch.lock: O_EXCL create, pid + staleness, ESRCH liveness) and the file is\n// replaced via write-temp-then-rename so a reader never sees a torn write. A\n// crashed lock holder cannot deadlock registration: the lock goes stale after\n// 10 seconds or when its pid dies, and after a brief bounded wait a writer\n// proceeds lockless (best-effort — same exposure as the old single-slot write).\n//\n// NOTE: only the standalone `clodex server` command writes this file. The\n// per-session MITM proxy spawned by `clodex claude --proxy` is private to that\n// session and must NOT advertise itself here. `clodex server --no-discovery`\n// (or CLODEX_NO_DISCOVERY=1) also opts a server out of registration entirely.\n\nimport {\n closeSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n rmSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { getAppHome } from './paths.js';\n\nexport interface ServerRuntimeState {\n mode: 'endpoint' | 'proxy';\n port: number;\n pid: number;\n /** Proxy mode only: absolute path to the CA bundle a client must trust. */\n caPath?: string;\n startedAt: string;\n}\n\ninterface HomeEnv {\n HOME?: string;\n CLODEX_HOME?: string;\n USERPROFILE?: string;\n}\n\nexport function getServerRuntimePath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'server-runtime.json');\n}\n\nexport function getServerRuntimeLockPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'server-runtime.lock');\n}\n\n/** `--no-discovery` flag, with CLODEX_NO_DISCOVERY=1 as the env fallback. */\nexport function isDiscoveryDisabled(\n flag: boolean | undefined,\n env: { CLODEX_NO_DISCOVERY?: string } = process.env,\n): boolean {\n if (flag !== undefined) return flag;\n const raw = env.CLODEX_NO_DISCOVERY?.trim().toLowerCase();\n return raw === '1' || raw === 'true';\n}\n\nfunction isPort(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 1 && value <= 65535;\n}\n\n/** Validate one runtime record. Returns null for anything malformed. */\nexport function parseServerRuntimeRecord(value: unknown): ServerRuntimeState | null {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return null;\n const record = value as Record<string, unknown>;\n\n const mode = record['mode'];\n if (mode !== 'endpoint' && mode !== 'proxy') return null;\n if (!isPort(record['port'])) return null;\n const pid = record['pid'];\n if (typeof pid !== 'number' || !Number.isInteger(pid) || pid <= 0) return null;\n const startedAt = typeof record['startedAt'] === 'string' ? record['startedAt'] : '';\n\n const caPath = record['caPath'];\n if (mode === 'proxy') {\n // A proxy-mode server without a CA path is unusable to clients — treat as invalid.\n if (typeof caPath !== 'string' || !caPath.trim()) return null;\n return { mode, port: record['port'], pid, caPath, startedAt };\n }\n return { mode, port: record['port'], pid, startedAt };\n}\n\n/**\n * Parse a raw server-runtime.json payload into a list of records. Tolerates\n * BOTH shapes: the current array of records and the legacy single object\n * (wrapped as a one-element list). Malformed input or records are skipped —\n * never throws.\n */\nexport function parseServerRuntimeStates(raw: string): ServerRuntimeState[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return [];\n }\n const items = Array.isArray(parsed) ? parsed : [parsed];\n const states: ServerRuntimeState[] = [];\n for (const item of items) {\n const state = parseServerRuntimeRecord(item);\n if (state) states.push(state);\n }\n return states;\n}\n\n/** kill(pid, 0) liveness probe: EPERM still means the process exists. */\nexport function isPidAlive(\n pid: number,\n kill: (pid: number, signal: number) => unknown = process.kill.bind(process),\n): boolean {\n try {\n kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException)?.code === 'EPERM';\n }\n}\n\n// ── Write lock (pid + staleness, patcher pattern) ───────────────────────────\n\nconst RUNTIME_LOCK_STALE_MS = 10_000;\nconst RUNTIME_LOCK_WAIT_MS = 500;\nconst RUNTIME_LOCK_RETRY_MS = 25;\n\ninterface RuntimeLockContent {\n pid: number;\n startedAt: number;\n}\n\nfunction tryAcquireRuntimeLock(\n lockPath: string,\n opts: { now?: number; isAlive?: (pid: number) => boolean } = {},\n): (() => void) | null {\n const now = opts.now ?? Date.now();\n const alive = opts.isAlive ?? isPidAlive;\n mkdirSync(dirname(lockPath), { recursive: true, mode: 0o700 });\n\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n const fd = openSync(lockPath, 'wx');\n const content: RuntimeLockContent = { pid: process.pid, startedAt: now };\n writeFileSync(fd, JSON.stringify(content));\n closeSync(fd);\n return () => {\n try {\n unlinkSync(lockPath);\n } catch {\n // already gone\n }\n };\n } catch {\n // Lock exists — check staleness.\n let stale = false;\n try {\n const existing = JSON.parse(readFileSync(lockPath, 'utf8')) as RuntimeLockContent;\n stale = !existing.pid\n || !alive(existing.pid)\n || (typeof existing.startedAt === 'number' && now - existing.startedAt > RUNTIME_LOCK_STALE_MS);\n } catch {\n stale = true; // unreadable lock file → stale\n }\n if (!stale) return null;\n try {\n unlinkSync(lockPath);\n } catch {\n // raced with the owner's cleanup — retry loop handles it\n }\n }\n }\n return null;\n}\n\nfunction sleepSync(ms: number): void {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\n/**\n * Run a read-modify-write mutation under the runtime lock. The lock is only\n * ever held for a few milliseconds, so after a short bounded wait the mutation\n * proceeds WITHOUT the lock rather than dropping a registration — the atomic\n * rename still prevents torn files; the worst case is a lost concurrent\n * update, which is no worse than the old single-slot behavior.\n */\nfunction withRuntimeWriteLock(env: HomeEnv, mutate: () => void): void {\n const lockPath = getServerRuntimeLockPath(env);\n let release: (() => void) | null = null;\n const deadline = Date.now() + RUNTIME_LOCK_WAIT_MS;\n for (;;) {\n release = tryAcquireRuntimeLock(lockPath);\n if (release || Date.now() >= deadline) break;\n sleepSync(RUNTIME_LOCK_RETRY_MS);\n }\n try {\n mutate();\n } finally {\n release?.();\n }\n}\n\nfunction readAllRecords(env: HomeEnv): ServerRuntimeState[] {\n let raw: string;\n try {\n raw = readFileSync(getServerRuntimePath(env), 'utf8');\n } catch {\n return [];\n }\n return parseServerRuntimeStates(raw);\n}\n\n/** Atomic replace: write a temp file in the same directory, then rename over. */\nfunction atomicWriteRecords(path: string, records: ServerRuntimeState[]): void {\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n const tmpPath = `${path}.${process.pid}.tmp`;\n writeFileSync(tmpPath, `${JSON.stringify(records, null, 2)}\\n`, { encoding: 'utf8', mode: 0o600 });\n renameSync(tmpPath, path);\n}\n\nexport interface RuntimeMutateOptions {\n isAlive?: (pid: number) => boolean;\n}\n\n/**\n * Add or update this server's own record (keyed by pid), pruning records whose\n * pids are dead. Best-effort — a state-file failure must never take the server\n * down.\n */\nexport function registerServerRuntimeState(\n state: ServerRuntimeState,\n env: HomeEnv = process.env,\n options: RuntimeMutateOptions = {},\n): void {\n const alive = options.isAlive ?? isPidAlive;\n try {\n withRuntimeWriteLock(env, () => {\n const records = readAllRecords(env).filter(\n record => record.pid !== state.pid && alive(record.pid),\n );\n records.push(state);\n atomicWriteRecords(getServerRuntimePath(env), records);\n });\n } catch {\n // Discovery is optional; the server itself keeps running.\n }\n}\n\n/**\n * Remove ONLY this server's own record (by pid) on graceful shutdown, pruning\n * dead-pid records along the way. Missing file/record is fine. When no live\n * records remain the file is removed entirely.\n */\nexport function unregisterServerRuntimeState(\n pid: number = process.pid,\n env: HomeEnv = process.env,\n options: RuntimeMutateOptions = {},\n): void {\n const alive = options.isAlive ?? isPidAlive;\n try {\n withRuntimeWriteLock(env, () => {\n const records = readAllRecords(env).filter(\n record => record.pid !== pid && alive(record.pid),\n );\n if (records.length === 0) {\n rmSync(getServerRuntimePath(env), { force: true });\n } else {\n atomicWriteRecords(getServerRuntimePath(env), records);\n }\n });\n } catch {\n // Stale records are handled by readers via pid liveness.\n }\n}\n\nexport interface ReadServerRuntimeOptions {\n isAlive?: (pid: number) => boolean;\n}\n\n/**\n * Read every advertised server record whose process is still alive. Missing or\n * malformed files yield an empty list. Read-only: stale records are ignored\n * here and physically pruned on the next registration/unregistration.\n */\nexport function readLiveServerRuntimeStates(\n env: HomeEnv = process.env,\n options: ReadServerRuntimeOptions = {},\n): ServerRuntimeState[] {\n const alive = options.isAlive ?? isPidAlive;\n return readAllRecords(env).filter(state => alive(state.pid));\n}\n\n/**\n * Wrapper selection policy: order candidate servers by preference —\n * 1. proxy mode before endpoint mode (bridging through the MITM proxy keeps\n * Claude Code's own Anthropic auth, the recommended setup);\n * 2. within a mode, newest startedAt first.\n * If only an endpoint server is live it is used; with no live server the\n * wrapper launches claude untouched (both handled by the caller).\n */\nexport function orderWrapperServerCandidates(records: ServerRuntimeState[]): ServerRuntimeState[] {\n return [...records].sort((a, b) => {\n if (a.mode !== b.mode) return a.mode === 'proxy' ? -1 : 1;\n return (Date.parse(b.startedAt) || 0) - (Date.parse(a.startedAt) || 0);\n });\n}\n\n/**\n * Read the single preferred live server (selection policy above), or null when\n * none is advertised/alive.\n */\nexport function readLiveServerRuntimeState(\n env: HomeEnv = process.env,\n options: ReadServerRuntimeOptions = {},\n): ServerRuntimeState | null {\n return orderWrapperServerCandidates(readLiveServerRuntimeStates(env, options))[0] ?? null;\n}\n","export const PROXY_ENV_VARS = [\n 'HTTPS_PROXY',\n 'HTTP_PROXY',\n 'https_proxy',\n 'http_proxy',\n] as const;\n\nexport const CHILD_NETWORK_ENV_VARS = [\n ...PROXY_ENV_VARS,\n 'NO_PROXY',\n 'no_proxy',\n 'NODE_EXTRA_CA_CERTS',\n] as const;\n\nexport const NETWORK_ENV_CONTRACT_VAR = 'CLAUDE_CODE_CLODEX_NETWORK_ENV';\n\ntype ChildNetworkEnvVar = typeof CHILD_NETWORK_ENV_VARS[number];\ntype NetworkEnvValue = string | null;\n\ninterface NetworkEnvContract {\n version: 1;\n original: Partial<Record<ChildNetworkEnvVar, NetworkEnvValue>>;\n injected: Partial<Record<ChildNetworkEnvVar, NetworkEnvValue>>;\n}\n\nconst childNetworkEnvVarSet = new Set<string>(CHILD_NETWORK_ENV_VARS);\n\nfunction networkEnvValue(env: NodeJS.ProcessEnv, name: ChildNetworkEnvVar): NetworkEnvValue {\n return typeof env[name] === 'string' ? env[name]! : null;\n}\n\nfunction isNetworkValueRecord(value: unknown): value is Record<string, NetworkEnvValue> {\n return Boolean(value && typeof value === 'object' && !Array.isArray(value)\n && Object.entries(value).every(([key, entry]) =>\n childNetworkEnvVarSet.has(key) && (typeof entry === 'string' || entry === null)));\n}\n\nfunction parseNetworkEnvContract(value: string | undefined): NetworkEnvContract | undefined {\n if (value === undefined) return undefined;\n try {\n const parsed: unknown = JSON.parse(value);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return undefined;\n const candidate = parsed as Partial<NetworkEnvContract>;\n const original = candidate.original;\n const injected = candidate.injected;\n if (candidate.version !== 1\n || !isNetworkValueRecord(original)\n || !isNetworkValueRecord(injected)) {\n return undefined;\n }\n if (!Object.keys(original).every(key => key in injected)\n || !Object.keys(injected).every(key => key in original)) {\n return undefined;\n }\n return { version: 1, original, injected };\n } catch {\n return undefined;\n }\n}\n\nfunction setNetworkEnvValue(\n env: NodeJS.ProcessEnv,\n name: ChildNetworkEnvVar,\n value: NetworkEnvValue,\n): void {\n if (value === null) delete env[name];\n else env[name] = value;\n}\n\n/**\n * Recover the external network environment only where the inherited values\n * still equal a prior Clodex injection. Values changed by settings or another\n * wrapper layer remain authoritative.\n */\nexport function networkEnvBaseline(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...baseEnv };\n const contract = parseNetworkEnvContract(baseEnv[NETWORK_ENV_CONTRACT_VAR]);\n delete env[NETWORK_ENV_CONTRACT_VAR];\n if (!contract) return env;\n\n for (const name of CHILD_NETWORK_ENV_VARS) {\n if (!(name in contract.original) || !(name in contract.injected)) continue;\n if (networkEnvValue(baseEnv, name) !== contract.injected[name]) continue;\n setNetworkEnvValue(env, name, contract.original[name] ?? null);\n }\n return env;\n}\n\n/**\n * Attach a compare-before-revert contract for the network values changed\n * between an external baseline and the child environment Clodex will launch.\n */\nexport function recordNetworkEnvMutation(\n baseline: NodeJS.ProcessEnv,\n injectedEnv: NodeJS.ProcessEnv,\n): void {\n const original: NetworkEnvContract['original'] = {};\n const injected: NetworkEnvContract['injected'] = {};\n for (const name of CHILD_NETWORK_ENV_VARS) {\n const before = networkEnvValue(baseline, name);\n const after = networkEnvValue(injectedEnv, name);\n if (before === after) continue;\n original[name] = before;\n injected[name] = after;\n }\n if (Object.keys(original).length === 0) {\n delete injectedEnv[NETWORK_ENV_CONTRACT_VAR];\n return;\n }\n injectedEnv[NETWORK_ENV_CONTRACT_VAR] = JSON.stringify({\n version: 1,\n original,\n injected,\n } satisfies NetworkEnvContract);\n}\n","// src/wrapper-env.ts\n//\n// Pure env computation for the `clodex-claude` wrapper bin. Given the process\n// env and a live `clodex server` runtime state (or null), returns the env to\n// launch the Claude Code binary with. Kept dependency-free so the wrapper\n// stays tiny and fast — it runs for every Claude-Code-spawned agent process.\n\nimport type { ServerRuntimeState } from './server-runtime.js';\nimport {\n networkEnvBaseline,\n PROXY_ENV_VARS,\n recordNetworkEnvMutation,\n} from './network-env.js';\n\nexport const REQUIRE_SERVER_ENV = 'CLODEX_REQUIRE_SERVER';\n\nexport function removeAnthropicProxyBypass(env: NodeJS.ProcessEnv): void {\n const noProxyValues = [env['NO_PROXY'], env['no_proxy']]\n .filter((value): value is string => value !== undefined);\n if (noProxyValues.length === 0) return;\n\n const filtered = [...new Set(noProxyValues\n .flatMap(value => value.split(','))\n .map(value => value.trim())\n .filter(Boolean)\n .filter(value => {\n const entry = value.toLowerCase().replace(/^https?:\\/\\//, '');\n const host = entry.replace(/:\\d+$/, '');\n if (host === '*') return false;\n const suffix = host.startsWith('*.') ? host.slice(1) : host;\n const bypassesAnthropic = suffix.startsWith('.')\n ? 'api.anthropic.com'.endsWith(suffix)\n : 'api.anthropic.com' === suffix || 'api.anthropic.com'.endsWith(`.${suffix}`);\n return !bypassesAnthropic;\n }))]\n .join(',');\n if (filtered) {\n env['NO_PROXY'] = filtered;\n env['no_proxy'] = filtered;\n } else {\n delete env['NO_PROXY'];\n delete env['no_proxy'];\n }\n}\n\n/**\n * Any non-empty key satisfies the local endpoint gateway (`isAuthorized`\n * accepts everything when no server password is set, i.e. local listen mode).\n */\nexport const LOCAL_GATEWAY_API_KEY = 'clodex-local';\n\nexport function wrapperRequiresServer(env: NodeJS.ProcessEnv): boolean {\n return env[REQUIRE_SERVER_ENV] === '1';\n}\n\nexport function computeWrapperEnv(\n baseEnv: NodeJS.ProcessEnv,\n state: ServerRuntimeState | null,\n): NodeJS.ProcessEnv {\n // No live server: launch claude completely untouched — a down server must\n // never break launching claude.\n if (!state) return { ...baseEnv };\n\n const baseline = networkEnvBaseline(baseEnv);\n const env: NodeJS.ProcessEnv = { ...baseline };\n\n if (state.mode === 'proxy') {\n // Selective MITM: claude keeps its own Anthropic credentials; the proxy\n // routes clodex:/alias models to OpenAI and passes everything else through.\n const proxyUrl = `http://127.0.0.1:${state.port}`;\n delete env['ANTHROPIC_BASE_URL'];\n for (const name of PROXY_ENV_VARS) env[name] = proxyUrl;\n if (state.caPath) env['NODE_EXTRA_CA_CERTS'] = state.caPath;\n removeAnthropicProxyBypass(env);\n recordNetworkEnvMutation(baseline, env);\n return env;\n }\n\n // Endpoint gateway: all traffic goes to the local Anthropic-format gateway.\n for (const name of PROXY_ENV_VARS) delete env[name];\n env['ANTHROPIC_BASE_URL'] = `http://127.0.0.1:${state.port}/anthropic`;\n env['ANTHROPIC_API_KEY'] = LOCAL_GATEWAY_API_KEY;\n recordNetworkEnvMutation(baseline, env);\n return env;\n}\n"],"mappings":"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","names":["randomUUID","closeSync","fsyncSync","mkdirSync","openSync","readFileSync","unlinkSync","dirname","join","join","mkdirSync","dirname","openSync","fsyncSync","closeSync","readFileSync","randomUUID","unlinkSync","randomUUID","readFileSync","renameSync","unlinkSync","readFileSync","randomUUID","renameSync","unlinkSync","execFileSync","existsSync","homedir","join","existsSync","isWindows","join","homedir","existsSync","execFileSync","closeSync","mkdirSync","openSync","readFileSync","renameSync","unlinkSync","writeFileSync","dirname","join","join","isPidAlive","mkdirSync","dirname","openSync","writeFileSync","closeSync","unlinkSync","readFileSync","sleepSync","renameSync"]}
1
+ {"version":3,"sources":["../src/oauth-account-selection.ts","../src/registry/io.ts","../src/paths.ts","../src/registry/types.ts","../src/registry/lock.ts","../src/registry/oauth-account-storage.ts","../src/registry/migrate.ts","../src/registry/validate.ts","../src/config.ts","../src/claude-binary.ts","../src/binary-lookup.ts","../src/listener-ready.ts","../src/server-runtime.ts","../src/network-env.ts","../src/wrapper-env.ts"],"sourcesContent":["/** Environment override for selecting one named OAuth account slot. */\nexport const OAUTH_ACCOUNT_ENV = 'CLODEX_OAUTH_ACCOUNT';\n","// src/registry/io.ts — load/save providers.json with secure permissions\n\nimport { randomUUID } from 'node:crypto';\nimport {\n chmodSync,\n closeSync,\n copyFileSync,\n existsSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeSync,\n} from 'node:fs';\nimport { dirname } from 'node:path';\nimport { isDeepStrictEqual } from 'node:util';\nimport { getAppHome, getProvidersPath } from '../paths.js';\nimport type { ProviderRegistry, RegistryModelsCache, RegistryProvider } from './types.js';\nimport {\n OAUTH_ACCOUNT_NAME_RE,\n REGISTRY_SCHEMA_VERSION,\n REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_SLOTS,\n REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT,\n REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES,\n REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT,\n} from './types.js';\nimport {\n assertRegistryWriteOwnership,\n RegistryLockLostError,\n withRegistryWriteLockSync,\n} from './lock.js';\nimport { migrateRegistry } from './migrate.js';\nimport {\n getOAuthAccountSlot,\n migrateActiveOAuthAccountStorage,\n} from './oauth-account-storage.js';\nimport { isValidProviderId } from './validate.js';\n\nconst DIR_MODE = 0o700;\nconst FILE_MODE = 0o600;\n\nexport function ensureSecureAppHome(): void {\n const home = getAppHome();\n mkdirSync(home, { recursive: true, mode: DIR_MODE });\n try {\n chmodSync(home, DIR_MODE);\n } catch {\n // best-effort on platforms that restrict chmod\n }\n}\n\nexport function writeSecureFile(path: string, content: string): void {\n ensureSecureAppHome();\n mkdirSync(dirname(path), { recursive: true, mode: DIR_MODE });\n const fd = openSync(path, 'wx', FILE_MODE);\n try {\n const payload = Buffer.from(content);\n let offset = 0;\n while (offset < payload.length) {\n const written = writeSync(fd, payload, offset, payload.length - offset);\n if (written <= 0) {\n throw new Error(`Could not complete secure file write: ${path}`);\n }\n offset += written;\n }\n fsyncSync(fd);\n } finally {\n closeSync(fd);\n }\n try {\n chmodSync(path, FILE_MODE);\n } catch {\n // best-effort\n }\n}\n\nexport function syncParentDirectory(path: string): void {\n let fd: number | undefined;\n try {\n fd = openSync(dirname(path), 'r');\n fsyncSync(fd);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== 'EINVAL' && code !== 'ENOTSUP' && code !== 'EPERM') throw error;\n } finally {\n if (fd !== undefined) closeSync(fd);\n }\n}\n\nfunction parseProvider(\n raw: unknown,\n diag?: (message: string) => void,\n): RegistryProvider | null {\n if (!raw || typeof raw !== 'object') return null;\n const p = raw as Record<string, unknown>;\n if (typeof p.id !== 'string' || !isValidProviderId(p.id)) return null;\n if (typeof p.templateId !== 'string' || !p.templateId) return null;\n if (typeof p.name !== 'string' || !p.name) return null;\n if (typeof p.enabled !== 'boolean') return null;\n if (typeof p.authRef !== 'string' || !p.authRef) return null;\n if (typeof p.addedAt !== 'string' || !p.addedAt) return null;\n const api = p.api;\n if (!api || typeof api !== 'object') return null;\n\n const provider: RegistryProvider = {\n id: p.id,\n templateId: p.templateId,\n name: p.name,\n enabled: p.enabled,\n authRef: p.authRef,\n api: api as RegistryProvider['api'],\n addedAt: p.addedAt,\n };\n\n if (hasOwn(p, 'defaultAuthRef')) {\n if (typeof p.defaultAuthRef !== 'string' || !p.defaultAuthRef) return null;\n provider.defaultAuthRef = p.defaultAuthRef;\n }\n\n if (p.subscriptionFilter === 'free') {\n provider.subscriptionFilter = p.subscriptionFilter;\n }\n if (typeof p.preserveModelPricing === 'boolean') {\n provider.preserveModelPricing = p.preserveModelPricing;\n }\n if (p.authType === 'api' || p.authType === 'oauth' || p.authType === 'none') {\n provider.authType = p.authType;\n }\n if (hasOwn(p, 'authAccounts')) {\n const slots = parseAuthAccounts(p.authAccounts);\n if (slots === null) return null;\n provider.authAccounts = slots;\n }\n if (hasOwn(p, 'activeAuthAccount')) {\n if (!isAccountName(p.activeAuthAccount)) return null;\n provider.activeAuthAccount = p.activeAuthAccount;\n }\n if (typeof p.refreshedAt === 'string') provider.refreshedAt = p.refreshedAt;\n if (hasOwn(p, 'defaultModelsCache')) {\n const defaultModelsCache = parseModelsCache(p.defaultModelsCache);\n if (!defaultModelsCache) return null;\n provider.defaultModelsCache = defaultModelsCache;\n }\n const modelsCache = parseModelsCache(p.modelsCache);\n if (modelsCache) provider.modelsCache = modelsCache;\n else if (hasOwn(p, 'modelsCache')) {\n diag?.(`Provider registry dropped an invalid model cache for provider \"${p.id}\".`);\n }\n return provider;\n}\n\nfunction hasOwn(record: Record<string, unknown>, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(record, key);\n}\n\n/**\n * Shape check only, deliberately not a slot-membership check: see the\n * `activeAuthAccount` doc comment on RegistryProvider for why a stale-but-\n * well-formed name must survive the load and fail at apply time instead.\n */\nfunction isAccountName(raw: unknown): raw is string {\n return typeof raw === 'string' && OAUTH_ACCOUNT_NAME_RE.test(raw);\n}\n\nfunction parseModelsCache(raw: unknown): RegistryModelsCache | null {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;\n const cache = raw as Record<string, unknown>;\n if (typeof cache.fetchedAt !== 'string' || !Array.isArray(cache.models)) return null;\n if (cache.models.some(model => !model || typeof model !== 'object' || Array.isArray(model))) {\n return null;\n }\n return {\n fetchedAt: cache.fetchedAt,\n models: cache.models as RegistryModelsCache['models'],\n };\n}\n\n/**\n * Named OAuth account slots must survive a registry load intact and are\n * fail-closed: a silently dropped slot would revert a CLODEX_OAUTH_ACCOUNT\n * launch to the default identity and let credential reconciliation delete the\n * slot's tokens as unreferenced. A malformed slot therefore invalidates the\n * whole provider record instead of being skipped.\n */\nfunction parseAuthAccounts(raw: unknown): RegistryProvider['authAccounts'] | null {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;\n const out: NonNullable<RegistryProvider['authAccounts']> = {};\n for (const [name, value] of Object.entries(raw as Record<string, unknown>)) {\n if (!OAUTH_ACCOUNT_NAME_RE.test(name)) return null;\n if (!value || typeof value !== 'object' || Array.isArray(value)) return null;\n const slot = value as Record<string, unknown>;\n if (typeof slot.authRef !== 'string' || !slot.authRef) return null;\n if (typeof slot.addedAt !== 'string' || !slot.addedAt) return null;\n const modelsCache = hasOwn(slot, 'modelsCache')\n ? parseModelsCache(slot.modelsCache)\n : undefined;\n if (hasOwn(slot, 'modelsCache') && !modelsCache) return null;\n out[name] = {\n authRef: slot.authRef,\n addedAt: slot.addedAt,\n ...(modelsCache ? { modelsCache } : {}),\n };\n }\n return out;\n}\n\nfunction hasValidStrictProviderFields(raw: unknown): boolean {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return false;\n const provider = raw as Record<string, unknown>;\n if (hasOwn(provider, 'subscriptionFilter') && provider.subscriptionFilter !== 'free') {\n return false;\n }\n if (hasOwn(provider, 'preserveModelPricing') && typeof provider.preserveModelPricing !== 'boolean') {\n return false;\n }\n if (\n hasOwn(provider, 'authType')\n && provider.authType !== 'api'\n && provider.authType !== 'oauth'\n && provider.authType !== 'none'\n ) {\n return false;\n }\n if (hasOwn(provider, 'refreshedAt') && typeof provider.refreshedAt !== 'string') {\n return false;\n }\n if (hasOwn(provider, 'authAccounts') && parseAuthAccounts(provider.authAccounts) === null) {\n return false;\n }\n if (hasOwn(provider, 'activeAuthAccount') && !isAccountName(provider.activeAuthAccount)) {\n return false;\n }\n if (hasOwn(provider, 'defaultAuthRef')\n && (typeof provider.defaultAuthRef !== 'string' || !provider.defaultAuthRef)) {\n return false;\n }\n if (hasOwn(provider, 'defaultModelsCache')\n && parseModelsCache(provider.defaultModelsCache) === null) {\n return false;\n }\n if (hasOwn(provider, 'modelsCache')) {\n if (parseModelsCache(provider.modelsCache) === null) return false;\n }\n return true;\n}\n\nfunction hasPresentInvalidAuthType(raw: unknown): boolean {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return false;\n const provider = raw as Record<string, unknown>;\n return hasOwn(provider, 'authType')\n && provider.authType !== 'api'\n && provider.authType !== 'oauth'\n && provider.authType !== 'none';\n}\n\n/**\n * Validate the cross-field credential-storage contract for the schema that\n * supplied it. Versions 1-4 are valid migration input only when the parked\n * field is absent. Version 5 requires every live OAuth selector to name a slot\n * and to materialize that exact slot in `authRef`; otherwise launch must fail\n * closed rather than falling back to the provider default.\n */\nfunction hasValidSelectionStorage(\n provider: RegistryProvider,\n schemaVersion: number,\n): boolean {\n const name = provider.activeAuthAccount?.trim();\n const hasDefault = provider.defaultAuthRef !== undefined;\n const hasDefaultCache = provider.defaultModelsCache !== undefined;\n\n if (schemaVersion < REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES\n && Object.values(provider.authAccounts ?? {}).some(account => account.modelsCache !== undefined)) {\n return false;\n }\n if (name && schemaVersion < REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT) {\n return false;\n }\n if (schemaVersion <= REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES\n && (hasDefault || hasDefaultCache)) {\n return false;\n }\n if (!name) return !hasDefault && !hasDefaultCache;\n if (provider.authType !== 'oauth') return !hasDefault && !hasDefaultCache;\n if (schemaVersion <= REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES) {\n // A well-formed but missing legacy slot remains repairable. Migration does\n // not materialize it, and current launch-time selection still throws.\n return true;\n }\n if (schemaVersion !== REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT) {\n // Preserve the lenient reader's forward-compatible behavior. Strict reads\n // reject unsupported versions before reaching this branch.\n return true;\n }\n const selected = getOAuthAccountSlot(provider, name);\n return hasDefault\n && selected !== undefined\n && provider.authRef === selected.authRef\n // A downgraded launch consumes top-level authRef AND modelsCache. Require\n // the cache to be the selected slot's proven cache (or both absent), or it\n // could launch the right credential with another account's entitlements.\n && isDeepStrictEqual(provider.modelsCache, selected.modelsCache);\n}\n\nfunction parseRegistry(\n raw: unknown,\n diag?: (message: string) => void,\n): ProviderRegistry {\n const empty: ProviderRegistry = { schemaVersion: REGISTRY_SCHEMA_VERSION, providers: [] };\n if (!raw || typeof raw !== 'object') return empty;\n const data = raw as Record<string, unknown>;\n const schemaVersion =\n typeof data.schemaVersion === 'number' ? data.schemaVersion : REGISTRY_SCHEMA_VERSION;\n const providers: RegistryProvider[] = [];\n if (Array.isArray(data.providers)) {\n for (const [index, entry] of data.providers.entries()) {\n const parsed = parseProvider(entry, diag);\n const invalidKnownSelectionAuthType = schemaVersion >= REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT\n && schemaVersion <= REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT\n && parsed?.activeAuthAccount !== undefined\n && hasPresentInvalidAuthType(entry);\n const validSelectionStorage = parsed\n ? hasValidSelectionStorage(parsed, schemaVersion)\n : false;\n if (parsed && !invalidKnownSelectionAuthType && validSelectionStorage) {\n providers.push(parsed);\n } else {\n const id = entry && typeof entry === 'object' && typeof (entry as Record<string, unknown>).id === 'string'\n ? ` \"${(entry as Record<string, unknown>).id}\"`\n : ` at index ${index}`;\n const reason = parsed && !validSelectionStorage\n ? ' because its OAuth account selection storage is inconsistent'\n : '';\n diag?.(`Provider registry dropped invalid provider${id}${reason}.`);\n }\n }\n }\n const registry: ProviderRegistry = {\n schemaVersion,\n providers,\n };\n if (typeof data.importedAt === 'string') registry.importedAt = data.importedAt;\n if (typeof data.pricingCacheAt === 'string') registry.pricingCacheAt = data.pricingCacheAt;\n return registry;\n}\n\nfunction parseRegistryStrict(raw: unknown): ProviderRegistry {\n if (!raw || typeof raw !== 'object') {\n throw new Error('Provider registry must be a JSON object.');\n }\n const data = raw as Record<string, unknown>;\n if (\n data.schemaVersion !== REGISTRY_SCHEMA_VERSION\n && data.schemaVersion !== REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_SLOTS\n && data.schemaVersion !== REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT\n && data.schemaVersion !== REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES\n && data.schemaVersion !== REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT\n ) {\n throw new Error('Provider registry has an unsupported schema version.');\n }\n if (!Array.isArray(data.providers)) {\n throw new Error('Provider registry is missing its providers list.');\n }\n for (const entry of data.providers) {\n const provider = parseProvider(entry);\n if (!provider || !hasValidStrictProviderFields(entry)\n || !hasValidSelectionStorage(provider, data.schemaVersion)) {\n throw new Error('Provider registry contains an invalid provider entry.');\n }\n }\n return parseRegistry(raw);\n}\n\nfunction readRegistryStrict(path: string): ProviderRegistry {\n return parseRegistryStrict(JSON.parse(readFileSync(path, 'utf8')));\n}\n\nclass RegistryMigrationValidationError extends Error {\n constructor(\n readonly registryPath: string,\n cause: unknown,\n ) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n super(detail, { cause });\n this.name = 'RegistryMigrationValidationError';\n }\n}\n\nclass RegistryMigrationReadError extends Error {\n constructor(\n readonly registryPath: string,\n cause: unknown,\n ) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n super(detail, { cause });\n this.name = 'RegistryMigrationReadError';\n }\n}\n\nclass RegistrySaveValidationError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'RegistrySaveValidationError';\n }\n}\n\nclass RegistryPersistenceError extends Error {\n constructor(\n readonly registryPath: string,\n cause: unknown,\n ) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n super(detail, { cause });\n this.name = 'RegistryPersistenceError';\n }\n}\n\nclass RegistryDurabilityCheckError extends Error {\n constructor(\n readonly registryPath: string,\n cause: unknown,\n ) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n super(detail, { cause });\n this.name = 'RegistryDurabilityCheckError';\n }\n}\n\nfunction selectedAccountFilesystemError(\n path: string,\n cause: unknown,\n action: string,\n): Error {\n const detail = cause instanceof Error ? cause.message : String(cause);\n return new Error(\n 'Could not safely persist the selected OAuth account before launch. '\n + `Could not ${action} the provider registry at ${path}: ${detail} `\n + 'Check filesystem permissions, storage health, and free disk space, then retry.',\n { cause },\n );\n}\n\nfunction hasMaterializedActiveAccount(registry: ProviderRegistry): boolean {\n return registry.schemaVersion === REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT\n && registry.providers.some(provider => provider.defaultAuthRef !== undefined);\n}\n\nexport function loadRegistry(\n path = getProvidersPath(),\n diag?: (message: string) => void,\n): ProviderRegistry {\n if (!existsSync(path)) {\n return { schemaVersion: REGISTRY_SCHEMA_VERSION, providers: [] };\n }\n let registry: ProviderRegistry;\n try {\n const raw = JSON.parse(readFileSync(path, 'utf8'));\n registry = parseRegistry(raw, diag);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n diag?.(`Could not read the provider registry at ${path}; treating it as empty: ${detail}`);\n return { schemaVersion: REGISTRY_SCHEMA_VERSION, providers: [] };\n }\n\n const migration = migrateRegistry(registry);\n if (!migration.changed) {\n // A previous publication may have renamed ANY schema version before its\n // parent-directory durability barrier failed. This includes clearing a v5\n // selection back to v1/v2. Re-sync every successfully parsed winner so a\n // plain retry repairs both selection and downgrade transitions.\n try {\n syncParentDirectory(path);\n } catch (error) {\n if (hasMaterializedActiveAccount(registry)) {\n throw selectedAccountFilesystemError(path, error, 'durably sync');\n }\n const detail = error instanceof Error ? error.message : String(error);\n diag?.(`Could not durably sync the unchanged provider registry at ${path}; continuing read-only: ${detail}`);\n }\n return registry;\n }\n\n let winner = registry;\n let materializedActiveAccount = migration.materializedActiveAccount;\n try {\n withRegistryWriteLockSync(() => {\n if (!existsSync(path)) {\n if (materializedActiveAccount) {\n throw new Error('the provider registry disappeared during migration');\n }\n return;\n }\n // The lock may have been contended. Re-read and migrate the winner rather\n // than publishing or returning the stale pre-lock snapshot.\n let serialized: string;\n try {\n serialized = readFileSync(path, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error('the provider registry disappeared during migration', { cause: error });\n }\n throw new RegistryMigrationReadError(path, error);\n }\n let raw: unknown;\n try {\n raw = JSON.parse(serialized);\n } catch (error) {\n throw new RegistryMigrationValidationError(path, error);\n }\n // Classify the winner's identity requirement before strict validation.\n // A malformed sibling can make the strict parse throw, but it must not\n // hide a valid selected provider whose downgrade-visible projection\n // would otherwise remain in memory only.\n const lenientCurrent = parseRegistry(raw);\n const lenientMigration = migrateRegistry(lenientCurrent);\n winner = lenientCurrent;\n materializedActiveAccount = lenientMigration.materializedActiveAccount\n || hasMaterializedActiveAccount(lenientCurrent);\n\n let current: ProviderRegistry;\n try {\n current = parseRegistryStrict(raw);\n } catch (error) {\n throw new RegistryMigrationValidationError(path, error);\n }\n const currentMigration = migrateRegistry(current);\n winner = current;\n // The winner under the lock, not the stale pre-lock snapshot, decides\n // whether a failed write could split launch identity across processes.\n materializedActiveAccount = currentMigration.materializedActiveAccount\n || hasMaterializedActiveAccount(current);\n if (currentMigration.changed) {\n try {\n saveRegistry(current, path);\n } catch (error) {\n if (error instanceof RegistrySaveValidationError) {\n throw new RegistryMigrationValidationError(path, error);\n }\n throw error;\n }\n } else {\n // Another process may have renamed this already-migrated winner but\n // failed its parent-directory fsync before we acquired the lock. The\n // authoritative reread must repair that barrier too, not only the\n // optimistic no-migration read above.\n try {\n syncParentDirectory(path);\n } catch (error) {\n throw new RegistryDurabilityCheckError(path, error);\n }\n }\n }, { lockPath: `${path}.lock` });\n return winner;\n } catch (error) {\n if (error instanceof RegistryDurabilityCheckError) {\n if (materializedActiveAccount) {\n throw selectedAccountFilesystemError(\n error.registryPath,\n error,\n 'durably sync',\n );\n }\n throw new Error(\n `Could not durably sync the provider registry at ${error.registryPath}: ${error.message} `\n + 'Check filesystem permissions, storage health, and free disk space, then retry.',\n { cause: error },\n );\n }\n if (materializedActiveAccount) {\n if (error instanceof RegistryMigrationValidationError) {\n throw new Error(\n 'Could not safely persist the selected OAuth account before launch. '\n + `The provider registry at ${error.registryPath} is invalid: ${error.message} `\n + `Repair it or restore ${error.registryPath}.bak, then retry.`,\n { cause: error },\n );\n }\n if (error instanceof RegistryMigrationReadError) {\n throw selectedAccountFilesystemError(\n error.registryPath,\n error,\n 'read',\n );\n }\n if (error instanceof RegistryPersistenceError) {\n throw selectedAccountFilesystemError(\n error.registryPath,\n error,\n 'durably write',\n );\n }\n if (error && typeof error === 'object'\n && typeof (error as NodeJS.ErrnoException).code === 'string') {\n // Lock timeout/lost-lease errors are intentionally untyped and retain\n // the process-contention guidance below. Raw errno failures from lock\n // directory/file I/O need filesystem recovery instead.\n throw selectedAccountFilesystemError(path, error, 'access the lock for');\n }\n const detail = error instanceof Error ? ` ${error.message}` : '';\n throw new Error(\n 'Could not safely persist the selected OAuth account before launch.'\n + `${detail} Stop other Clodex processes and retry.`,\n { cause: error },\n );\n }\n // The historical provider-id rename is presentation-only and remains a\n // best-effort migration. Identity materialization above is not.\n return winner;\n }\n}\n\n/**\n * Load a registry for destructive decisions. Unlike `loadRegistry`, read,\n * parse, and provider-shape errors propagate so callers cannot confuse an\n * unreadable registry with an empty one.\n */\nexport function loadRegistryStrict(path = getProvidersPath()): ProviderRegistry {\n if (!existsSync(path)) {\n return { schemaVersion: REGISTRY_SCHEMA_VERSION, providers: [] };\n }\n const registry = readRegistryStrict(path);\n migrateRegistry(registry);\n return registry;\n}\n\nexport function saveRegistry(registry: ProviderRegistry, path = getProvidersPath()): void {\n assertRegistryWriteOwnership(path);\n // Programmatic callers and strict legacy loads may hand this function a\n // v3/v4 selector. Upgrade it under the same write lock so this build never\n // publishes a selector that a downgraded launch will ignore.\n if (registry.schemaVersion >= REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT\n && registry.schemaVersion <= REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES) {\n migrateActiveOAuthAccountStorage(registry);\n }\n for (const provider of registry.providers) {\n if (!hasValidSelectionStorage(\n provider,\n REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT,\n )) {\n throw new RegistrySaveValidationError(\n 'Provider registry contains invalid OAuth account selection storage.',\n );\n }\n }\n // Slot state fences older writers via the schema version (see types.ts);\n // slot-free registries return to v1 so old builds interoperate again.\n // Highest state present wins. Version 3 fences the selector from older\n // writers; version 5 also projects it into `authRef`, which older lenient\n // launchers already read.\n const hasMaterializedSelector = registry.providers.some(\n provider => provider.defaultAuthRef !== undefined,\n );\n const hasAccountModelCaches = registry.providers.some(provider => (\n Object.values(provider.authAccounts ?? {}).some(account => account.modelsCache !== undefined)\n ));\n const hasSelector = registry.providers.some(provider => provider.activeAuthAccount !== undefined);\n const hasSlots = registry.providers.some(\n provider => provider.authAccounts && Object.keys(provider.authAccounts).length > 0,\n );\n const schemaVersion = hasMaterializedSelector\n ? REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT\n : hasAccountModelCaches\n ? REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES\n : hasSelector\n ? REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT\n : hasSlots\n ? REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_SLOTS\n : REGISTRY_SCHEMA_VERSION;\n const serializedRegistry = { ...registry, schemaVersion };\n // Validate the exact JSON shape about to be published. This catches values\n // omitted by JSON.stringify (for example an accidentally undefined authRef)\n // instead of letting the next load discover the provider has disappeared.\n try {\n parseRegistryStrict(JSON.parse(JSON.stringify(serializedRegistry)));\n } catch (error) {\n throw new RegistrySaveValidationError(\n error instanceof Error ? error.message : String(error),\n { cause: error },\n );\n }\n const payload = `${JSON.stringify(serializedRegistry, null, 2)}\\n`;\n const backup = `${path}.bak`;\n if (existsSync(path)) {\n try {\n copyFileSync(path, backup);\n } catch {\n // backup is best-effort\n }\n }\n const tmp = `${path}.${process.pid}.${randomUUID()}.tmp`;\n try {\n writeSecureFile(tmp, payload);\n assertRegistryWriteOwnership(path);\n renameSync(tmp, path);\n syncParentDirectory(path);\n } catch (error) {\n if (error instanceof RegistryLockLostError) throw error;\n throw new RegistryPersistenceError(path, error);\n } finally {\n try {\n unlinkSync(tmp);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw new RegistryPersistenceError(path, err);\n }\n }\n }\n}\n\nexport function emptyRegistry(): ProviderRegistry {\n return { schemaVersion: REGISTRY_SCHEMA_VERSION, providers: [] };\n}\n","import { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nexport const APP_DIR_NAME = 'clodex';\n\ninterface HomeEnv {\n HOME?: string;\n CLODEX_HOME?: string;\n USERPROFILE?: string;\n}\n\nfunction userHome(env: HomeEnv = process.env): string {\n return env.HOME ?? env.USERPROFILE ?? homedir();\n}\n\nexport function resolveAppHomeOverride(env: HomeEnv = process.env): string | undefined {\n const override = env.CLODEX_HOME;\n return override?.trim() || undefined;\n}\n\nexport function getAppHome(env: HomeEnv = process.env): string {\n const override = resolveAppHomeOverride(env);\n if (override) return override;\n return join(userHome(env), `.${APP_DIR_NAME}`);\n}\n\nexport function getConfigPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'config.json');\n}\n\nexport function getLocalPatchesPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'local-patches.mjs');\n}\n\nexport function getProvidersPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'providers.json');\n}\n\nexport function getCredentialCleanupPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'credential-cleanup.json');\n}\n\nexport function getLogsPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'logs');\n}\n","// src/registry/types.ts — native provider registry schema (no secrets)\n\nimport type { FreeStatus } from '../free-models.js';\nimport type { ModelRuntimeCompatibility } from '../model-runtime-compatibility.js';\n\nexport const REGISTRY_SCHEMA_VERSION = 1;\n\n/**\n * Written whenever any provider carries named OAuth account slots. Builds\n * >= 1.3.0 fail closed on an unknown schema version in every MUTATING path\n * (parseRegistryStrict throws), so those builds cannot load a slot-bearing\n * registry, drop the unknown field, and save the providers back slot-less.\n * Releases 0.1.0-1.2.2 have no strict loader and silently strip slot state;\n * the credentials remain recoverable in the credential store. A registry\n * whose last slot is removed is written back at version 1, so older builds\n * interoperate again the moment no slot state exists.\n */\nexport const REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_SLOTS = 2;\n\n/**\n * Written whenever any provider carries `activeAuthAccount`.\n *\n * A DISTINCT version, not a reuse of the slot version: a build from before the\n * stored selector existed accepts version 2, parses the slots, silently\n * ignores the unknown `activeAuthAccount`, and saves the registry back without\n * it. Version 3 stops that, because its strict loader throws on a version it\n * does not know. A registry whose selector is cleared falls back to 2 (or 1),\n * so older builds interoperate again as soon as no selector state exists.\n *\n * Versions 3 and 4 are also migration sources for downgrade-safe selection\n * storage. They still carry the provider default in `authRef`; current builds\n * project the selected slot into that field and park the default separately\n * before writing version 5.\n */\nexport const REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT = 3;\n\n/**\n * Written when a named OAuth slot carries its own model-entitlement cache.\n * A cache is not a credential, but silently dropping it would make a temporary\n * account reuse the persisted account's catalog. Version 4 therefore fences\n * older mutating builds that know about slots but not their cache isolation.\n */\nexport const REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES = 4;\n\n/**\n * Written whenever `defaultAuthRef` parks a provider's own OAuth credential\n * while `authRef` points at the selected named slot. A pre-selector build's\n * lenient loader ignores both the version and the new fields, but already\n * reads `authRef`, so it launches as the selected identity. Its strict\n * mutation paths reject version 5 and cannot discard the parked default.\n */\nexport const REGISTRY_SCHEMA_VERSION_WITH_MATERIALIZED_ACTIVE_ACCOUNT = 5;\n\n/**\n * Shape rule for a named OAuth account-slot name — the single home. Slot\n * names land in credential-store scopes and env values, and the registry\n * parser must accept exactly what `validateOAuthAccountName` admits, or a\n * saved slot fails to survive a load.\n */\nexport const OAUTH_ACCOUNT_NAME_RE = /^[a-z0-9][a-z0-9_-]{0,31}$/;\n\nexport type RegistrySubscriptionFilter = 'free';\n\nexport interface CachedModel {\n id: string;\n name: string;\n upstreamModelId: string;\n family?: string;\n brand?: string;\n contextWindow?: number;\n /** Highest input window the model accepts, reachable via the `max` context stop. */\n maxContextWindow?: number;\n /** Share of the raw window a client fills; mirrors the Codex catalog field. */\n effectiveContextPercent?: number;\n /** Input size above which the provider bills the whole request at a higher rate. */\n pricingBoundary?: number;\n /** How the provider prices above the boundary, for the user-facing warning. */\n pricingBoundaryNote?: string;\n /** Largest output the model accepts, independent of the input window. */\n maxOutputTokens?: number;\n cost?: { input: number; output: number; cache_read?: number; cache_write?: number };\n isFree?: boolean;\n freeStatus?: FreeStatus;\n modelFormat: 'anthropic' | 'openai' | 'cloud-code';\n /** Per-model override — wins over provider-level api.npm */\n npm?: string;\n /** Per-model override — wins over provider-level api.url */\n apiUrl?: string;\n sourceBackend?: string;\n /** Provider-reported request parameters, e.g. OpenRouter supported_parameters. */\n supportedParameters?: string[];\n /** Broad model metadata: model can produce reasoning/thinking output. */\n reasoning?: boolean;\n /** Streaming/interleaved reasoning field name from metadata, e.g. reasoning_content. */\n interleavedReasoningField?: string;\n /** Backend capability: model requires the Responses-Lite request shape (x-openai-internal-codex-responses-lite). */\n useResponsesLite?: boolean;\n /** Backend capability: model must use the WebSocket Responses transport instead of HTTP. */\n preferWebSockets?: boolean;\n /** Supported input modalities preserved from curated provider metadata. */\n modalities?: ('text' | 'image')[];\n /** Provider-neutral per-model wire quirks. */\n compatibility?: ModelRuntimeCompatibility;\n}\n\nexport interface RegistryModelsCache {\n fetchedAt: string;\n models: CachedModel[];\n}\n\nexport interface RegistryOAuthAccount {\n authRef: string;\n addedAt: string;\n /** Catalog discovered with this named slot's credential. */\n modelsCache?: RegistryModelsCache;\n}\n\nexport interface RegistryProvider {\n id: string;\n templateId: string;\n name: string;\n enabled: boolean;\n authRef: string;\n /**\n * The provider's own OAuth credential while a named slot is selected.\n * During that time `authRef` deliberately points at the selected slot so a\n * downgraded pre-selector build launches as the same identity. Clearing the\n * selection restores this value to `authRef` and removes the field.\n */\n defaultAuthRef?: string;\n /** Catalog discovered with the provider default while a named slot is selected. */\n defaultModelsCache?: RegistryModelsCache;\n authType?: 'api' | 'oauth' | 'none';\n /**\n * Named OAuth account slots beyond the default credential\n * (`clodex providers auth openai --account <name>`). Each slot owns a\n * disjoint credential-store lineage; CLODEX_OAUTH_ACCOUNT selects one for a\n * launch without replacing the provider-owned default credential.\n */\n authAccounts?: Record<string, RegistryOAuthAccount>;\n /**\n * The `authAccounts` slot every launch uses, so the running identity does not\n * depend on remembering an environment variable. Absent means the provider's\n * own default credential. CLODEX_OAUTH_ACCOUNT still overrides it for a\n * single run. While present on an OAuth provider, persisted `authRef` is the\n * selected slot and `defaultAuthRef` parks the provider default for rollback.\n *\n * Legacy v3/v4 bytes enforce only the name shape so a missing slot remains\n * loadable and repairable; applying it still fails loud. V5 additionally\n * requires membership and exact authRef/cache projection, because a missing\n * materialized slot is corruption rather than a legacy repair state.\n */\n activeAuthAccount?: string;\n subscriptionFilter?: RegistrySubscriptionFilter;\n /** Keep provider/curated costs instead of replacing them with the global pricing cache. */\n preserveModelPricing?: boolean;\n api: {\n npm?: string;\n url?: string;\n id?: string;\n /** Static headers sent on every upstream request (e.g. a plan/auth-tracking header a custom endpoint requires). */\n headers?: Record<string, string>;\n };\n modelsCache?: RegistryModelsCache;\n addedAt: string;\n refreshedAt?: string;\n}\n\nexport interface ProviderRegistry {\n schemaVersion: number;\n providers: RegistryProvider[];\n importedAt?: string;\n pricingCacheAt?: string;\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport { createHash, randomUUID } from 'node:crypto';\nimport {\n closeSync,\n fstatSync,\n fsyncSync,\n linkSync,\n mkdirSync,\n openSync,\n readFileSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { userInfo } from 'node:os';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport { getProvidersPath } from '../paths.js';\n\nconst DEFAULT_WAIT_MS = 30_000;\nconst DEFAULT_CREDENTIAL_MUTATION_WAIT_MS = 150_000;\nconst DEFAULT_RETRY_MS = 25;\n\ninterface RegistryLockOwner {\n pid: number;\n startedAt: number;\n token: string;\n}\n\ninterface RegistryLockSnapshot {\n raw: string;\n device: number;\n inode: number;\n modifiedAt: number;\n}\n\ninterface RegistryLockOptions {\n lockPath?: string;\n waitMs?: number;\n retryMs?: number;\n now?: () => number;\n isAlive?: (pid: number) => boolean;\n}\n\ninterface RegistryLockContext {\n leases: ReadonlyMap<string, RegistryLockLease>;\n}\n\nexport interface RegistryLockLease {\n active: boolean;\n readonly lockPath: string;\n readonly token: string;\n readonly device: number;\n readonly inode: number;\n assertOwned: () => void;\n release: () => void;\n}\n\nconst registryLockContext = new AsyncLocalStorage<RegistryLockContext>();\n\nexport class RegistryLockLostError extends Error {\n constructor(lockPath: string) {\n super(`Provider registry lock ownership was lost before write: ${lockPath}`);\n this.name = 'RegistryLockLostError';\n }\n}\n\nexport function getRegistryLockPath(): string {\n return `${getProvidersPath()}.lock`;\n}\n\nfunction isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code === 'EPERM';\n }\n}\n\nfunction parseLockOwner(raw: string): RegistryLockOwner | null {\n try {\n const parsed = JSON.parse(raw) as Partial<RegistryLockOwner>;\n if (!Number.isInteger(parsed.pid) || (parsed.pid ?? 0) <= 0) return null;\n if (\n typeof parsed.startedAt !== 'number' ||\n !Number.isFinite(parsed.startedAt)\n )\n return null;\n if (typeof parsed.token !== 'string' || parsed.token.length === 0)\n return null;\n return parsed as RegistryLockOwner;\n } catch {\n return null;\n }\n}\n\nfunction createLockRecord(\n lockPath: string,\n owner: RegistryLockOwner,\n): RegistryLockSnapshot | null {\n const raw = JSON.stringify(owner);\n const tempPath = `${lockPath}.${process.pid}.${owner.token}.tmp`;\n let fd: number | undefined;\n try {\n fd = openSync(tempPath, 'wx', 0o600);\n writeFileSync(fd, raw);\n fsyncSync(fd);\n const stats = fstatSync(fd);\n try {\n linkSync(tempPath, lockPath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') return null;\n throw err;\n }\n return {\n raw,\n device: stats.dev,\n inode: stats.ino,\n modifiedAt: stats.mtimeMs,\n };\n } finally {\n if (fd !== undefined) closeSync(fd);\n try {\n unlinkSync(tempPath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n }\n}\n\nfunction lockFileMatchesLease(lease: RegistryLockLease): boolean {\n let fd: number | undefined;\n try {\n fd = openSync(lease.lockPath, 'r');\n const openedStats = fstatSync(fd);\n const owner = parseLockOwner(readFileSync(fd, 'utf8'));\n const pathStats = statSync(lease.lockPath);\n return (\n owner?.token === lease.token &&\n openedStats.dev === lease.device &&\n openedStats.ino === lease.inode &&\n pathStats.dev === lease.device &&\n pathStats.ino === lease.inode\n );\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return false;\n throw err;\n } finally {\n if (fd !== undefined) closeSync(fd);\n }\n}\n\nfunction createLease(\n lockPath: string,\n owner: RegistryLockOwner,\n snapshot: RegistryLockSnapshot,\n): RegistryLockLease {\n const lease: RegistryLockLease = {\n active: true,\n lockPath,\n token: owner.token,\n device: snapshot.device,\n inode: snapshot.inode,\n assertOwned: () => {\n if (!lease.active || !lockFileMatchesLease(lease)) {\n lease.active = false;\n throw new RegistryLockLostError(lockPath);\n }\n },\n release: () => {\n if (!lease.active) return;\n lease.active = false;\n if (lockFileMatchesLease(lease)) unlinkSync(lockPath);\n },\n };\n return lease;\n}\n\nexport function assertRegistryWriteOwnership(\n registryPath = getProvidersPath(),\n): void {\n const lockPath = `${registryPath}.lock`;\n const lease = registryLockContext.getStore()?.leases.get(lockPath);\n if (!lease) throw new RegistryLockLostError(lockPath);\n lease.assertOwned();\n}\n\nfunction getStaleLockSnapshot(\n lockPath: string,\n alive: (pid: number) => boolean,\n): RegistryLockSnapshot | null {\n const raw = readFileSync(lockPath, 'utf8');\n const stats = statSync(lockPath);\n const snapshot: RegistryLockSnapshot = {\n raw,\n device: stats.dev,\n inode: stats.ino,\n modifiedAt: stats.mtimeMs,\n };\n const owner = parseLockOwner(raw);\n if (owner) return alive(owner.pid) ? null : snapshot;\n return snapshot;\n}\n\nfunction removeStaleLock(\n lockPath: string,\n expected?: RegistryLockSnapshot,\n): boolean {\n try {\n if (expected) {\n const raw = readFileSync(lockPath, 'utf8');\n const stats = statSync(lockPath);\n if (\n raw !== expected.raw ||\n stats.dev !== expected.device ||\n stats.ino !== expected.inode ||\n stats.mtimeMs !== expected.modifiedAt\n )\n return false;\n }\n unlinkSync(lockPath);\n return true;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n return false;\n }\n}\n\nfunction tryAcquireReaperGuard(\n lockPath: string,\n now: number,\n alive: (pid: number) => boolean,\n): RegistryLockLease | null {\n const guardPath = `${lockPath}.reap`;\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const owner: RegistryLockOwner = {\n pid: process.pid,\n startedAt: now,\n token: randomUUID(),\n };\n try {\n const snapshot = createLockRecord(guardPath, owner);\n if (snapshot) return createLease(guardPath, owner, snapshot);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw err;\n }\n\n let stale: RegistryLockSnapshot | null = null;\n try {\n stale = getStaleLockSnapshot(guardPath, alive);\n } catch (readErr) {\n if ((readErr as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw readErr;\n }\n if (!stale) return null;\n if (!removeStaleLock(guardPath, stale)) continue;\n }\n return null;\n}\n\nexport function tryAcquireRegistryLock(\n lockPath = getRegistryLockPath(),\n options: Pick<RegistryLockOptions, 'now' | 'isAlive'> = {},\n): RegistryLockLease | null {\n const now = options.now?.() ?? Date.now();\n const alive = options.isAlive ?? isPidAlive;\n mkdirSync(dirname(lockPath), { recursive: true, mode: 0o700 });\n\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const owner: RegistryLockOwner = {\n pid: process.pid,\n startedAt: now,\n token: randomUUID(),\n };\n try {\n const snapshot = createLockRecord(lockPath, owner);\n if (snapshot) return createLease(lockPath, owner, snapshot);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw err;\n }\n\n let stale: RegistryLockSnapshot | null = null;\n try {\n stale = getStaleLockSnapshot(lockPath, alive);\n } catch (readErr) {\n if ((readErr as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw readErr;\n }\n if (!stale) return null;\n const reaperLease = tryAcquireReaperGuard(lockPath, now, alive);\n if (!reaperLease) return null;\n try {\n let currentStale: RegistryLockSnapshot | null = null;\n try {\n currentStale = getStaleLockSnapshot(lockPath, alive);\n } catch (readErr) {\n if ((readErr as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw readErr;\n }\n if (!currentStale) return null;\n if (!removeStaleLock(lockPath, currentStale)) continue;\n } finally {\n reaperLease.release();\n }\n }\n return null;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction sleepSync(ms: number): void {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\nfunction lockTimeoutError(\n lockPath: string,\n waitMs: number,\n alive: (pid: number) => boolean,\n): Error {\n let owner: RegistryLockOwner | null = null;\n try {\n owner = parseLockOwner(readFileSync(lockPath, 'utf8'));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n if (owner && alive(owner.pid)) {\n return new Error(\n `Timed out after ${waitMs}ms waiting for lock held by clodex process ` +\n `(pid ${owner.pid}): ${lockPath}`,\n );\n }\n return new Error(\n `Timed out after ${waitMs}ms waiting for lock: ${lockPath}`,\n );\n}\n\nexport async function withRegistryWriteLock<T>(\n operation: () => Promise<T> | T,\n options: RegistryLockOptions = {},\n): Promise<T> {\n const lockPath = options.lockPath ?? getRegistryLockPath();\n const inheritedLeases = registryLockContext.getStore()?.leases;\n if (inheritedLeases?.get(lockPath)?.active) return operation();\n\n const waitMs = options.waitMs ?? DEFAULT_WAIT_MS;\n const retryMs = options.retryMs ?? DEFAULT_RETRY_MS;\n const now = options.now ?? Date.now;\n const deadline = now() + waitMs;\n let lease: RegistryLockLease | null = null;\n\n while (!lease) {\n lease = tryAcquireRegistryLock(lockPath, {\n now,\n isAlive: options.isAlive,\n });\n if (lease) break;\n if (now() >= deadline)\n throw lockTimeoutError(lockPath, waitMs, options.isAlive ?? isPidAlive);\n await sleep(retryMs);\n }\n\n const leases = new Map(inheritedLeases);\n leases.set(lockPath, lease);\n const context: RegistryLockContext = { leases };\n return registryLockContext.run(context, async () => {\n try {\n return await operation();\n } finally {\n lease.release();\n }\n });\n}\n\nexport function withRegistryWriteLockSync<T>(\n operation: () => T,\n options: RegistryLockOptions = {},\n): T {\n const lockPath = options.lockPath ?? getRegistryLockPath();\n const inheritedLeases = registryLockContext.getStore()?.leases;\n if (inheritedLeases?.get(lockPath)?.active) return operation();\n\n const waitMs = options.waitMs ?? DEFAULT_WAIT_MS;\n const retryMs = options.retryMs ?? DEFAULT_RETRY_MS;\n const now = options.now ?? Date.now;\n const deadline = now() + waitMs;\n let lease: RegistryLockLease | null = null;\n\n while (!lease) {\n lease = tryAcquireRegistryLock(lockPath, {\n now,\n isAlive: options.isAlive,\n });\n if (lease) break;\n if (now() >= deadline)\n throw lockTimeoutError(lockPath, waitMs, options.isAlive ?? isPidAlive);\n sleepSync(retryMs);\n }\n\n const leases = new Map(inheritedLeases);\n leases.set(lockPath, lease);\n const context: RegistryLockContext = { leases };\n return registryLockContext.run(context, () => {\n try {\n return operation();\n } finally {\n lease.release();\n }\n });\n}\n\nexport function getCredentialMutationLockPath(authRef: string): string {\n const digest = createHash('sha256')\n .update('clodex-credential-mutation\\0')\n .update(authRef)\n .digest('hex');\n return join(getCredentialLockRoot(), `${digest}.lock`);\n}\n\nfunction getNativeCredentialRoot(): string {\n const nativeHome = userInfo().homedir;\n if (!nativeHome || !isAbsolute(nativeHome)) {\n throw new Error('Could not determine the native user home for credential coordination');\n }\n return join(nativeHome, '.clodex');\n}\n\nexport function getCredentialLockRoot(): string {\n return join(getNativeCredentialRoot(), 'credential-locks');\n}\n\nexport function getCredentialStateRoot(): string {\n return join(getNativeCredentialRoot(), 'keyring-state');\n}\n\nexport function withCredentialMutationLock<T>(\n authRef: string,\n operation: () => Promise<T> | T,\n options: Pick<RegistryLockOptions, 'waitMs' | 'retryMs'> = {},\n): Promise<T> {\n return withRegistryWriteLock(operation, {\n ...options,\n lockPath: getCredentialMutationLockPath(authRef),\n waitMs: options.waitMs ?? DEFAULT_CREDENTIAL_MUTATION_WAIT_MS,\n });\n}\n\nexport function getProviderMutationLockPath(providerSlot: string): string {\n const digest = createHash('sha256')\n .update('clodex-provider-mutation\\0')\n .update(providerSlot)\n .digest('hex');\n return `${getProvidersPath()}.provider-${digest}.lock`;\n}\n\nexport function withProviderMutationLock<T>(\n providerSlot: string,\n operation: () => Promise<T> | T,\n): Promise<T> {\n return withRegistryWriteLock(operation, {\n lockPath: getProviderMutationLockPath(providerSlot),\n });\n}\n","import type { ProviderRegistry, RegistryProvider } from './types.js';\n\n/**\n * Resolve only an account slot the registry actually owns. Account names such\n * as `constructor` are valid, so ordinary bracket lookup can otherwise return\n * an inherited Object.prototype member and turn a stale selector into data.\n */\nexport function getOAuthAccountSlot(\n provider: Pick<RegistryProvider, 'authAccounts'>,\n name: string,\n): NonNullable<RegistryProvider['authAccounts']>[string] | undefined {\n const accounts = provider.authAccounts;\n return accounts && Object.prototype.hasOwnProperty.call(accounts, name)\n ? accounts[name]\n : undefined;\n}\n\n/** The provider-owned credential, whether or not a named slot is selected. */\nexport function providerDefaultAuthRef(\n provider: Pick<RegistryProvider, 'authRef' | 'defaultAuthRef'>,\n): string {\n return provider.defaultAuthRef ?? provider.authRef;\n}\n\n/**\n * Persist one named selection in the downgrade-visible `authRef` field while\n * retaining the provider default for an exact rollback.\n */\nexport function storeActiveOAuthAccount(\n provider: RegistryProvider,\n name: string,\n selectedAuthRef: string,\n): boolean {\n const previousAuthRef = provider.authRef;\n const previousDefaultAuthRef = provider.defaultAuthRef;\n const previousDefaultModelsCache = provider.defaultModelsCache;\n const previousAccount = provider.activeAuthAccount;\n if (provider.defaultAuthRef === undefined) {\n provider.defaultAuthRef = provider.authRef;\n if (provider.modelsCache) provider.defaultModelsCache = provider.modelsCache;\n }\n provider.authRef = selectedAuthRef;\n provider.activeAuthAccount = name;\n return previousAuthRef !== provider.authRef\n || previousDefaultAuthRef !== provider.defaultAuthRef\n || previousDefaultModelsCache !== provider.defaultModelsCache\n || previousAccount !== provider.activeAuthAccount;\n}\n\n/** Restore the parked provider default and remove all persisted selection state. */\nexport function clearActiveOAuthAccount(provider: RegistryProvider): boolean {\n const previousAuthRef = provider.authRef;\n const previousDefaultAuthRef = provider.defaultAuthRef;\n const previousDefaultModelsCache = provider.defaultModelsCache;\n const previousAccount = provider.activeAuthAccount;\n const hasMaterializedSelection = provider.defaultAuthRef !== undefined;\n provider.authRef = providerDefaultAuthRef(provider);\n if (hasMaterializedSelection) {\n if (provider.defaultModelsCache) {\n provider.modelsCache = provider.defaultModelsCache;\n provider.refreshedAt = provider.defaultModelsCache.fetchedAt;\n } else {\n delete provider.modelsCache;\n delete provider.refreshedAt;\n }\n }\n delete provider.defaultAuthRef;\n delete provider.defaultModelsCache;\n delete provider.activeAuthAccount;\n return previousAuthRef !== provider.authRef\n || previousDefaultAuthRef !== provider.defaultAuthRef\n || previousDefaultModelsCache !== provider.defaultModelsCache\n || previousAccount !== provider.activeAuthAccount;\n}\n\n/**\n * Upgrade OAuth selectors written before schema v5. In v3/v4, `authRef` is\n * defined as the provider default, so it is safe to park. The top-level model\n * cache is not proof of account ownership, however: only a v4 slot cache is.\n * Never copy an ambiguous top cache into the selected slot. Project the slot's\n * proven cache when one exists, otherwise clear the top cache and fail closed\n * until that account is refreshed.\n *\n * A selector whose slot is missing is deliberately left untouched. There is\n * no selected credential to materialize, and guessing the default would turn\n * a broken selection into a silent identity fallback.\n */\nexport function migrateActiveOAuthAccountStorage(registry: ProviderRegistry): boolean {\n let changed = false;\n for (const provider of registry.providers) {\n const name = provider.activeAuthAccount?.trim();\n if (provider.authType !== 'oauth' || !name || provider.defaultAuthRef !== undefined) continue;\n const selected = getOAuthAccountSlot(provider, name);\n if (!selected) continue;\n\n provider.defaultAuthRef = provider.authRef;\n provider.authRef = selected.authRef;\n // Account-owned caches did not exist until v4. A stray cache in older\n // bytes has no schema-backed ownership provenance and must not be paired\n // with the selected credential.\n if (registry.schemaVersion >= 4 && selected.modelsCache) {\n provider.modelsCache = selected.modelsCache;\n provider.refreshedAt = selected.modelsCache.fetchedAt;\n } else {\n delete provider.modelsCache;\n delete provider.refreshedAt;\n }\n changed = true;\n }\n return changed;\n}\n","import {\n REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT,\n REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES,\n type ProviderRegistry,\n} from './types.js';\nimport { migrateActiveOAuthAccountStorage } from './oauth-account-storage.js';\n\n// Rename {id:'openai', authType:'oauth'} → {id:'openai-oauth'} so it can coexist\n// with the API-key 'openai' provider. Preserves the original authRef so the\n// keyring credential isn't orphaned.\nexport function migrateOAuthOpenAiProvider(registry: ProviderRegistry): boolean {\n if (registry.providers.some(p => p.id === 'openai-oauth')) return false;\n\n const idx = registry.providers.findIndex(\n p => p.id === 'openai' && p.authType === 'oauth',\n );\n if (idx < 0) return false;\n\n const existing = registry.providers[idx]!;\n registry.providers[idx] = {\n ...existing,\n id: 'openai-oauth',\n templateId: existing.templateId || 'openai',\n name: existing.name === 'OpenAI' ? 'OpenAI (ChatGPT)' : existing.name,\n };\n return true;\n}\n\nexport interface RegistryMigrationResult {\n changed: boolean;\n /**\n * The selected credential/cache identity was projected into downgrade-visible\n * top-level fields. Returning those bytes before they are durable would put\n * the current process and an older process on different identities.\n */\n materializedActiveAccount: boolean;\n}\n\n/** Apply every supported in-memory registry migration. */\nexport function migrateRegistry(registry: ProviderRegistry): RegistryMigrationResult {\n const renamed = migrateOAuthOpenAiProvider(registry);\n // Schema v5 is authoritative. Never infer a missing parked default there:\n // its top-level authRef is already the selected slot, not the value to park.\n const materialized = registry.schemaVersion >= REGISTRY_SCHEMA_VERSION_WITH_ACTIVE_ACCOUNT\n && registry.schemaVersion <= REGISTRY_SCHEMA_VERSION_WITH_ACCOUNT_MODEL_CACHES\n ? migrateActiveOAuthAccountStorage(registry)\n : false;\n return {\n changed: renamed || materialized,\n materializedActiveAccount: materialized,\n };\n}\n","// src/registry/validate.ts\n\n/** Stable provider slug: lowercase alphanumeric + internal hyphens. */\nexport const PROVIDER_ID_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\n\nexport function isValidProviderId(id: string): boolean {\n return PROVIDER_ID_PATTERN.test(id);\n}\n\nexport function slugifyProviderId(displayName: string): string {\n const base = displayName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n if (!base) return 'custom-provider';\n if (isValidProviderId(base)) return base;\n const trimmed = base.replace(/^-+|-+$/g, '');\n return isValidProviderId(trimmed) ? trimmed : `custom-${trimmed.slice(0, 40)}`;\n}\n\nexport function customProviderId(displayName: string): string {\n const slug = slugifyProviderId(displayName);\n return slug.startsWith('custom-') ? slug : `custom-${slug}`;\n}\n","import type { UserPreferences } from './types.js';\nimport { randomUUID } from 'node:crypto';\nimport { readFileSync, renameSync, unlinkSync } from 'node:fs';\nimport { getConfigPath } from './paths.js';\nimport { syncParentDirectory, writeSecureFile } from './registry/io.js';\nimport {\n assertRegistryWriteOwnership,\n withRegistryWriteLock,\n withRegistryWriteLockSync,\n} from './registry/lock.js';\n\nfunction readJsonFile(path: string): UserPreferences | null {\n try {\n const parsed = JSON.parse(readFileSync(path, 'utf8'));\n return parsed && typeof parsed === 'object' ? parsed as UserPreferences : null;\n } catch {\n return null;\n }\n}\n\nfunction readConfig(): UserPreferences {\n return readJsonFile(getConfigPath()) ?? {};\n}\n\nfunction writeConfig(config: UserPreferences): void {\n const configPath = getConfigPath();\n assertRegistryWriteOwnership(configPath);\n const payload = `${JSON.stringify(config, null, 2)}\\n`;\n const tmp = `${configPath}.${process.pid}.${randomUUID()}.tmp`;\n try {\n writeSecureFile(tmp, payload);\n assertRegistryWriteOwnership(configPath);\n renameSync(tmp, configPath);\n syncParentDirectory(configPath);\n } finally {\n try {\n unlinkSync(tmp);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n }\n}\n\nfunction updateConfig<T>(mutate: (config: UserPreferences) => T): T {\n const configPath = getConfigPath();\n return withRegistryWriteLockSync(() => {\n const config = readJsonFile(configPath) ?? {};\n const result = mutate(config);\n writeConfig(config);\n return result;\n }, { lockPath: `${configPath}.lock` });\n}\n\ninterface AsyncConfigUpdate<T> {\n result: T;\n write: boolean;\n}\n\nasync function updateConfigAsync<T>(\n mutate: (\n config: UserPreferences,\n ) => Promise<AsyncConfigUpdate<T>> | AsyncConfigUpdate<T>,\n): Promise<T> {\n const configPath = getConfigPath();\n return withRegistryWriteLock(async () => {\n const config = readJsonFile(configPath) ?? {};\n const update = await mutate(config);\n if (update.write) writeConfig(config);\n return update.result;\n }, { lockPath: `${configPath}.lock` });\n}\n\nexport function loadPreferences(): UserPreferences {\n const config = readConfig();\n return {\n lastModel: config.lastModel,\n lastProvider: config.lastProvider,\n recentModelsByProvider: config.recentModelsByProvider,\n favoriteModels: config.favoriteModels,\n modelAliases: config.modelAliases,\n modelContextModes: config.modelContextModes,\n claudeBridgeMode: config.claudeBridgeMode,\n serverBridgeMode: config.serverBridgeMode,\n appPathOverrides: config.appPathOverrides,\n localPatchesEnabled: config.localPatchesEnabled,\n recentLaunchFolders: config.recentLaunchFolders,\n server: config.server,\n };\n}\n\nexport function savePreferences(prefs: Partial<Pick<UserPreferences, 'lastModel' | 'lastProvider' | 'recentModelsByProvider' | 'favoriteModels' | 'modelAliases' | 'modelContextModes' | 'claudeBridgeMode' | 'serverBridgeMode' | 'appPathOverrides' | 'localPatchesEnabled' | 'recentLaunchFolders'>>): void {\n updateConfig(config => {\n if (prefs.lastModel !== undefined) config.lastModel = prefs.lastModel;\n if (prefs.lastProvider !== undefined) config.lastProvider = prefs.lastProvider;\n if (prefs.recentModelsByProvider !== undefined) config.recentModelsByProvider = prefs.recentModelsByProvider;\n if (prefs.favoriteModels !== undefined) config.favoriteModels = prefs.favoriteModels;\n if (prefs.modelAliases !== undefined) config.modelAliases = prefs.modelAliases;\n if (prefs.modelContextModes !== undefined) config.modelContextModes = prefs.modelContextModes;\n if (prefs.claudeBridgeMode !== undefined) config.claudeBridgeMode = prefs.claudeBridgeMode;\n if (prefs.serverBridgeMode !== undefined) config.serverBridgeMode = prefs.serverBridgeMode;\n if (prefs.appPathOverrides !== undefined) config.appPathOverrides = prefs.appPathOverrides;\n if (prefs.localPatchesEnabled !== undefined) config.localPatchesEnabled = prefs.localPatchesEnabled;\n if (prefs.recentLaunchFolders !== undefined) config.recentLaunchFolders = prefs.recentLaunchFolders;\n });\n}\n\nexport function getAppPathOverride(appId: string): string | undefined {\n const value = loadPreferences().appPathOverrides?.[appId];\n return typeof value === 'string' && value.trim() ? value : undefined;\n}\n\nexport function setAppPathOverride(appId: string, path: string | null): Record<string, string> {\n return updateConfig(config => {\n const next = { ...(config.appPathOverrides ?? {}) };\n const trimmed = path?.trim() ?? '';\n if (trimmed) next[appId] = trimmed;\n else delete next[appId];\n config.appPathOverrides = next;\n if (Object.keys(next).length === 0) delete config.appPathOverrides;\n return next;\n });\n}\n\n/**\n * Resolve the bridge mode for a command. An explicit flag applies to that run only —\n * it is persisted as the command's default ONLY when the caller opts in (--save-mode).\n * With no flag, the saved per-command default applies; with no saved default, proxy.\n */\nexport function resolveBridgeMode(\n command: 'claude' | 'server',\n explicit: import('./types.js').BridgeMode | undefined,\n opts: { persist?: boolean } = {},\n): import('./types.js').BridgeMode {\n const key = command === 'claude' ? 'claudeBridgeMode' : 'serverBridgeMode';\n if (explicit) {\n if (opts.persist === true) savePreferences({ [key]: explicit });\n return explicit;\n }\n return loadPreferences()[key] ?? 'proxy';\n}\n\nconst MAX_RECENT_MODELS = 3;\nconst MAX_RECENT_LAUNCH_FOLDERS = 6;\n\nexport function recordLaunchFolder(folder: string): string[] {\n const trimmed = folder.trim();\n if (!trimmed) return loadPreferences().recentLaunchFolders ?? [];\n return updateConfig(config => {\n const prev = config.recentLaunchFolders ?? [];\n const next = [trimmed, ...prev.filter(path => path !== trimmed)].slice(0, MAX_RECENT_LAUNCH_FOLDERS);\n config.recentLaunchFolders = next;\n return next;\n });\n}\n\nexport function recordLaunchSelection(\n _agent: 'claude',\n providerId: string,\n modelId: string,\n prefs: UserPreferences,\n): void {\n const prevRecent = prefs.recentModelsByProvider?.[providerId] ?? [];\n const updatedRecent = [modelId, ...prevRecent.filter(id => id !== modelId)].slice(0, MAX_RECENT_MODELS);\n savePreferences({\n lastProvider: providerId,\n lastModel: modelId,\n recentModelsByProvider: { ...prefs.recentModelsByProvider, [providerId]: updatedRecent },\n });\n}\n\nconst SERVER_PASSWORD_SERVICE = 'clodex-server-password';\nconst SERVER_PASSWORD_ACCOUNT = 'server-password';\n\nasync function getServerPasswordKeyring(): Promise<any | null> {\n try {\n const { Entry } = await import('@napi-rs/keyring');\n return new Entry(SERVER_PASSWORD_SERVICE, SERVER_PASSWORD_ACCOUNT);\n } catch {\n return null;\n }\n}\n\nexport async function getSavedServerPassword(): Promise<string | null> {\n const keyring = await getServerPasswordKeyring();\n if (!keyring) return readConfig().server?.savedPassword ?? null;\n\n const savedPassword = await updateConfigAsync(async config => {\n const server = config.server;\n const password = server?.savedPassword;\n if (!password) return { result: null, write: false };\n try {\n await keyring.setPassword(password);\n delete server.savedPassword;\n if (Object.keys(server).length === 0) delete config.server;\n return { result: password, write: true };\n } catch {\n // Fallback: keep in config.json if keyring fails\n return { result: password, write: false };\n }\n });\n if (savedPassword) return savedPassword;\n\n try {\n return await keyring.getPassword();\n } catch {\n return null;\n }\n}\n\nexport async function setSavedServerPassword(password: string): Promise<void> {\n const keyring = await getServerPasswordKeyring();\n if (keyring) {\n try {\n await keyring.setPassword(password);\n return;\n } catch {\n // Fallback\n }\n }\n await updateConfigAsync(config => {\n config.server = {\n ...(config.server ?? {}),\n savedPassword: password,\n };\n return { result: undefined, write: true };\n });\n}\n\nexport async function clearSavedServerPassword(): Promise<void> {\n const keyring = await getServerPasswordKeyring();\n if (keyring) {\n try {\n await keyring.deletePassword();\n } catch {\n // Ignore\n }\n }\n await updateConfigAsync(config => {\n if (!config.server) return { result: undefined, write: false };\n delete config.server.savedPassword;\n if (Object.keys(config.server).length === 0) delete config.server;\n return { result: undefined, write: true };\n });\n}\n\nexport function getServerExposedProviders(): string[] | null {\n const list = readConfig().server?.exposedProviders;\n return list && list.length > 0 ? list : null;\n}\n\nexport function setServerExposedProviders(providerIds: string[]): void {\n updateConfig(config => {\n config.server = {\n ...(config.server ?? {}),\n exposedProviders: providerIds,\n };\n });\n}\n\nexport function getServerMaskGatewayIds(): boolean {\n return readConfig().server?.maskGatewayIds ?? true;\n}\n\nexport function setServerMaskGatewayIds(mask: boolean): void {\n updateConfig(config => {\n config.server = {\n ...(config.server ?? {}),\n maskGatewayIds: mask,\n };\n });\n}\n\nexport function getServerFavoritesOnly(): boolean {\n return readConfig().server?.favoritesOnly ?? false;\n}\n\nexport function setServerFavoritesOnly(favoritesOnly: boolean): void {\n updateConfig(config => {\n config.server = {\n ...(config.server ?? {}),\n favoritesOnly,\n };\n });\n}\n\nexport function getServerListenMode(): 'local' | 'network' {\n return readConfig().server?.listenMode === 'network' ? 'network' : 'local';\n}\n\nexport function setServerListenMode(listenMode: 'local' | 'network'): void {\n updateConfig(config => {\n config.server = {\n ...(config.server ?? {}),\n listenMode,\n };\n });\n}\n","// src/claude-binary.ts\n//\n// Claude Code binary discovery and version probing, kept OUT of launch.ts so the\n// `clodex-claude` wrapper can import discovery without pulling in launchClaude\n// and everything the launch path needs. The wrapper runs for every spawned agent\n// process, so its import graph is an invariant (see CLAUDE.md), and tsup places\n// anything both entry points touch in the shared chunk they both load.\nimport { execFileSync, execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { getAppPathOverride } from './config.js';\nimport { findBinaryOnPath } from './binary-lookup.js';\n\nconst isWindows = process.platform === 'win32';\n\nconst FALLBACK_PATHS = isWindows\n ? [\n join(process.env['APPDATA'] ?? homedir(), 'npm', 'claude.cmd'),\n join(process.env['APPDATA'] ?? homedir(), 'npm', 'claude'),\n join(homedir(), 'AppData', 'Roaming', 'npm', 'claude.cmd'),\n ]\n : [\n join(homedir(), '.local', 'bin', 'claude'),\n join(homedir(), '.npm', 'bin', 'claude'),\n '/usr/local/bin/claude',\n '/opt/homebrew/bin/claude',\n ];\n\nexport function findClaudeBinary(): string | null {\n const environmentOverride = process.env['CLODEX_CLAUDE_PATH'];\n if (environmentOverride?.trim()) {\n return existsSync(environmentOverride) ? environmentOverride : null;\n }\n\n const override = getAppPathOverride('claude');\n if (override) return existsSync(override) ? override : null;\n\n return findBinaryOnPath('claude', FALLBACK_PATHS);\n}\n\n/** Version reported when the installed claude cannot be probed. */\nconst FALLBACK_CLAUDE_VERSION = '2.1.183';\n\nconst VERSION_PROBE_TIMEOUT_MS = 15_000;\n\n/**\n * Probe `--version` of ONE SPECIFIC claude binary, returning null when it cannot\n * be executed or prints nothing version-shaped.\n *\n * Callers that key destructive state on the answer — the patcher names its\n * pristine backups after this version and restores them over the live install —\n * MUST use this and fail loudly on null. A guessed version tags a backup with\n * bytes it does not contain, and restoring it downgrades the user's Claude Code.\n */\nexport function getClaudeVersionForBinary(binaryPath: string): string | null {\n try {\n // A JavaScript entry point — an npm install's `cli.js` — is not an\n // executable. POSIX ran it anyway via its `#!` line, but only while the file\n // kept its executable bit, and Windows cannot run it at all (cmd would hand\n // a `.js` to the Windows Script Host). Run it with the Node already running\n // clodex instead; the version still comes from THIS exact file, which is the\n // invariant that matters.\n // POSIX: exec the file directly so a path containing spaces still works.\n // Windows: `claude` is often a .cmd shim, which needs a shell — keep the\n // quoted shell invocation there.\n const result = /\\.[cm]?js$/i.test(binaryPath)\n ? execFileSync(process.execPath, [binaryPath, '--version'], {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: VERSION_PROBE_TIMEOUT_MS,\n })\n : isWindows\n ? execSync(`\"${binaryPath}\" --version`, {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: VERSION_PROBE_TIMEOUT_MS,\n })\n : execFileSync(binaryPath, ['--version'], {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: VERSION_PROBE_TIMEOUT_MS,\n });\n return result.match(/(\\d+\\.\\d+\\.\\d+)/)?.[1] ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Version of the claude found on PATH (or via the configured overrides), with a\n * known-good fallback. This is a best-effort string for request metadata — it is\n * NOT the version of any particular file, because `findClaudeBinary()` can\n * return a wrapper shim that differs from the real installation.\n */\nexport function getInstalledClaudeVersion(): string {\n const claudePath = findClaudeBinary();\n if (!claudePath) return FALLBACK_CLAUDE_VERSION;\n return getClaudeVersionForBinary(claudePath) ?? FALLBACK_CLAUDE_VERSION;\n}\n","import { execFileSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\n\nexport interface FindBinaryOnPathOptions {\n verifyWhichResult?: boolean;\n isWindows?: boolean;\n exists?: (path: string) => boolean;\n runWhich?: (name: string, isWindows: boolean) => string;\n}\n\nexport function findBinaryOnPath(\n name: string,\n fallbackPaths: string[],\n options: FindBinaryOnPathOptions = {},\n): string | null {\n const isWindows = options.isWindows ?? process.platform === 'win32';\n const exists = options.exists ?? existsSync;\n // argv form, never a shell string — the binary name must not be shell-interpretable\n // (defense-in-depth originally added in d887984, must survive refactors).\n const runWhich = options.runWhich ?? ((binary, win) =>\n execFileSync(win ? 'where.exe' : 'which', [binary], {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }));\n\n try {\n const lines = runWhich(name, isWindows)\n .trim()\n .split('\\n')\n .map(line => line.trim())\n .filter(Boolean);\n const path = (isWindows ? lines.find(line => line.toLowerCase().endsWith('.cmd')) : null)\n ?? lines[0];\n if (path && (!options.verifyWhichResult || exists(path))) return path;\n } catch {\n // Fall through to fallback paths.\n }\n\n for (const path of fallbackPaths) {\n if (exists(path)) return path;\n }\n return null;\n}\n","import { connect, type AddressInfo, type Server } from 'node:net';\nimport { setTimeout as delay } from 'node:timers/promises';\n\nconst LISTENER_READY_TIMEOUT_MS = 1_000;\nconst LISTENER_READY_RETRY_MS = 5;\nconst TCP_PROBE_TIMEOUT_MS = 50;\n\nfunction connectHost(address: string): string {\n if (address === '0.0.0.0') return '127.0.0.1';\n if (address === '::') return '::1';\n return address;\n}\n\n/** Return a reachable host formatted for use in an HTTP URL. */\nexport function tcpListenerUrlHost(address: string): string {\n const host = connectHost(address);\n return host.includes(':') ? `[${host}]` : host;\n}\n\ntype TcpListenerProbeResult = 'ready' | 'timeout' | 'unreachable';\n\nfunction probeTcpListener(\n host: string,\n port: number,\n timeoutMs: number,\n): Promise<TcpListenerProbeResult> {\n return new Promise(resolve => {\n const socket = connect({ host, port });\n let settled = false;\n const finish = (result: TcpListenerProbeResult) => {\n if (settled) return;\n settled = true;\n socket.destroy();\n resolve(result);\n };\n socket.once('connect', () => finish('ready'));\n socket.once('error', error => {\n finish(\n (error as NodeJS.ErrnoException).code === 'ETIMEDOUT'\n ? 'timeout'\n : 'unreachable',\n );\n });\n socket.setTimeout(timeoutMs, () => finish('timeout'));\n });\n}\n\ninterface TcpListenerWaitOptions {\n now?: () => number;\n probe?: (\n host: string,\n port: number,\n timeoutMs: number,\n ) => Promise<TcpListenerProbeResult>;\n retryFailure?: (result: Exclude<TcpListenerProbeResult, 'ready'>) => boolean;\n delay?: (ms: number) => Promise<void>;\n}\n\n/**\n * Probe every candidate once per round and return the first reachable\n * candidate in caller-provided priority order. All retry rounds share one\n * overall deadline.\n */\nexport async function waitForTcpListenerCandidate<T extends { port: number }>(\n host: string,\n candidates: readonly T[],\n timeoutMs = LISTENER_READY_TIMEOUT_MS,\n options: TcpListenerWaitOptions = {},\n): Promise<T | null> {\n if (candidates.length === 0) return null;\n\n const now = options.now ?? Date.now;\n const probe = options.probe ?? probeTcpListener;\n const retryFailure = options.retryFailure ?? (() => true);\n const wait = options.delay ?? (ms => delay(ms));\n const deadline = now() + timeoutMs;\n let pendingCandidates = [...candidates];\n\n do {\n const remaining = Math.max(1, deadline - now());\n const results = await Promise.all(\n pendingCandidates.map(candidate => probe(\n host,\n candidate.port,\n Math.min(remaining, TCP_PROBE_TIMEOUT_MS),\n )),\n );\n const readyIndex = results.findIndex(result => result === 'ready');\n if (readyIndex >= 0) return pendingCandidates[readyIndex] ?? null;\n\n pendingCandidates = pendingCandidates.filter((_candidate, index) => {\n const result = results[index];\n return result !== undefined && result !== 'ready' && retryFailure(result);\n });\n if (pendingCandidates.length === 0) return null;\n\n const retryDelay = Math.min(LISTENER_READY_RETRY_MS, deadline - now());\n if (retryDelay <= 0) return null;\n await wait(retryDelay);\n } while (now() < deadline);\n\n return null;\n}\n\n/** Retry a TCP probe until the listener answers or the deadline expires. */\nexport async function waitForTcpListener(\n host: string,\n port: number,\n timeoutMs = LISTENER_READY_TIMEOUT_MS,\n options: TcpListenerWaitOptions = {},\n): Promise<boolean> {\n return (await waitForTcpListenerCandidate(host, [{ port }], timeoutMs, options)) !== null;\n}\n\nasync function closeAfterReadinessFailure(server: Server): Promise<void> {\n if (!server.listening) return;\n await new Promise<void>(resolve => server.close(() => resolve()));\n}\n\n/** Bind a TCP server and wait until the bound socket accepts connections. */\nexport async function listenTcpServer(\n server: Server,\n port: number,\n host: string,\n): Promise<AddressInfo> {\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => server.off('error', onError);\n const onError = (error: Error) => {\n cleanup();\n reject(error);\n };\n server.once('error', onError);\n try {\n server.listen(port, host, () => {\n cleanup();\n resolve();\n });\n } catch (error) {\n cleanup();\n reject(error);\n }\n });\n\n const address = server.address();\n if (!address || typeof address === 'string') {\n await closeAfterReadinessFailure(server);\n throw new Error('TCP server did not bind to a network address');\n }\n\n const probeHost = connectHost(address.address);\n if (await waitForTcpListener(probeHost, address.port)) return address;\n\n await closeAfterReadinessFailure(server);\n throw new Error(\n `TCP listener did not become reachable within ${LISTENER_READY_TIMEOUT_MS}ms: `\n + `${probeHost}:${address.port}`,\n );\n}\n","// src/server-runtime.ts\n//\n// Runtime-state advertisement for the standalone `clodex server` command.\n// Each registering server ADDS its own record (keyed by pid) to\n// ~/.clodex/server-runtime.json on startup and removes ONLY its own record on\n// graceful shutdown, so other processes (notably the `clodex-claude` wrapper\n// bin) can discover every running server's mode, port, and CA path without any\n// hardcoding. The file holds an ARRAY of records; the legacy single-object\n// shape (pre multi-server) is tolerated on read as a one-element list. Stale\n// detection is the READER's job: a crashed server leaves its record behind, so\n// readers must validate pid liveness before trusting it. Writers additionally\n// prune dead-pid records while they hold the write lock.\n//\n// Concurrency: read-modify-write cycles are serialized by a short-lived pid\n// lock (~/.clodex/server-runtime.lock — same pattern as the patcher's\n// patch.lock: O_EXCL create, pid + staleness, ESRCH liveness) and the file is\n// replaced via write-temp-then-rename so a reader never sees a torn write. A\n// crashed lock holder cannot deadlock registration: the lock goes stale after\n// 10 seconds or when its pid dies, and after a brief bounded wait a writer\n// proceeds lockless (best-effort — same exposure as the old single-slot write).\n//\n// NOTE: only the standalone `clodex server` command writes this file. The\n// per-session MITM proxy spawned by `clodex claude --proxy` is private to that\n// session and must NOT advertise itself here. `clodex server --no-discovery`\n// (or CLODEX_NO_DISCOVERY=1) also opts a server out of registration entirely.\n\nimport {\n closeSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n rmSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { getAppHome } from './paths.js';\n\nexport interface ServerRuntimeState {\n mode: 'endpoint' | 'proxy';\n port: number;\n pid: number;\n /** Proxy mode only: absolute path to the CA bundle a client must trust. */\n caPath?: string;\n startedAt: string;\n}\n\ninterface HomeEnv {\n HOME?: string;\n CLODEX_HOME?: string;\n USERPROFILE?: string;\n}\n\nexport function getServerRuntimePath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'server-runtime.json');\n}\n\nexport function getServerRuntimeLockPath(env: HomeEnv = process.env): string {\n return join(getAppHome(env), 'server-runtime.lock');\n}\n\n/** `--no-discovery` flag, with CLODEX_NO_DISCOVERY=1 as the env fallback. */\nexport function isDiscoveryDisabled(\n flag: boolean | undefined,\n env: { CLODEX_NO_DISCOVERY?: string } = process.env,\n): boolean {\n if (flag !== undefined) return flag;\n const raw = env.CLODEX_NO_DISCOVERY?.trim().toLowerCase();\n return raw === '1' || raw === 'true';\n}\n\nfunction isPort(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 1 && value <= 65535;\n}\n\n/** Validate one runtime record. Returns null for anything malformed. */\nexport function parseServerRuntimeRecord(value: unknown): ServerRuntimeState | null {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return null;\n const record = value as Record<string, unknown>;\n\n const mode = record['mode'];\n if (mode !== 'endpoint' && mode !== 'proxy') return null;\n if (!isPort(record['port'])) return null;\n const pid = record['pid'];\n if (typeof pid !== 'number' || !Number.isInteger(pid) || pid <= 0) return null;\n const startedAt = typeof record['startedAt'] === 'string' ? record['startedAt'] : '';\n\n const caPath = record['caPath'];\n if (mode === 'proxy') {\n // A proxy-mode server without a CA path is unusable to clients — treat as invalid.\n if (typeof caPath !== 'string' || !caPath.trim()) return null;\n return { mode, port: record['port'], pid, caPath, startedAt };\n }\n return { mode, port: record['port'], pid, startedAt };\n}\n\n/**\n * Parse a raw server-runtime.json payload into a list of records. Tolerates\n * BOTH shapes: the current array of records and the legacy single object\n * (wrapped as a one-element list). Malformed input or records are skipped —\n * never throws.\n */\nexport function parseServerRuntimeStates(raw: string): ServerRuntimeState[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return [];\n }\n const items = Array.isArray(parsed) ? parsed : [parsed];\n const states: ServerRuntimeState[] = [];\n for (const item of items) {\n const state = parseServerRuntimeRecord(item);\n if (state) states.push(state);\n }\n return states;\n}\n\n/** kill(pid, 0) liveness probe: EPERM still means the process exists. */\nexport function isPidAlive(\n pid: number,\n kill: (pid: number, signal: number) => unknown = process.kill.bind(process),\n): boolean {\n try {\n kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException)?.code === 'EPERM';\n }\n}\n\n// ── Write lock (pid + staleness, patcher pattern) ───────────────────────────\n\nconst RUNTIME_LOCK_STALE_MS = 10_000;\nconst RUNTIME_LOCK_WAIT_MS = 500;\nconst RUNTIME_LOCK_RETRY_MS = 25;\n\ninterface RuntimeLockContent {\n pid: number;\n startedAt: number;\n}\n\nfunction tryAcquireRuntimeLock(\n lockPath: string,\n opts: { now?: number; isAlive?: (pid: number) => boolean } = {},\n): (() => void) | null {\n const now = opts.now ?? Date.now();\n const alive = opts.isAlive ?? isPidAlive;\n mkdirSync(dirname(lockPath), { recursive: true, mode: 0o700 });\n\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n const fd = openSync(lockPath, 'wx');\n const content: RuntimeLockContent = { pid: process.pid, startedAt: now };\n writeFileSync(fd, JSON.stringify(content));\n closeSync(fd);\n return () => {\n try {\n unlinkSync(lockPath);\n } catch {\n // already gone\n }\n };\n } catch {\n // Lock exists — check staleness.\n let stale = false;\n try {\n const existing = JSON.parse(readFileSync(lockPath, 'utf8')) as RuntimeLockContent;\n stale = !existing.pid\n || !alive(existing.pid)\n || (typeof existing.startedAt === 'number' && now - existing.startedAt > RUNTIME_LOCK_STALE_MS);\n } catch {\n stale = true; // unreadable lock file → stale\n }\n if (!stale) return null;\n try {\n unlinkSync(lockPath);\n } catch {\n // raced with the owner's cleanup — retry loop handles it\n }\n }\n }\n return null;\n}\n\nfunction sleepSync(ms: number): void {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\n/**\n * Run a read-modify-write mutation under the runtime lock. The lock is only\n * ever held for a few milliseconds, so after a short bounded wait the mutation\n * proceeds WITHOUT the lock rather than dropping a registration — the atomic\n * rename still prevents torn files; the worst case is a lost concurrent\n * update, which is no worse than the old single-slot behavior.\n */\nfunction withRuntimeWriteLock(env: HomeEnv, mutate: () => void): void {\n const lockPath = getServerRuntimeLockPath(env);\n let release: (() => void) | null = null;\n const deadline = Date.now() + RUNTIME_LOCK_WAIT_MS;\n for (;;) {\n release = tryAcquireRuntimeLock(lockPath);\n if (release || Date.now() >= deadline) break;\n sleepSync(RUNTIME_LOCK_RETRY_MS);\n }\n try {\n mutate();\n } finally {\n release?.();\n }\n}\n\nfunction readAllRecords(env: HomeEnv): ServerRuntimeState[] {\n let raw: string;\n try {\n raw = readFileSync(getServerRuntimePath(env), 'utf8');\n } catch {\n return [];\n }\n return parseServerRuntimeStates(raw);\n}\n\n/** Atomic replace: write a temp file in the same directory, then rename over. */\nfunction atomicWriteRecords(path: string, records: ServerRuntimeState[]): void {\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n const tmpPath = `${path}.${process.pid}.tmp`;\n writeFileSync(tmpPath, `${JSON.stringify(records, null, 2)}\\n`, { encoding: 'utf8', mode: 0o600 });\n renameSync(tmpPath, path);\n}\n\nexport interface RuntimeMutateOptions {\n isAlive?: (pid: number) => boolean;\n}\n\n/**\n * Add or update this server's own record (keyed by pid), pruning records whose\n * pids are dead. Best-effort — a state-file failure must never take the server\n * down.\n */\nexport function registerServerRuntimeState(\n state: ServerRuntimeState,\n env: HomeEnv = process.env,\n options: RuntimeMutateOptions = {},\n): void {\n const alive = options.isAlive ?? isPidAlive;\n try {\n withRuntimeWriteLock(env, () => {\n const records = readAllRecords(env).filter(\n record => record.pid !== state.pid && alive(record.pid),\n );\n records.push(state);\n atomicWriteRecords(getServerRuntimePath(env), records);\n });\n } catch {\n // Discovery is optional; the server itself keeps running.\n }\n}\n\n/**\n * Remove ONLY this server's own record (by pid) on graceful shutdown, pruning\n * dead-pid records along the way. Missing file/record is fine. When no live\n * records remain the file is removed entirely.\n */\nexport function unregisterServerRuntimeState(\n pid: number = process.pid,\n env: HomeEnv = process.env,\n options: RuntimeMutateOptions = {},\n): void {\n const alive = options.isAlive ?? isPidAlive;\n try {\n withRuntimeWriteLock(env, () => {\n const records = readAllRecords(env).filter(\n record => record.pid !== pid && alive(record.pid),\n );\n if (records.length === 0) {\n rmSync(getServerRuntimePath(env), { force: true });\n } else {\n atomicWriteRecords(getServerRuntimePath(env), records);\n }\n });\n } catch {\n // Stale records are handled by readers via pid liveness.\n }\n}\n\nexport interface ReadServerRuntimeOptions {\n isAlive?: (pid: number) => boolean;\n}\n\n/**\n * Read every advertised server record whose process is still alive. Missing or\n * malformed files yield an empty list. Read-only: stale records are ignored\n * here and physically pruned on the next registration/unregistration.\n */\nexport function readLiveServerRuntimeStates(\n env: HomeEnv = process.env,\n options: ReadServerRuntimeOptions = {},\n): ServerRuntimeState[] {\n const alive = options.isAlive ?? isPidAlive;\n return readAllRecords(env).filter(state => alive(state.pid));\n}\n\n/**\n * Wrapper selection policy: order candidate servers by preference —\n * 1. proxy mode before endpoint mode (bridging through the MITM proxy keeps\n * Claude Code's own Anthropic auth, the recommended setup);\n * 2. within a mode, newest startedAt first.\n * If only an endpoint server is live it is used; with no live server the\n * wrapper launches claude untouched (both handled by the caller).\n */\nexport function orderWrapperServerCandidates(records: ServerRuntimeState[]): ServerRuntimeState[] {\n return [...records].sort((a, b) => {\n if (a.mode !== b.mode) return a.mode === 'proxy' ? -1 : 1;\n return (Date.parse(b.startedAt) || 0) - (Date.parse(a.startedAt) || 0);\n });\n}\n\n/**\n * Read the single preferred live server (selection policy above), or null when\n * none is advertised/alive.\n */\nexport function readLiveServerRuntimeState(\n env: HomeEnv = process.env,\n options: ReadServerRuntimeOptions = {},\n): ServerRuntimeState | null {\n return orderWrapperServerCandidates(readLiveServerRuntimeStates(env, options))[0] ?? null;\n}\n","export const PROXY_ENV_VARS = [\n 'HTTPS_PROXY',\n 'HTTP_PROXY',\n 'https_proxy',\n 'http_proxy',\n] as const;\n\nexport const CHILD_NETWORK_ENV_VARS = [\n ...PROXY_ENV_VARS,\n 'NO_PROXY',\n 'no_proxy',\n 'NODE_EXTRA_CA_CERTS',\n] as const;\n\nexport const NETWORK_ENV_CONTRACT_VAR = 'CLAUDE_CODE_CLODEX_NETWORK_ENV';\n\ntype ChildNetworkEnvVar = typeof CHILD_NETWORK_ENV_VARS[number];\ntype NetworkEnvValue = string | null;\n\ninterface NetworkEnvContract {\n version: 1;\n original: Partial<Record<ChildNetworkEnvVar, NetworkEnvValue>>;\n injected: Partial<Record<ChildNetworkEnvVar, NetworkEnvValue>>;\n}\n\nconst childNetworkEnvVarSet = new Set<string>(CHILD_NETWORK_ENV_VARS);\n\nfunction networkEnvValue(env: NodeJS.ProcessEnv, name: ChildNetworkEnvVar): NetworkEnvValue {\n return typeof env[name] === 'string' ? env[name]! : null;\n}\n\nfunction isNetworkValueRecord(value: unknown): value is Record<string, NetworkEnvValue> {\n return Boolean(value && typeof value === 'object' && !Array.isArray(value)\n && Object.entries(value).every(([key, entry]) =>\n childNetworkEnvVarSet.has(key) && (typeof entry === 'string' || entry === null)));\n}\n\nfunction parseNetworkEnvContract(value: string | undefined): NetworkEnvContract | undefined {\n if (value === undefined) return undefined;\n try {\n const parsed: unknown = JSON.parse(value);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return undefined;\n const candidate = parsed as Partial<NetworkEnvContract>;\n const original = candidate.original;\n const injected = candidate.injected;\n if (candidate.version !== 1\n || !isNetworkValueRecord(original)\n || !isNetworkValueRecord(injected)) {\n return undefined;\n }\n if (!Object.keys(original).every(key => key in injected)\n || !Object.keys(injected).every(key => key in original)) {\n return undefined;\n }\n return { version: 1, original, injected };\n } catch {\n return undefined;\n }\n}\n\nfunction setNetworkEnvValue(\n env: NodeJS.ProcessEnv,\n name: ChildNetworkEnvVar,\n value: NetworkEnvValue,\n): void {\n if (value === null) delete env[name];\n else env[name] = value;\n}\n\n/**\n * Recover the external network environment only where the inherited values\n * still equal a prior Clodex injection. Values changed by settings or another\n * wrapper layer remain authoritative.\n */\nexport function networkEnvBaseline(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...baseEnv };\n const contract = parseNetworkEnvContract(baseEnv[NETWORK_ENV_CONTRACT_VAR]);\n delete env[NETWORK_ENV_CONTRACT_VAR];\n if (!contract) return env;\n\n for (const name of CHILD_NETWORK_ENV_VARS) {\n if (!(name in contract.original) || !(name in contract.injected)) continue;\n if (networkEnvValue(baseEnv, name) !== contract.injected[name]) continue;\n setNetworkEnvValue(env, name, contract.original[name] ?? null);\n }\n return env;\n}\n\n/**\n * Attach a compare-before-revert contract for the network values changed\n * between an external baseline and the child environment Clodex will launch.\n */\nexport function recordNetworkEnvMutation(\n baseline: NodeJS.ProcessEnv,\n injectedEnv: NodeJS.ProcessEnv,\n): void {\n const original: NetworkEnvContract['original'] = {};\n const injected: NetworkEnvContract['injected'] = {};\n for (const name of CHILD_NETWORK_ENV_VARS) {\n const before = networkEnvValue(baseline, name);\n const after = networkEnvValue(injectedEnv, name);\n if (before === after) continue;\n original[name] = before;\n injected[name] = after;\n }\n if (Object.keys(original).length === 0) {\n delete injectedEnv[NETWORK_ENV_CONTRACT_VAR];\n return;\n }\n injectedEnv[NETWORK_ENV_CONTRACT_VAR] = JSON.stringify({\n version: 1,\n original,\n injected,\n } satisfies NetworkEnvContract);\n}\n","// src/wrapper-env.ts\n//\n// Pure env computation for the `clodex-claude` wrapper bin. Given the process\n// env and a live `clodex server` runtime state (or null), returns the env to\n// launch the Claude Code binary with. Kept dependency-free so the wrapper\n// stays tiny and fast — it runs for every Claude-Code-spawned agent process.\n\nimport type { ServerRuntimeState } from './server-runtime.js';\nimport {\n networkEnvBaseline,\n PROXY_ENV_VARS,\n recordNetworkEnvMutation,\n} from './network-env.js';\n\nexport const REQUIRE_SERVER_ENV = 'CLODEX_REQUIRE_SERVER';\n\nexport function removeAnthropicProxyBypass(env: NodeJS.ProcessEnv): void {\n const noProxyValues = [env['NO_PROXY'], env['no_proxy']]\n .filter((value): value is string => value !== undefined);\n if (noProxyValues.length === 0) return;\n\n const filtered = [...new Set(noProxyValues\n .flatMap(value => value.split(','))\n .map(value => value.trim())\n .filter(Boolean)\n .filter(value => {\n const entry = value.toLowerCase().replace(/^https?:\\/\\//, '');\n const host = entry.replace(/:\\d+$/, '');\n if (host === '*') return false;\n const suffix = host.startsWith('*.') ? host.slice(1) : host;\n const bypassesAnthropic = suffix.startsWith('.')\n ? 'api.anthropic.com'.endsWith(suffix)\n : 'api.anthropic.com' === suffix || 'api.anthropic.com'.endsWith(`.${suffix}`);\n return !bypassesAnthropic;\n }))]\n .join(',');\n if (filtered) {\n env['NO_PROXY'] = filtered;\n env['no_proxy'] = filtered;\n } else {\n delete env['NO_PROXY'];\n delete env['no_proxy'];\n }\n}\n\n/**\n * Any non-empty key satisfies the local endpoint gateway (`isAuthorized`\n * accepts everything when no server password is set, i.e. local listen mode).\n */\nexport const LOCAL_GATEWAY_API_KEY = 'clodex-local';\n\nexport function wrapperRequiresServer(env: NodeJS.ProcessEnv): boolean {\n return env[REQUIRE_SERVER_ENV] === '1';\n}\n\nexport function computeWrapperEnv(\n baseEnv: NodeJS.ProcessEnv,\n state: ServerRuntimeState | null,\n): NodeJS.ProcessEnv {\n // No live server: launch claude completely untouched — a down server must\n // never break launching claude.\n if (!state) return { ...baseEnv };\n\n const baseline = networkEnvBaseline(baseEnv);\n const env: NodeJS.ProcessEnv = { ...baseline };\n\n if (state.mode === 'proxy') {\n // Selective MITM: claude keeps its own Anthropic credentials; the proxy\n // routes clodex:/alias models to OpenAI and passes everything else through.\n const proxyUrl = `http://127.0.0.1:${state.port}`;\n delete env['ANTHROPIC_BASE_URL'];\n for (const name of PROXY_ENV_VARS) env[name] = proxyUrl;\n if (state.caPath) env['NODE_EXTRA_CA_CERTS'] = state.caPath;\n removeAnthropicProxyBypass(env);\n recordNetworkEnvMutation(baseline, env);\n return env;\n }\n\n // Endpoint gateway: all traffic goes to the local Anthropic-format gateway.\n for (const name of PROXY_ENV_VARS) delete env[name];\n env['ANTHROPIC_BASE_URL'] = `http://127.0.0.1:${state.port}/anthropic`;\n env['ANTHROPIC_API_KEY'] = LOCAL_GATEWAY_API_KEY;\n recordNetworkEnvMutation(baseline, env);\n return env;\n}\n"],"mappings":"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","names":["randomUUID","closeSync","fsyncSync","mkdirSync","openSync","readFileSync","unlinkSync","dirname","join","join","mkdirSync","dirname","openSync","fsyncSync","closeSync","readFileSync","randomUUID","unlinkSync","randomUUID","readFileSync","renameSync","unlinkSync","readFileSync","randomUUID","renameSync","unlinkSync","execFileSync","existsSync","homedir","join","existsSync","isWindows","join","homedir","existsSync","execFileSync","closeSync","mkdirSync","openSync","readFileSync","renameSync","unlinkSync","writeFileSync","dirname","join","join","isPidAlive","mkdirSync","dirname","openSync","writeFileSync","closeSync","unlinkSync","readFileSync","sleepSync","renameSync"]}