opencode-switch-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/config/json-file.ts","../src/config/opencode-repository.ts","../src/config/switch-repository.ts","../src/prompt-client.ts","../src/types.ts","../src/services/model-service.ts","../src/services/vendor-service.ts","../src/bin.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\n\nimport pc from 'picocolors';\n\nimport { createJsonFileStore } from './config/json-file.js';\nimport { createOpencodeRepository } from './config/opencode-repository.js';\nimport { createSwitchRepository } from './config/switch-repository.js';\nimport { createPromptClient, type PromptClient } from './prompt-client.js';\nimport { createModelService } from './services/model-service.js';\nimport { createVendorService } from './services/vendor-service.js';\nimport { SUPPORTED_MODEL_TYPES, type SupportedModelType } from './types.js';\n\nexport interface ExecuteCliOptions {\n homeDir?: string;\n promptClient?: PromptClient;\n}\n\nexport interface RunCliOptions extends ExecuteCliOptions {\n stdout?: NodeJS.WriteStream;\n stderr?: NodeJS.WriteStream;\n}\n\nexport interface CliExecutionResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface VendorService {\n addVendor(vendor: {\n vendorName: string;\n npm: string;\n baseURL?: string;\n apiKey?: string;\n }): Promise<void>;\n listVendors(): Promise<Array<{ vendorName: string; managed: boolean; modelCount: number }>>;\n useVendor(vendorName: string): Promise<void>;\n removeVendor(vendorName: string): Promise<void>;\n}\n\nexport interface ModelService {\n addModel(model: {\n vendorName: string;\n modelType: SupportedModelType;\n realModel: string;\n apiKey?: string;\n baseURL?: string;\n }): Promise<void>;\n listModels(vendorName: string): Promise<Array<{\n modelType: string;\n realModel: string;\n activeKeyAlias: string | null;\n keyCount: number;\n }>>;\n addKey(input: {\n vendorName: string;\n modelType: SupportedModelType;\n keyAlias: string;\n apiKey: string;\n baseURL?: string;\n }): Promise<void>;\n listKeys(vendorName: string, modelType: SupportedModelType): Promise<Array<{\n keyAlias: string;\n isActive: boolean;\n }>>;\n useKey(vendorName: string, modelType: SupportedModelType, keyAlias: string): Promise<void>;\n removeKey(vendorName: string, modelType: SupportedModelType, keyAlias: string): Promise<void>;\n removeModel(vendorName: string, modelType: SupportedModelType): Promise<void>;\n}\n\ninterface ParsedFlags {\n [key: string]: string;\n}\n\ninterface CliContext {\n opencodeRepository: ReturnType<typeof createOpencodeRepository>;\n promptClient: PromptClient;\n switchRepository: ReturnType<typeof createSwitchRepository>;\n vendorService: VendorService;\n modelService: ModelService;\n}\n\nconst DEFAULT_VENDOR_NPM = '@ai-sdk/openai';\n\nfunction resolveConfigPaths(homeDir: string): { opencodeConfigPath: string; switchConfigPath: string } {\n const configDir = path.join(homeDir, '.config', 'opencode');\n\n return {\n opencodeConfigPath: path.join(configDir, 'opencode.json'),\n switchConfigPath: path.join(configDir, 'opencode-switch.json'),\n };\n}\n\nfunction parseFlags(args: string[]): ParsedFlags {\n const flags: ParsedFlags = {};\n\n for (let index = 0; index < args.length; index += 2) {\n const key = args[index];\n const value = args[index + 1];\n\n if (!key?.startsWith('--') || value === undefined) {\n throw new Error(`Invalid arguments: ${args.join(' ')}`);\n }\n\n flags[key.slice(2)] = value;\n }\n\n return flags;\n}\n\nfunction formatList(lines: string[]): string {\n return lines.length > 0 ? `${lines.join('\\n')}\\n` : '';\n}\n\nfunction formatVendorDashboard(input: {\n activeVendor: string | null;\n vendors: Array<{ vendorName: string; managed: boolean; modelCount: number }>;\n}): string {\n if (input.vendors.length === 0) {\n return [pc.bold('OpenCode Switch'), 'No vendors configured yet.'].join('\\n');\n }\n\n return [\n pc.bold('OpenCode Switch'),\n ...input.vendors.map((vendor, index) => {\n const marker = vendor.vendorName === input.activeVendor ? pc.cyan('>') : '-';\n const activeLabel = vendor.vendorName === input.activeVendor ? ` ${pc.green('[active]')}` : '';\n return `${marker} ${pc.bold(vendor.vendorName)}${activeLabel} models:${vendor.modelCount}`;\n }),\n ].join('\\n');\n}\n\nfunction createCliContext(homeDir: string, promptClient: PromptClient): CliContext {\n const { opencodeConfigPath, switchConfigPath } = resolveConfigPaths(homeDir);\n const jsonStore = createJsonFileStore();\n const opencodeRepository = createOpencodeRepository({ filePath: opencodeConfigPath, jsonStore });\n const switchRepository = createSwitchRepository({ filePath: switchConfigPath, jsonStore });\n\n return {\n opencodeRepository,\n promptClient,\n switchRepository,\n vendorService: createVendorService({ opencodeRepository, switchRepository }),\n modelService: createModelService({ opencodeRepository, switchRepository }),\n };\n}\n\nfunction stripSensitiveTemplateOptions(options: Record<string, unknown> | undefined) {\n if (!options) {\n return undefined;\n }\n\n const nextOptions = { ...options };\n delete nextOptions.apiKey;\n delete nextOptions.baseURL;\n\n return nextOptions;\n}\n\nfunction asSupportedModelType(modelType: string): SupportedModelType {\n if (!SUPPORTED_MODEL_TYPES.includes(modelType as SupportedModelType)) {\n throw new Error('Unsupported model type');\n }\n\n return modelType as SupportedModelType;\n}\n\nasync function selectVendor(context: CliContext, message: string): Promise<string> {\n const vendors = await context.vendorService.listVendors();\n\n if (vendors.length === 0) {\n throw new Error('No vendors configured');\n }\n\n return context.promptClient.select({\n message,\n options: vendors.map((vendor) => ({\n value: vendor.vendorName,\n label: vendor.vendorName,\n hint: `${vendor.modelCount} model(s)`,\n })),\n });\n}\n\nasync function selectModelForKeys(context: CliContext, vendorName: string): Promise<SupportedModelType> {\n while (true) {\n const models = await context.modelService.listModels(vendorName);\n const selected = await context.promptClient.select({\n message: `Pick a model for ${vendorName}`,\n options: [\n ...models.map((model) => ({\n value: model.modelType,\n label: model.modelType,\n hint: `${model.realModel}${model.activeKeyAlias ? ` | active:${model.activeKeyAlias}` : ''}`,\n })),\n {\n value: '__add_new_model__',\n label: 'Add new model',\n hint: 'Create a model before choosing keys',\n },\n ],\n });\n\n if (selected !== '__add_new_model__') {\n return asSupportedModelType(selected);\n }\n\n const modelType = asSupportedModelType(\n await context.promptClient.select({\n message: `Choose a model type for ${vendorName}`,\n options: SUPPORTED_MODEL_TYPES.map((supportedType) => ({\n value: supportedType,\n label: supportedType,\n })),\n }),\n );\n const realModel = await context.promptClient.text({\n message: `Real model id for ${vendorName}/${modelType}`,\n placeholder: modelType === 'gpt-5.4' ? 'duck/gpt-5.4' : 'google/gemini-2.5-flash',\n });\n\n await context.promptClient.withSpinner(`Adding ${vendorName}/${modelType}`, async () => {\n await context.modelService.addModel({ vendorName, modelType, realModel });\n });\n context.promptClient.note(`${vendorName}/${modelType} is ready.`, 'Model added');\n }\n}\n\nasync function runInteractiveRemoveVendor(context: CliContext): Promise<CliExecutionResult> {\n context.promptClient.intro('Remove vendor');\n const vendors = await context.vendorService.listVendors();\n\n if (vendors.length === 0) {\n return { exitCode: 1, stdout: '', stderr: 'No vendors configured\\n' };\n }\n\n const vendorName = await selectVendor(context, 'Choose a vendor to remove');\n const targetVendor = vendors.find((vendor) => vendor.vendorName === vendorName);\n const confirmed = await context.promptClient.confirm({\n message: `Delete ${vendorName} and its ${targetVendor?.modelCount ?? 0} model(s)?`,\n initialValue: false,\n });\n\n if (!confirmed) {\n context.promptClient.outro('No changes made.');\n return { exitCode: 0, stdout: 'Canceled removal\\n', stderr: '' };\n }\n\n await context.promptClient.withSpinner(`Removing ${vendorName}`, async () => {\n await context.vendorService.removeVendor(vendorName);\n });\n context.promptClient.outro(`${vendorName} removed.`);\n\n return {\n exitCode: 0,\n stdout: `Removed vendor ${vendorName}\\n`,\n stderr: '',\n };\n}\n\nasync function runInteractiveAddKey(context: CliContext): Promise<CliExecutionResult> {\n context.promptClient.intro('Add or switch key');\n const vendorName = await selectVendor(context, 'Choose a vendor');\n const modelType = await selectModelForKeys(context, vendorName);\n const keyAlias = await context.promptClient.text({\n message: `Remark for ${vendorName}/${modelType}`,\n placeholder: 'project-a',\n });\n const apiKey = await context.promptClient.password({\n message: `API key for ${vendorName}/${modelType}`,\n placeholder: 'sk-...',\n });\n\n await context.promptClient.withSpinner(`Saving key ${keyAlias}`, async () => {\n await context.modelService.addKey({ vendorName, modelType, keyAlias, apiKey });\n await context.modelService.useKey(vendorName, modelType, keyAlias);\n });\n context.promptClient.outro(`Active key for ${vendorName}/${modelType}: ${keyAlias}`);\n\n return {\n exitCode: 0,\n stdout: `Added key ${keyAlias} for ${vendorName}/${modelType}\\n`,\n stderr: '',\n };\n}\n\nasync function runInteractiveSwitchKey(context: CliContext): Promise<CliExecutionResult> {\n context.promptClient.intro('Switch key');\n const vendorName = await selectVendor(context, 'Choose a vendor');\n const models = await context.modelService.listModels(vendorName);\n\n if (models.length === 0) {\n return { exitCode: 1, stdout: '', stderr: `No models configured for ${vendorName}\\n` };\n }\n\n const modelType = asSupportedModelType(\n await context.promptClient.select({\n message: `Choose a model for ${vendorName}`,\n options: models.map((model) => ({\n value: model.modelType,\n label: model.modelType,\n hint: model.activeKeyAlias ? `active:${model.activeKeyAlias}` : `${model.keyCount} key(s)`,\n })),\n }),\n );\n const keys = await context.modelService.listKeys(vendorName, modelType);\n\n if (keys.length === 0) {\n return {\n exitCode: 1,\n stdout: '',\n stderr: `No keys configured for ${vendorName}/${modelType}\\n`,\n };\n }\n\n const keyAlias = await context.promptClient.select({\n message: `Choose the active key for ${vendorName}/${modelType}`,\n options: keys.map((key) => ({\n value: key.keyAlias,\n label: key.keyAlias,\n hint: key.isActive ? 'active' : 'saved key',\n })),\n });\n\n await context.promptClient.withSpinner(`Switching to ${keyAlias}`, async () => {\n await context.modelService.useKey(vendorName, modelType, keyAlias);\n });\n context.promptClient.outro(`Active key for ${vendorName}/${modelType}: ${keyAlias}`);\n\n return {\n exitCode: 0,\n stdout: `Using key ${keyAlias} for ${vendorName}/${modelType}\\n`,\n stderr: '',\n };\n}\n\nasync function runInteractiveRemoveKey(context: CliContext): Promise<CliExecutionResult> {\n context.promptClient.intro('Remove key');\n const vendorName = await selectVendor(context, 'Choose a vendor');\n const models = await context.modelService.listModels(vendorName);\n\n if (models.length === 0) {\n return { exitCode: 1, stdout: '', stderr: `No models configured for ${vendorName}\\n` };\n }\n\n const modelType = asSupportedModelType(\n await context.promptClient.select({\n message: `Choose a model for ${vendorName}`,\n options: models.map((model) => ({\n value: model.modelType,\n label: model.modelType,\n hint: `${model.keyCount} key(s)`,\n })),\n }),\n );\n const keys = await context.modelService.listKeys(vendorName, modelType);\n\n if (keys.length === 0) {\n return {\n exitCode: 1,\n stdout: '',\n stderr: `No keys configured for ${vendorName}/${modelType}\\n`,\n };\n }\n\n const keyAlias = await context.promptClient.select({\n message: `Choose a key to remove from ${vendorName}/${modelType}`,\n options: keys.map((key) => ({\n value: key.keyAlias,\n label: key.keyAlias,\n hint: key.isActive ? 'active' : 'saved key',\n })),\n });\n const confirmed = await context.promptClient.confirm({\n message: `Remove key ${keyAlias} from ${vendorName}/${modelType}?`,\n initialValue: false,\n });\n\n if (!confirmed) {\n context.promptClient.outro('No changes made.');\n return { exitCode: 0, stdout: 'Canceled removal\\n', stderr: '' };\n }\n\n await context.promptClient.withSpinner(`Removing ${keyAlias}`, async () => {\n await context.modelService.removeKey(vendorName, modelType, keyAlias);\n });\n context.promptClient.outro(`Removed ${keyAlias} from ${vendorName}/${modelType}.`);\n\n return {\n exitCode: 0,\n stdout: `Removed key ${keyAlias} from ${vendorName}/${modelType}\\n`,\n stderr: '',\n };\n}\n\nexport async function executeCli(\n args: string[],\n options: ExecuteCliOptions = {},\n): Promise<CliExecutionResult> {\n const homeDir = options.homeDir ?? process.env.OPENCODE_SWITCH_HOME ?? os.homedir();\n const context = createCliContext(homeDir, options.promptClient ?? createPromptClient());\n\n try {\n const [resource, action, ...rest] = args;\n\n if (resource === 'ls') {\n const vendors = await context.vendorService.listVendors();\n const switchConfig = await context.switchRepository.read();\n return {\n exitCode: 0,\n stdout: `${formatVendorDashboard({ activeVendor: switchConfig.activeVendor, vendors })}\\n`,\n stderr: '',\n };\n }\n\n if (resource === 'add') {\n const name = action;\n const url = rest[0];\n\n if (!name || !url) {\n throw new Error('Usage: add <name> <url>');\n }\n\n const opencodeConfig = await context.opencodeRepository.read();\n const templateOptions = stripSensitiveTemplateOptions(opencodeConfig.provider.duck?.options);\n\n await context.vendorService.addVendor({\n vendorName: name,\n npm: DEFAULT_VENDOR_NPM,\n baseURL: url,\n ...(templateOptions ? { templateOptions } : {}),\n });\n\n return {\n exitCode: 0,\n stdout: `Added vendor ${name}\\n`,\n stderr: '',\n };\n }\n\n if (resource === 'rm') {\n return runInteractiveRemoveVendor(context);\n }\n\n if (resource === 'addk') {\n return runInteractiveAddKey(context);\n }\n\n if (resource === 'switch') {\n return runInteractiveSwitchKey(context);\n }\n\n if (resource === 'rmk') {\n return runInteractiveRemoveKey(context);\n }\n\n if (resource === 'vendor' && action === 'add') {\n const [vendorName, ...flagArgs] = rest;\n if (!vendorName) {\n throw new Error('Missing vendor name');\n }\n\n const flags = parseFlags(flagArgs);\n if (!flags.npm) {\n throw new Error('Missing required flag: --npm');\n }\n\n await context.vendorService.addVendor({\n vendorName,\n npm: flags.npm,\n ...(flags['base-url'] ? { baseURL: flags['base-url'] } : {}),\n ...(flags['api-key'] ? { apiKey: flags['api-key'] } : {}),\n });\n\n return {\n exitCode: 0,\n stdout: `Added vendor ${vendorName}\\n`,\n stderr: '',\n };\n }\n\n if (resource === 'vendor' && action === 'list') {\n const vendors = await context.vendorService.listVendors();\n const lines = vendors.map((vendor) => `${vendor.vendorName} (${vendor.modelCount})`);\n\n return {\n exitCode: 0,\n stdout: formatList(lines),\n stderr: '',\n };\n }\n\n if (resource === 'vendor' && action === 'use') {\n const [vendorName] = rest;\n if (!vendorName) {\n throw new Error('Missing vendor name');\n }\n\n await context.vendorService.useVendor(vendorName);\n\n return {\n exitCode: 0,\n stdout: `Using vendor ${vendorName}\\n`,\n stderr: '',\n };\n }\n\n if (resource === 'vendor' && action === 'remove') {\n const [vendorName] = rest;\n if (!vendorName) {\n throw new Error('Missing vendor name');\n }\n\n await context.vendorService.removeVendor(vendorName);\n\n return {\n exitCode: 0,\n stdout: `Removed vendor ${vendorName}\\n`,\n stderr: '',\n };\n }\n\n if (resource === 'model' && action === 'add') {\n const [vendorName, modelType, ...flagArgs] = rest;\n if (!vendorName || !modelType) {\n throw new Error('Missing vendor name or model type');\n }\n\n const flags = parseFlags(flagArgs);\n if (!flags.model) {\n throw new Error('Missing required flag: --model');\n }\n\n await context.modelService.addModel({\n vendorName,\n modelType: asSupportedModelType(modelType),\n realModel: flags.model,\n ...(flags['api-key'] ? { apiKey: flags['api-key'] } : {}),\n ...(flags['base-url'] ? { baseURL: flags['base-url'] } : {}),\n });\n\n return {\n exitCode: 0,\n stdout: `Added model ${modelType} for ${vendorName}\\n`,\n stderr: '',\n };\n }\n\n if (resource === 'model' && action === 'list') {\n const [vendorName] = rest;\n if (!vendorName) {\n throw new Error('Missing vendor name');\n }\n\n const models = await context.modelService.listModels(vendorName);\n const lines = models.map((model) =>\n model.activeKeyAlias\n ? `${model.modelType} -> ${model.realModel} (key: ${model.activeKeyAlias})`\n : `${model.modelType} -> ${model.realModel}`,\n );\n\n return {\n exitCode: 0,\n stdout: formatList(lines),\n stderr: '',\n };\n }\n\n if (resource === 'model' && action === 'remove') {\n const [vendorName, modelType] = rest;\n if (!vendorName || !modelType) {\n throw new Error('Missing vendor name or model type');\n }\n\n await context.modelService.removeModel(vendorName, asSupportedModelType(modelType));\n\n return {\n exitCode: 0,\n stdout: `Removed model ${modelType} from ${vendorName}\\n`,\n stderr: '',\n };\n }\n\n if (resource === 'key' && action === 'add') {\n const [vendorName, modelType, keyAlias, ...flagArgs] = rest;\n if (!vendorName || !modelType || !keyAlias) {\n throw new Error('Missing vendor name, model type, or key alias');\n }\n\n const flags = parseFlags(flagArgs);\n if (!flags['api-key']) {\n throw new Error('Missing required flag: --api-key');\n }\n\n await context.modelService.addKey({\n vendorName,\n modelType: asSupportedModelType(modelType),\n keyAlias,\n apiKey: flags['api-key'],\n ...(flags['base-url'] ? { baseURL: flags['base-url'] } : {}),\n });\n\n return {\n exitCode: 0,\n stdout: `Added key ${keyAlias} for ${vendorName}/${modelType}\\n`,\n stderr: '',\n };\n }\n\n if (resource === 'key' && action === 'list') {\n const [vendorName, modelType] = rest;\n if (!vendorName || !modelType) {\n throw new Error('Missing vendor name or model type');\n }\n\n const keys = await context.modelService.listKeys(vendorName, asSupportedModelType(modelType));\n const lines = keys.map((key) => (key.isActive ? `${key.keyAlias} (active)` : key.keyAlias));\n\n return {\n exitCode: 0,\n stdout: formatList(lines),\n stderr: '',\n };\n }\n\n if (resource === 'key' && action === 'use') {\n const [vendorName, modelType, keyAlias] = rest;\n if (!vendorName || !modelType || !keyAlias) {\n throw new Error('Missing vendor name, model type, or key alias');\n }\n\n await context.modelService.useKey(vendorName, asSupportedModelType(modelType), keyAlias);\n\n return {\n exitCode: 0,\n stdout: `Using key ${keyAlias} for ${vendorName}/${modelType}\\n`,\n stderr: '',\n };\n }\n\n if (resource === 'key' && action === 'remove') {\n const [vendorName, modelType, keyAlias] = rest;\n if (!vendorName || !modelType || !keyAlias) {\n throw new Error('Missing vendor name, model type, or key alias');\n }\n\n await context.modelService.removeKey(vendorName, asSupportedModelType(modelType), keyAlias);\n\n return {\n exitCode: 0,\n stdout: `Removed key ${keyAlias} from ${vendorName}/${modelType}\\n`,\n stderr: '',\n };\n }\n\n throw new Error('Unknown command');\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return {\n exitCode: 1,\n stdout: '',\n stderr: `${message}\\n`,\n };\n }\n}\n\nexport async function runCli(args: string[], options: RunCliOptions = {}): Promise<number> {\n const result = await executeCli(args, options);\n const stdout = options.stdout ?? process.stdout;\n const stderr = options.stderr ?? process.stderr;\n\n if (result.stdout) {\n stdout.write(result.stdout);\n }\n\n if (result.stderr) {\n stderr.write(result.stderr);\n }\n\n return result.exitCode;\n}\n","import { copyFile, mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type { JsonFileStore } from '../types.js';\n\nfunction cloneValue<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await readFile(filePath, 'utf8');\n return true;\n } catch {\n return false;\n }\n}\n\nexport function createJsonFileStore(): JsonFileStore {\n return {\n async read<T>({ filePath, defaultValue }: { filePath: string; defaultValue: T }): Promise<T> {\n if (!(await fileExists(filePath))) {\n const initialValue = cloneValue(defaultValue);\n await mkdir(path.dirname(filePath), { recursive: true });\n await writeFile(filePath, `${JSON.stringify(initialValue, null, 2)}\\n`, 'utf8');\n return initialValue;\n }\n\n const content = await readFile(filePath, 'utf8');\n return JSON.parse(content) as T;\n },\n\n async write<T>({\n filePath,\n value,\n backupExisting = false,\n }: {\n filePath: string;\n value: T;\n backupExisting?: boolean;\n }): Promise<void> {\n await mkdir(path.dirname(filePath), { recursive: true });\n\n if (backupExisting && (await fileExists(filePath))) {\n await copyFile(filePath, `${filePath}.bak`);\n }\n\n await writeFile(filePath, `${JSON.stringify(value, null, 2)}\\n`, 'utf8');\n },\n };\n}\n","import type { JsonFileStore, OpenCodeConfig, OpencodeRepository } from '../types.js';\n\nconst DEFAULT_OPENCODE_CONFIG: OpenCodeConfig = {\n provider: {},\n model: null,\n small_model: null,\n};\n\nfunction normalizeOpenCodeConfig(value: Partial<OpenCodeConfig> | null | undefined): OpenCodeConfig {\n if (!value) {\n return { ...DEFAULT_OPENCODE_CONFIG };\n }\n\n const { provider, model, small_model, ...rest } = value;\n\n return {\n ...rest,\n provider: provider ?? {},\n model: model ?? null,\n small_model: small_model ?? null,\n };\n}\n\nexport function createOpencodeRepository(input: {\n filePath: string;\n jsonStore: JsonFileStore;\n}): OpencodeRepository {\n const { filePath, jsonStore } = input;\n\n return {\n async read(): Promise<OpenCodeConfig> {\n const config = await jsonStore.read({ filePath, defaultValue: DEFAULT_OPENCODE_CONFIG });\n return normalizeOpenCodeConfig(config);\n },\n\n async write(config: OpenCodeConfig): Promise<void> {\n await jsonStore.write({\n filePath,\n value: normalizeOpenCodeConfig(config),\n backupExisting: true,\n });\n },\n };\n}\n","import type { JsonFileStore, SwitchConfig, SwitchRepository } from '../types.js';\n\nconst DEFAULT_SWITCH_CONFIG: SwitchConfig = {\n activeVendor: null,\n managedProviders: [],\n};\n\nfunction normalizeSwitchConfig(value: Partial<SwitchConfig> | null | undefined): SwitchConfig {\n return {\n activeVendor: value?.activeVendor ?? null,\n managedProviders: (value?.managedProviders ?? []).map((provider) => ({\n vendorName: provider.vendorName,\n models: (provider.models ?? []).map((model) => ({\n modelType: model.modelType,\n realModel: model.realModel,\n activeKeyAlias: model.activeKeyAlias ?? null,\n keys: (model.keys ?? []).map((key) => ({\n keyAlias: key.keyAlias,\n apiKey: key.apiKey,\n ...(key.baseURL ? { baseURL: key.baseURL } : {}),\n })),\n })),\n })),\n };\n}\n\nexport function createSwitchRepository(input: {\n filePath: string;\n jsonStore: JsonFileStore;\n}): SwitchRepository {\n const { filePath, jsonStore } = input;\n\n return {\n async read(): Promise<SwitchConfig> {\n const config = await jsonStore.read({ filePath, defaultValue: DEFAULT_SWITCH_CONFIG });\n return normalizeSwitchConfig(config);\n },\n\n async write(config: SwitchConfig): Promise<void> {\n await jsonStore.write({\n filePath,\n value: normalizeSwitchConfig(config),\n });\n },\n };\n}\n","import {\n cancel,\n confirm,\n intro,\n isCancel,\n note,\n outro,\n password,\n select,\n spinner,\n text,\n} from '@clack/prompts';\n\nexport interface PromptOption {\n value: string;\n label: string;\n hint?: string;\n}\n\nexport interface SelectPromptInput {\n message: string;\n options: PromptOption[];\n}\n\nexport interface TextPromptInput {\n message: string;\n placeholder?: string;\n defaultValue?: string;\n}\n\nexport interface ConfirmPromptInput {\n message: string;\n initialValue?: boolean;\n}\n\nexport interface PromptClient {\n intro(message: string): void;\n outro(message: string): void;\n note(message: string, title?: string): void;\n select(input: SelectPromptInput): Promise<string>;\n text(input: TextPromptInput): Promise<string>;\n password(input: TextPromptInput): Promise<string>;\n confirm(input: ConfirmPromptInput): Promise<boolean>;\n withSpinner<T>(message: string, action: () => Promise<T>): Promise<T>;\n}\n\nfunction unwrapCanceled<T>(value: T | symbol): T {\n if (isCancel(value)) {\n cancel('Canceled');\n throw new Error('Canceled');\n }\n\n return value;\n}\n\nexport function createPromptClient(): PromptClient {\n return {\n intro(message: string): void {\n intro(message);\n },\n\n outro(message: string): void {\n outro(message);\n },\n\n note(message: string, title?: string): void {\n note(message, title);\n },\n\n async select(input: SelectPromptInput): Promise<string> {\n return unwrapCanceled(\n await select({\n message: input.message,\n options: input.options.map((option) => ({\n value: option.value,\n label: option.label,\n ...(option.hint ? { hint: option.hint } : {}),\n })),\n }),\n );\n },\n\n async text(input: TextPromptInput): Promise<string> {\n return unwrapCanceled(\n await text({\n message: input.message,\n ...(input.placeholder ? { placeholder: input.placeholder } : {}),\n ...(input.defaultValue ? { defaultValue: input.defaultValue } : {}),\n validate(value) {\n return value?.trim().length ? undefined : 'Required';\n },\n }),\n );\n },\n\n async password(input: TextPromptInput): Promise<string> {\n return unwrapCanceled(\n await password({\n message: input.message,\n ...(input.placeholder ? { placeholder: input.placeholder } : {}),\n validate(value) {\n return value?.trim().length ? undefined : 'Required';\n },\n }),\n );\n },\n\n async confirm(input: ConfirmPromptInput): Promise<boolean> {\n return unwrapCanceled(\n await confirm({\n message: input.message,\n ...(input.initialValue !== undefined ? { initialValue: input.initialValue } : {}),\n }),\n );\n },\n\n async withSpinner<T>(message: string, action: () => Promise<T>): Promise<T> {\n const s = spinner();\n s.start(message);\n\n try {\n const result = await action();\n s.stop('Done');\n return result;\n } catch (error) {\n s.stop('Failed');\n throw error;\n }\n },\n };\n}\n","export const SUPPORTED_MODEL_TYPES = ['gpt-5.4', 'gemini'] as const;\n\nexport type SupportedModelType = (typeof SUPPORTED_MODEL_TYPES)[number];\n\nexport interface JsonFileStore {\n read<T>(input: { filePath: string; defaultValue: T }): Promise<T>;\n write<T>(input: { filePath: string; value: T; backupExisting?: boolean }): Promise<void>;\n}\n\nexport interface OpenCodeProviderModel {\n name: string;\n [key: string]: unknown;\n}\n\nexport interface OpenCodeProvider {\n name: string;\n npm: string;\n options?: {\n baseURL?: string;\n apiKey?: string;\n [key: string]: unknown;\n };\n models: Record<string, OpenCodeProviderModel>;\n [key: string]: unknown;\n}\n\nexport interface OpenCodeConfig {\n provider: Record<string, OpenCodeProvider>;\n model: string | null;\n small_model: string | null;\n [key: string]: unknown;\n}\n\nexport interface ManagedModelMetadata {\n modelType: SupportedModelType;\n realModel: string;\n activeKeyAlias: string | null;\n keys: ManagedModelKeyMetadata[];\n}\n\nexport interface ManagedModelKeyMetadata {\n keyAlias: string;\n apiKey: string;\n baseURL?: string;\n}\n\nexport interface ManagedProviderMetadata {\n vendorName: string;\n models: ManagedModelMetadata[];\n}\n\nexport interface SwitchConfig {\n activeVendor: string | null;\n managedProviders: ManagedProviderMetadata[];\n}\n\nexport interface OpencodeRepository {\n read(): Promise<OpenCodeConfig>;\n write(config: OpenCodeConfig): Promise<void>;\n}\n\nexport interface SwitchRepository {\n read(): Promise<SwitchConfig>;\n write(config: SwitchConfig): Promise<void>;\n}\n","import type {\n ManagedModelKeyMetadata,\n ManagedModelMetadata,\n ManagedProviderMetadata,\n OpenCodeConfig,\n OpenCodeProviderModel,\n OpencodeRepository,\n SupportedModelType,\n SwitchConfig,\n SwitchRepository,\n} from '../types.js';\nimport { SUPPORTED_MODEL_TYPES } from '../types.js';\n\nexport interface AddModelInput {\n vendorName: string;\n modelType: SupportedModelType;\n realModel: string;\n apiKey?: string;\n baseURL?: string;\n}\n\nexport interface AddKeyInput {\n vendorName: string;\n modelType: SupportedModelType;\n keyAlias: string;\n apiKey: string;\n baseURL?: string;\n}\n\nexport interface ModelSummary {\n vendorName: string;\n modelType: SupportedModelType;\n realModel: string;\n activeKeyAlias: string | null;\n keyCount: number;\n}\n\nexport interface KeySummary {\n keyAlias: string;\n isActive: boolean;\n}\n\nfunction isSupportedModelType(modelType: string): modelType is SupportedModelType {\n return SUPPORTED_MODEL_TYPES.includes(modelType as SupportedModelType);\n}\n\nfunction requireSupportedModelType(modelType: string): SupportedModelType {\n if (!isSupportedModelType(modelType)) {\n throw new Error('Unsupported model type');\n }\n\n return modelType;\n}\n\nfunction upsertManagedProvider(providers: ManagedProviderMetadata[], nextProvider: ManagedProviderMetadata) {\n const providerIndex = providers.findIndex((provider) => provider.vendorName === nextProvider.vendorName);\n\n if (providerIndex === -1) {\n return [...providers, nextProvider];\n }\n\n return providers.map((provider, index) => (index === providerIndex ? nextProvider : provider));\n}\n\nfunction upsertManagedModel(\n providers: ManagedProviderMetadata[],\n vendorName: string,\n nextModel: ManagedModelMetadata,\n): ManagedProviderMetadata[] {\n const existingProvider = providers.find((provider) => provider.vendorName === vendorName);\n const existingModels = existingProvider?.models ?? [];\n const otherModels = existingModels.filter((model) => model.modelType !== nextModel.modelType);\n const nextProvider: ManagedProviderMetadata = {\n vendorName,\n models: [...otherModels, nextModel],\n };\n\n return upsertManagedProvider(providers, nextProvider);\n}\n\nfunction getManagedProvider(config: SwitchConfig, vendorName: string): ManagedProviderMetadata | undefined {\n return config.managedProviders.find((provider) => provider.vendorName === vendorName);\n}\n\nfunction getManagedModel(\n provider: ManagedProviderMetadata | undefined,\n modelType: SupportedModelType,\n): ManagedModelMetadata | undefined {\n return provider?.models.find((model) => model.modelType === modelType);\n}\n\nfunction requireManagedModel(\n config: SwitchConfig,\n vendorName: string,\n modelType: SupportedModelType,\n): ManagedModelMetadata {\n const managedModel = getManagedModel(getManagedProvider(config, vendorName), modelType);\n\n if (!managedModel) {\n throw new Error(`Unknown model: ${vendorName}/${modelType}`);\n }\n\n return managedModel;\n}\n\nfunction mergeProviderOptions(\n existingOptions: OpenCodeConfig['provider'][string]['options'],\n nextOptions: { apiKey?: string; baseURL?: string },\n): OpenCodeConfig['provider'][string]['options'] {\n const mergedOptions = {\n ...(existingOptions ?? {}),\n ...(nextOptions.baseURL ? { baseURL: nextOptions.baseURL } : {}),\n ...(nextOptions.apiKey ? { apiKey: nextOptions.apiKey } : {}),\n };\n\n return Object.keys(mergedOptions).length > 0 ? mergedOptions : undefined;\n}\n\nfunction findTemplateModel(input: {\n opencodeConfig: OpenCodeConfig;\n vendorName: string;\n modelType: SupportedModelType;\n}): OpenCodeProviderModel | undefined {\n const currentProviderModel = input.opencodeConfig.provider[input.vendorName]?.models[input.modelType];\n if (currentProviderModel) {\n return currentProviderModel;\n }\n\n const duckTemplateModel = input.opencodeConfig.provider.duck?.models[input.modelType];\n if (duckTemplateModel) {\n return duckTemplateModel;\n }\n\n return Object.values(input.opencodeConfig.provider)\n .map((provider) => provider.models[input.modelType])\n .find((model): model is OpenCodeProviderModel => model !== undefined);\n}\n\nfunction applyActiveKeyToPrimaryModel(input: {\n opencodeConfig: OpenCodeConfig;\n switchConfig: SwitchConfig;\n vendorName: string;\n modelType: SupportedModelType;\n key: ManagedModelKeyMetadata | undefined;\n}): OpenCodeConfig {\n const { opencodeConfig, switchConfig, vendorName, modelType, key } = input;\n const provider = opencodeConfig.provider[vendorName];\n const primaryPointer = opencodeConfig.model;\n\n if (!provider || switchConfig.activeVendor !== vendorName || primaryPointer !== `${vendorName}/${modelType}`) {\n return opencodeConfig;\n }\n\n const mergedOptions = key\n ? mergeProviderOptions(provider.options, {\n apiKey: key.apiKey,\n ...(key.baseURL ? { baseURL: key.baseURL } : {}),\n })\n : undefined;\n const nextProvider = key\n ? {\n ...provider,\n ...(mergedOptions ? { options: mergedOptions } : {}),\n }\n : provider;\n\n return {\n ...opencodeConfig,\n provider: {\n ...opencodeConfig.provider,\n [vendorName]: nextProvider,\n },\n };\n}\n\nexport function createModelService(input: {\n opencodeRepository: OpencodeRepository;\n switchRepository: SwitchRepository;\n}) {\n const { opencodeRepository, switchRepository } = input;\n\n return {\n async addModel(model: AddModelInput): Promise<void> {\n const supportedModelType = requireSupportedModelType(model.modelType);\n const opencodeConfig = await opencodeRepository.read();\n const provider = opencodeConfig.provider[model.vendorName];\n\n if (!provider) {\n throw new Error(`Unknown vendor: ${model.vendorName}`);\n }\n\n const nextOpencodeConfig: OpenCodeConfig = {\n ...opencodeConfig,\n provider: {\n ...opencodeConfig.provider,\n [model.vendorName]: {\n ...provider,\n models: {\n ...provider.models,\n [supportedModelType]: {\n ...(findTemplateModel({\n opencodeConfig,\n vendorName: model.vendorName,\n modelType: supportedModelType,\n }) ?? {}),\n name: model.realModel,\n },\n },\n },\n },\n };\n\n await opencodeRepository.write(nextOpencodeConfig);\n\n const switchConfig = await switchRepository.read();\n const existingModel = getManagedModel(getManagedProvider(switchConfig, model.vendorName), supportedModelType);\n const nextSwitchConfig: SwitchConfig = {\n ...switchConfig,\n managedProviders: upsertManagedModel(switchConfig.managedProviders, model.vendorName, {\n modelType: supportedModelType,\n realModel: model.realModel,\n activeKeyAlias: existingModel?.activeKeyAlias ?? null,\n keys: existingModel?.keys ?? [],\n }),\n };\n\n await switchRepository.write(nextSwitchConfig);\n },\n\n async addKey(input: AddKeyInput): Promise<void> {\n const modelType = requireSupportedModelType(input.modelType);\n const opencodeConfig = await opencodeRepository.read();\n\n if (!opencodeConfig.provider[input.vendorName]) {\n throw new Error(`Unknown vendor: ${input.vendorName}`);\n }\n\n const switchConfig = await switchRepository.read();\n const managedModel = requireManagedModel(switchConfig, input.vendorName, modelType);\n const otherKeys = managedModel.keys.filter((key) => key.keyAlias !== input.keyAlias);\n const nextKey: ManagedModelKeyMetadata = {\n keyAlias: input.keyAlias,\n apiKey: input.apiKey,\n ...(input.baseURL ? { baseURL: input.baseURL } : {}),\n };\n const nextModel: ManagedModelMetadata = {\n ...managedModel,\n activeKeyAlias: managedModel.activeKeyAlias ?? input.keyAlias,\n keys: [...otherKeys, nextKey].sort((left, right) => left.keyAlias.localeCompare(right.keyAlias)),\n };\n const nextSwitchConfig: SwitchConfig = {\n ...switchConfig,\n managedProviders: upsertManagedModel(switchConfig.managedProviders, input.vendorName, nextModel),\n };\n\n await switchRepository.write(nextSwitchConfig);\n\n const activeKey = nextModel.keys.find((key) => key.keyAlias === nextModel.activeKeyAlias);\n const nextOpencodeConfig = applyActiveKeyToPrimaryModel({\n opencodeConfig,\n switchConfig: nextSwitchConfig,\n vendorName: input.vendorName,\n modelType,\n key: activeKey,\n });\n\n if (nextOpencodeConfig !== opencodeConfig) {\n await opencodeRepository.write(nextOpencodeConfig);\n }\n },\n\n async listModels(vendorName: string): Promise<ModelSummary[]> {\n const switchConfig = await switchRepository.read();\n const managedProvider = getManagedProvider(switchConfig, vendorName);\n\n return (managedProvider?.models ?? [])\n .slice()\n .sort((left, right) => left.modelType.localeCompare(right.modelType))\n .map((model) => ({\n vendorName,\n modelType: model.modelType,\n realModel: model.realModel,\n activeKeyAlias: model.activeKeyAlias,\n keyCount: model.keys.length,\n }));\n },\n\n async listKeys(vendorName: string, modelType: SupportedModelType): Promise<KeySummary[]> {\n const supportedModelType = requireSupportedModelType(modelType);\n const switchConfig = await switchRepository.read();\n const managedModel = requireManagedModel(switchConfig, vendorName, supportedModelType);\n\n return managedModel.keys\n .slice()\n .sort((left, right) => left.keyAlias.localeCompare(right.keyAlias))\n .map((key) => ({\n keyAlias: key.keyAlias,\n isActive: key.keyAlias === managedModel.activeKeyAlias,\n }));\n },\n\n async useKey(vendorName: string, modelType: SupportedModelType, keyAlias: string): Promise<void> {\n const supportedModelType = requireSupportedModelType(modelType);\n const switchConfig = await switchRepository.read();\n const managedModel = requireManagedModel(switchConfig, vendorName, supportedModelType);\n const activeKey = managedModel.keys.find((key) => key.keyAlias === keyAlias);\n\n if (!activeKey) {\n throw new Error(`Unknown key: ${vendorName}/${supportedModelType}/${keyAlias}`);\n }\n\n const nextModel: ManagedModelMetadata = {\n ...managedModel,\n activeKeyAlias: keyAlias,\n };\n const nextSwitchConfig: SwitchConfig = {\n ...switchConfig,\n managedProviders: upsertManagedModel(switchConfig.managedProviders, vendorName, nextModel),\n };\n\n await switchRepository.write(nextSwitchConfig);\n\n const opencodeConfig = await opencodeRepository.read();\n const nextOpencodeConfig = applyActiveKeyToPrimaryModel({\n opencodeConfig,\n switchConfig: nextSwitchConfig,\n vendorName,\n modelType: supportedModelType,\n key: activeKey,\n });\n\n if (nextOpencodeConfig !== opencodeConfig) {\n await opencodeRepository.write(nextOpencodeConfig);\n }\n },\n\n async removeModel(vendorName: string, modelType: SupportedModelType): Promise<void> {\n const supportedModelType = requireSupportedModelType(modelType);\n const opencodeConfig = await opencodeRepository.read();\n const provider = opencodeConfig.provider[vendorName];\n\n if (!provider) {\n throw new Error(`Unknown vendor: ${vendorName}`);\n }\n\n const nextModels = { ...provider.models };\n delete nextModels[supportedModelType];\n const targetModelPointer = `${vendorName}/${supportedModelType}`;\n\n await opencodeRepository.write({\n ...opencodeConfig,\n provider: {\n ...opencodeConfig.provider,\n [vendorName]: {\n ...provider,\n models: nextModels,\n },\n },\n model: opencodeConfig.model === targetModelPointer ? null : opencodeConfig.model,\n small_model:\n opencodeConfig.small_model === targetModelPointer ? null : opencodeConfig.small_model,\n });\n\n const switchConfig = await switchRepository.read();\n await switchRepository.write({\n ...switchConfig,\n managedProviders: switchConfig.managedProviders.map((providerMetadata) => {\n if (providerMetadata.vendorName !== vendorName) {\n return providerMetadata;\n }\n\n return {\n ...providerMetadata,\n models: providerMetadata.models.filter(\n (modelMetadata) => modelMetadata.modelType !== supportedModelType,\n ),\n };\n }),\n });\n },\n\n async removeKey(vendorName: string, modelType: SupportedModelType, keyAlias: string): Promise<void> {\n const supportedModelType = requireSupportedModelType(modelType);\n const switchConfig = await switchRepository.read();\n const managedModel = requireManagedModel(switchConfig, vendorName, supportedModelType);\n\n if (!managedModel.keys.some((key) => key.keyAlias === keyAlias)) {\n throw new Error(`Unknown key: ${vendorName}/${supportedModelType}/${keyAlias}`);\n }\n\n const nextKeys = managedModel.keys.filter((key) => key.keyAlias !== keyAlias);\n const nextActiveKeyAlias =\n managedModel.activeKeyAlias === keyAlias ? (nextKeys[0]?.keyAlias ?? null) : managedModel.activeKeyAlias;\n const nextModel: ManagedModelMetadata = {\n ...managedModel,\n activeKeyAlias: nextActiveKeyAlias,\n keys: nextKeys,\n };\n const nextSwitchConfig: SwitchConfig = {\n ...switchConfig,\n managedProviders: upsertManagedModel(switchConfig.managedProviders, vendorName, nextModel),\n };\n\n await switchRepository.write(nextSwitchConfig);\n\n const opencodeConfig = await opencodeRepository.read();\n const activeKey = nextModel.keys.find((key) => key.keyAlias === nextActiveKeyAlias);\n const nextOpencodeConfig = applyActiveKeyToPrimaryModel({\n opencodeConfig,\n switchConfig: nextSwitchConfig,\n vendorName,\n modelType: supportedModelType,\n key: activeKey,\n });\n\n if (nextOpencodeConfig !== opencodeConfig) {\n await opencodeRepository.write(nextOpencodeConfig);\n }\n },\n };\n}\n","import type {\n ManagedProviderMetadata,\n OpenCodeConfig,\n OpenCodeProvider,\n OpenCodeProviderModel,\n OpencodeRepository,\n SwitchConfig,\n SwitchRepository,\n} from '../types.js';\n\nexport interface AddVendorInput {\n vendorName: string;\n npm: string;\n baseURL?: string;\n apiKey?: string;\n templateOptions?: OpenCodeProvider['options'];\n}\n\nexport interface VendorSummary {\n vendorName: string;\n managed: boolean;\n modelCount: number;\n}\n\nfunction upsertManagedProvider(\n managedProviders: ManagedProviderMetadata[],\n vendorName: string,\n): ManagedProviderMetadata[] {\n const existingProvider = managedProviders.find((provider) => provider.vendorName === vendorName);\n if (existingProvider) {\n return managedProviders;\n }\n\n return [...managedProviders, { vendorName, models: [] }];\n}\n\nfunction createProviderOptions(input: {\n templateOptions?: OpenCodeProvider['options'];\n existingOptions?: OpenCodeProvider['options'];\n baseURL?: string;\n apiKey?: string;\n}): OpenCodeProvider['options'] {\n const options = {\n ...(input.templateOptions ?? {}),\n ...(input.existingOptions ?? {}),\n ...(input.baseURL ? { baseURL: input.baseURL } : {}),\n ...(input.apiKey ? { apiKey: input.apiKey } : {}),\n };\n\n return Object.keys(options).length > 0 ? options : undefined;\n}\n\nfunction selectModelPointers(vendorName: string, provider: OpenCodeProvider): {\n model: string | null;\n smallModel: string | null;\n} {\n const availableModelTypes = Object.keys(provider.models).sort();\n if (availableModelTypes.length === 0) {\n return {\n model: null,\n smallModel: null,\n };\n }\n\n const primaryModelType = provider.models['gpt-5.4'] ? 'gpt-5.4' : availableModelTypes[0];\n const smallModelType = provider.models.gemini\n ? 'gemini'\n : primaryModelType;\n\n return {\n model: primaryModelType ? `${vendorName}/${primaryModelType}` : null,\n smallModel: smallModelType ? `${vendorName}/${smallModelType}` : null,\n };\n}\n\nfunction findActiveModelKey(input: {\n switchConfig: SwitchConfig;\n vendorName: string;\n modelType: string | null;\n}) {\n const managedProvider = input.switchConfig.managedProviders.find(\n (provider) => provider.vendorName === input.vendorName,\n );\n const managedModel = managedProvider?.models.find((model) => model.modelType === input.modelType);\n\n if (!managedModel?.activeKeyAlias) {\n return undefined;\n }\n\n return managedModel.keys.find((key) => key.keyAlias === managedModel.activeKeyAlias);\n}\n\nexport function createVendorService(input: {\n opencodeRepository: OpencodeRepository;\n switchRepository: SwitchRepository;\n}) {\n const { opencodeRepository, switchRepository } = input;\n\n return {\n async addVendor(vendor: AddVendorInput): Promise<void> {\n const opencodeConfig = await opencodeRepository.read();\n const existingProvider = opencodeConfig.provider[vendor.vendorName];\n const providerOptions =\n createProviderOptions({\n templateOptions: vendor.templateOptions,\n existingOptions: existingProvider?.options,\n ...(vendor.baseURL ? { baseURL: vendor.baseURL } : {}),\n ...(vendor.apiKey ? { apiKey: vendor.apiKey } : {}),\n }) ??\n existingProvider?.options;\n\n const providerConfig: OpenCodeProvider = {\n ...(existingProvider ?? {}),\n name: vendor.vendorName,\n npm: vendor.npm,\n models: existingProvider?.models ?? {},\n ...(providerOptions ? { options: providerOptions } : {}),\n };\n\n const nextConfig: OpenCodeConfig = {\n ...opencodeConfig,\n provider: {\n ...opencodeConfig.provider,\n [vendor.vendorName]: providerConfig,\n },\n };\n\n await opencodeRepository.write(nextConfig);\n\n const switchConfig = await switchRepository.read();\n const nextSwitchConfig: SwitchConfig = {\n ...switchConfig,\n managedProviders: upsertManagedProvider(switchConfig.managedProviders, vendor.vendorName),\n };\n\n await switchRepository.write(nextSwitchConfig);\n },\n\n async listVendors(): Promise<VendorSummary[]> {\n const opencodeConfig = await opencodeRepository.read();\n const switchConfig = await switchRepository.read();\n const managedProviders = new Map(\n switchConfig.managedProviders.map((provider) => [provider.vendorName, provider]),\n );\n\n return Object.keys(opencodeConfig.provider)\n .sort()\n .map((vendorName) => {\n const managedProvider = managedProviders.get(vendorName);\n const provider = opencodeConfig.provider[vendorName];\n\n return {\n vendorName,\n managed: managedProvider !== undefined,\n modelCount:\n managedProvider?.models.length ?? Object.keys(provider?.models ?? {}).length,\n };\n });\n },\n\n async useVendor(vendorName: string): Promise<void> {\n const opencodeConfig = await opencodeRepository.read();\n const provider = opencodeConfig.provider[vendorName];\n\n if (!provider) {\n throw new Error(`Unknown vendor: ${vendorName}`);\n }\n\n const pointers = selectModelPointers(vendorName, provider);\n const switchConfig = await switchRepository.read();\n const primaryModelType = pointers.model?.split('/')[1] ?? null;\n const activeKey = findActiveModelKey({\n switchConfig,\n vendorName,\n modelType: primaryModelType,\n });\n const providerOptions = activeKey\n ? {\n ...(provider.options ?? {}),\n apiKey: activeKey.apiKey,\n ...(activeKey.baseURL ? { baseURL: activeKey.baseURL } : {}),\n }\n : provider.options;\n\n await opencodeRepository.write({\n ...opencodeConfig,\n model: pointers.model,\n small_model: pointers.smallModel,\n provider: {\n ...opencodeConfig.provider,\n [vendorName]: {\n ...provider,\n ...(providerOptions ? { options: providerOptions } : {}),\n },\n },\n });\n\n await switchRepository.write({\n ...switchConfig,\n activeVendor: vendorName,\n });\n },\n\n async removeVendor(vendorName: string): Promise<void> {\n const opencodeConfig = await opencodeRepository.read();\n if (!opencodeConfig.provider[vendorName]) {\n throw new Error(`Unknown vendor: ${vendorName}`);\n }\n\n const nextProviders = { ...opencodeConfig.provider };\n delete nextProviders[vendorName];\n\n await opencodeRepository.write({\n ...opencodeConfig,\n provider: nextProviders,\n model: opencodeConfig.model?.startsWith(`${vendorName}/`) ? null : opencodeConfig.model,\n small_model: opencodeConfig.small_model?.startsWith(`${vendorName}/`)\n ? null\n : opencodeConfig.small_model,\n });\n\n const switchConfig = await switchRepository.read();\n await switchRepository.write({\n activeVendor: switchConfig.activeVendor === vendorName ? null : switchConfig.activeVendor,\n managedProviders: switchConfig.managedProviders.filter(\n (provider) => provider.vendorName !== vendorName,\n ),\n });\n },\n };\n}\n","import { runCli } from './cli.js';\n\nasync function main(): Promise<void> {\n const exitCode = await runCli(process.argv.slice(2));\n process.exitCode = exitCode;\n}\n\nvoid main();\n"],"mappings":"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","names":["path","input","upsertManagedProvider","path"]}
@@ -0,0 +1,175 @@
1
+ interface PromptOption {
2
+ value: string;
3
+ label: string;
4
+ hint?: string;
5
+ }
6
+ interface SelectPromptInput {
7
+ message: string;
8
+ options: PromptOption[];
9
+ }
10
+ interface TextPromptInput {
11
+ message: string;
12
+ placeholder?: string;
13
+ defaultValue?: string;
14
+ }
15
+ interface ConfirmPromptInput {
16
+ message: string;
17
+ initialValue?: boolean;
18
+ }
19
+ interface PromptClient {
20
+ intro(message: string): void;
21
+ outro(message: string): void;
22
+ note(message: string, title?: string): void;
23
+ select(input: SelectPromptInput): Promise<string>;
24
+ text(input: TextPromptInput): Promise<string>;
25
+ password(input: TextPromptInput): Promise<string>;
26
+ confirm(input: ConfirmPromptInput): Promise<boolean>;
27
+ withSpinner<T>(message: string, action: () => Promise<T>): Promise<T>;
28
+ }
29
+
30
+ declare const SUPPORTED_MODEL_TYPES: readonly ["gpt-5.4", "gemini"];
31
+ type SupportedModelType = (typeof SUPPORTED_MODEL_TYPES)[number];
32
+ interface JsonFileStore {
33
+ read<T>(input: {
34
+ filePath: string;
35
+ defaultValue: T;
36
+ }): Promise<T>;
37
+ write<T>(input: {
38
+ filePath: string;
39
+ value: T;
40
+ backupExisting?: boolean;
41
+ }): Promise<void>;
42
+ }
43
+ interface OpenCodeProviderModel {
44
+ name: string;
45
+ [key: string]: unknown;
46
+ }
47
+ interface OpenCodeProvider {
48
+ name: string;
49
+ npm: string;
50
+ options?: {
51
+ baseURL?: string;
52
+ apiKey?: string;
53
+ [key: string]: unknown;
54
+ };
55
+ models: Record<string, OpenCodeProviderModel>;
56
+ [key: string]: unknown;
57
+ }
58
+ interface OpenCodeConfig {
59
+ provider: Record<string, OpenCodeProvider>;
60
+ model: string | null;
61
+ small_model: string | null;
62
+ [key: string]: unknown;
63
+ }
64
+ interface ManagedModelMetadata {
65
+ modelType: SupportedModelType;
66
+ realModel: string;
67
+ activeKeyAlias: string | null;
68
+ keys: ManagedModelKeyMetadata[];
69
+ }
70
+ interface ManagedModelKeyMetadata {
71
+ keyAlias: string;
72
+ apiKey: string;
73
+ baseURL?: string;
74
+ }
75
+ interface ManagedProviderMetadata {
76
+ vendorName: string;
77
+ models: ManagedModelMetadata[];
78
+ }
79
+ interface SwitchConfig {
80
+ activeVendor: string | null;
81
+ managedProviders: ManagedProviderMetadata[];
82
+ }
83
+ interface OpencodeRepository {
84
+ read(): Promise<OpenCodeConfig>;
85
+ write(config: OpenCodeConfig): Promise<void>;
86
+ }
87
+ interface SwitchRepository {
88
+ read(): Promise<SwitchConfig>;
89
+ write(config: SwitchConfig): Promise<void>;
90
+ }
91
+
92
+ interface ExecuteCliOptions {
93
+ homeDir?: string;
94
+ promptClient?: PromptClient;
95
+ }
96
+ interface CliExecutionResult {
97
+ exitCode: number;
98
+ stdout: string;
99
+ stderr: string;
100
+ }
101
+ declare function executeCli(args: string[], options?: ExecuteCliOptions): Promise<CliExecutionResult>;
102
+
103
+ declare function createJsonFileStore(): JsonFileStore;
104
+
105
+ declare function createOpencodeRepository(input: {
106
+ filePath: string;
107
+ jsonStore: JsonFileStore;
108
+ }): OpencodeRepository;
109
+
110
+ declare function createSwitchRepository(input: {
111
+ filePath: string;
112
+ jsonStore: JsonFileStore;
113
+ }): SwitchRepository;
114
+
115
+ interface AddModelInput {
116
+ vendorName: string;
117
+ modelType: SupportedModelType;
118
+ realModel: string;
119
+ apiKey?: string;
120
+ baseURL?: string;
121
+ }
122
+ interface AddKeyInput {
123
+ vendorName: string;
124
+ modelType: SupportedModelType;
125
+ keyAlias: string;
126
+ apiKey: string;
127
+ baseURL?: string;
128
+ }
129
+ interface ModelSummary {
130
+ vendorName: string;
131
+ modelType: SupportedModelType;
132
+ realModel: string;
133
+ activeKeyAlias: string | null;
134
+ keyCount: number;
135
+ }
136
+ interface KeySummary {
137
+ keyAlias: string;
138
+ isActive: boolean;
139
+ }
140
+ declare function createModelService(input: {
141
+ opencodeRepository: OpencodeRepository;
142
+ switchRepository: SwitchRepository;
143
+ }): {
144
+ addModel(model: AddModelInput): Promise<void>;
145
+ addKey(input: AddKeyInput): Promise<void>;
146
+ listModels(vendorName: string): Promise<ModelSummary[]>;
147
+ listKeys(vendorName: string, modelType: SupportedModelType): Promise<KeySummary[]>;
148
+ useKey(vendorName: string, modelType: SupportedModelType, keyAlias: string): Promise<void>;
149
+ removeModel(vendorName: string, modelType: SupportedModelType): Promise<void>;
150
+ removeKey(vendorName: string, modelType: SupportedModelType, keyAlias: string): Promise<void>;
151
+ };
152
+
153
+ interface AddVendorInput {
154
+ vendorName: string;
155
+ npm: string;
156
+ baseURL?: string;
157
+ apiKey?: string;
158
+ templateOptions?: OpenCodeProvider['options'];
159
+ }
160
+ interface VendorSummary {
161
+ vendorName: string;
162
+ managed: boolean;
163
+ modelCount: number;
164
+ }
165
+ declare function createVendorService(input: {
166
+ opencodeRepository: OpencodeRepository;
167
+ switchRepository: SwitchRepository;
168
+ }): {
169
+ addVendor(vendor: AddVendorInput): Promise<void>;
170
+ listVendors(): Promise<VendorSummary[]>;
171
+ useVendor(vendorName: string): Promise<void>;
172
+ removeVendor(vendorName: string): Promise<void>;
173
+ };
174
+
175
+ export { type AddModelInput, type AddVendorInput, type CliExecutionResult, type ExecuteCliOptions, type ManagedModelMetadata, type ManagedProviderMetadata, type ModelSummary, type OpenCodeConfig, type OpenCodeProvider, type OpenCodeProviderModel, SUPPORTED_MODEL_TYPES, type SupportedModelType, type SwitchConfig, type VendorSummary, createJsonFileStore, createModelService, createOpencodeRepository, createSwitchRepository, createVendorService, executeCli };
@@ -0,0 +1,175 @@
1
+ interface PromptOption {
2
+ value: string;
3
+ label: string;
4
+ hint?: string;
5
+ }
6
+ interface SelectPromptInput {
7
+ message: string;
8
+ options: PromptOption[];
9
+ }
10
+ interface TextPromptInput {
11
+ message: string;
12
+ placeholder?: string;
13
+ defaultValue?: string;
14
+ }
15
+ interface ConfirmPromptInput {
16
+ message: string;
17
+ initialValue?: boolean;
18
+ }
19
+ interface PromptClient {
20
+ intro(message: string): void;
21
+ outro(message: string): void;
22
+ note(message: string, title?: string): void;
23
+ select(input: SelectPromptInput): Promise<string>;
24
+ text(input: TextPromptInput): Promise<string>;
25
+ password(input: TextPromptInput): Promise<string>;
26
+ confirm(input: ConfirmPromptInput): Promise<boolean>;
27
+ withSpinner<T>(message: string, action: () => Promise<T>): Promise<T>;
28
+ }
29
+
30
+ declare const SUPPORTED_MODEL_TYPES: readonly ["gpt-5.4", "gemini"];
31
+ type SupportedModelType = (typeof SUPPORTED_MODEL_TYPES)[number];
32
+ interface JsonFileStore {
33
+ read<T>(input: {
34
+ filePath: string;
35
+ defaultValue: T;
36
+ }): Promise<T>;
37
+ write<T>(input: {
38
+ filePath: string;
39
+ value: T;
40
+ backupExisting?: boolean;
41
+ }): Promise<void>;
42
+ }
43
+ interface OpenCodeProviderModel {
44
+ name: string;
45
+ [key: string]: unknown;
46
+ }
47
+ interface OpenCodeProvider {
48
+ name: string;
49
+ npm: string;
50
+ options?: {
51
+ baseURL?: string;
52
+ apiKey?: string;
53
+ [key: string]: unknown;
54
+ };
55
+ models: Record<string, OpenCodeProviderModel>;
56
+ [key: string]: unknown;
57
+ }
58
+ interface OpenCodeConfig {
59
+ provider: Record<string, OpenCodeProvider>;
60
+ model: string | null;
61
+ small_model: string | null;
62
+ [key: string]: unknown;
63
+ }
64
+ interface ManagedModelMetadata {
65
+ modelType: SupportedModelType;
66
+ realModel: string;
67
+ activeKeyAlias: string | null;
68
+ keys: ManagedModelKeyMetadata[];
69
+ }
70
+ interface ManagedModelKeyMetadata {
71
+ keyAlias: string;
72
+ apiKey: string;
73
+ baseURL?: string;
74
+ }
75
+ interface ManagedProviderMetadata {
76
+ vendorName: string;
77
+ models: ManagedModelMetadata[];
78
+ }
79
+ interface SwitchConfig {
80
+ activeVendor: string | null;
81
+ managedProviders: ManagedProviderMetadata[];
82
+ }
83
+ interface OpencodeRepository {
84
+ read(): Promise<OpenCodeConfig>;
85
+ write(config: OpenCodeConfig): Promise<void>;
86
+ }
87
+ interface SwitchRepository {
88
+ read(): Promise<SwitchConfig>;
89
+ write(config: SwitchConfig): Promise<void>;
90
+ }
91
+
92
+ interface ExecuteCliOptions {
93
+ homeDir?: string;
94
+ promptClient?: PromptClient;
95
+ }
96
+ interface CliExecutionResult {
97
+ exitCode: number;
98
+ stdout: string;
99
+ stderr: string;
100
+ }
101
+ declare function executeCli(args: string[], options?: ExecuteCliOptions): Promise<CliExecutionResult>;
102
+
103
+ declare function createJsonFileStore(): JsonFileStore;
104
+
105
+ declare function createOpencodeRepository(input: {
106
+ filePath: string;
107
+ jsonStore: JsonFileStore;
108
+ }): OpencodeRepository;
109
+
110
+ declare function createSwitchRepository(input: {
111
+ filePath: string;
112
+ jsonStore: JsonFileStore;
113
+ }): SwitchRepository;
114
+
115
+ interface AddModelInput {
116
+ vendorName: string;
117
+ modelType: SupportedModelType;
118
+ realModel: string;
119
+ apiKey?: string;
120
+ baseURL?: string;
121
+ }
122
+ interface AddKeyInput {
123
+ vendorName: string;
124
+ modelType: SupportedModelType;
125
+ keyAlias: string;
126
+ apiKey: string;
127
+ baseURL?: string;
128
+ }
129
+ interface ModelSummary {
130
+ vendorName: string;
131
+ modelType: SupportedModelType;
132
+ realModel: string;
133
+ activeKeyAlias: string | null;
134
+ keyCount: number;
135
+ }
136
+ interface KeySummary {
137
+ keyAlias: string;
138
+ isActive: boolean;
139
+ }
140
+ declare function createModelService(input: {
141
+ opencodeRepository: OpencodeRepository;
142
+ switchRepository: SwitchRepository;
143
+ }): {
144
+ addModel(model: AddModelInput): Promise<void>;
145
+ addKey(input: AddKeyInput): Promise<void>;
146
+ listModels(vendorName: string): Promise<ModelSummary[]>;
147
+ listKeys(vendorName: string, modelType: SupportedModelType): Promise<KeySummary[]>;
148
+ useKey(vendorName: string, modelType: SupportedModelType, keyAlias: string): Promise<void>;
149
+ removeModel(vendorName: string, modelType: SupportedModelType): Promise<void>;
150
+ removeKey(vendorName: string, modelType: SupportedModelType, keyAlias: string): Promise<void>;
151
+ };
152
+
153
+ interface AddVendorInput {
154
+ vendorName: string;
155
+ npm: string;
156
+ baseURL?: string;
157
+ apiKey?: string;
158
+ templateOptions?: OpenCodeProvider['options'];
159
+ }
160
+ interface VendorSummary {
161
+ vendorName: string;
162
+ managed: boolean;
163
+ modelCount: number;
164
+ }
165
+ declare function createVendorService(input: {
166
+ opencodeRepository: OpencodeRepository;
167
+ switchRepository: SwitchRepository;
168
+ }): {
169
+ addVendor(vendor: AddVendorInput): Promise<void>;
170
+ listVendors(): Promise<VendorSummary[]>;
171
+ useVendor(vendorName: string): Promise<void>;
172
+ removeVendor(vendorName: string): Promise<void>;
173
+ };
174
+
175
+ export { type AddModelInput, type AddVendorInput, type CliExecutionResult, type ExecuteCliOptions, type ManagedModelMetadata, type ManagedProviderMetadata, type ModelSummary, type OpenCodeConfig, type OpenCodeProvider, type OpenCodeProviderModel, SUPPORTED_MODEL_TYPES, type SupportedModelType, type SwitchConfig, type VendorSummary, createJsonFileStore, createModelService, createOpencodeRepository, createSwitchRepository, createVendorService, executeCli };