diff --git a/src/commands/config.ts b/src/commands/config.ts index 5811aa7..21f6c29 100644 --- a/src/commands/config.ts +++ b/src/commands/config.ts @@ -101,11 +101,16 @@ function applyProviderChange(config: Config, provider: Config['provider']): Conf } function updateConfigFromRawValue(config: Config, key: ConfigSetKey, rawValue: string): Config { - if (key === 'provider') { - return applyProviderChange(config, parseConfigSetValue('provider', rawValue)); + const updatedConfig = + key === 'provider' + ? applyProviderChange(config, parseConfigSetValue('provider', rawValue)) + : updateConfigField(config, key, parseConfigSetValue(key, rawValue)); + + if (updatedConfig.provider === CUSTOM_PROVIDER_KEY && !updatedConfig.baseUrl) { + throw new Error('Custom provider requires a configured baseUrl. Set baseUrl before selecting __custom__.'); } - return updateConfigField(config, key, parseConfigSetValue(key, rawValue)); + return updatedConfig; } /** Masks a stored API key while leaving enough prefix to identify which key is configured. */ diff --git a/tests/config-command.test.mjs b/tests/config-command.test.mjs index 30ac976..d2adc37 100644 --- a/tests/config-command.test.mjs +++ b/tests/config-command.test.mjs @@ -332,6 +332,22 @@ test('config set clears stale baseUrl when switching between built-in providers' }); }); +test('config set requires a baseUrl before switching to the custom provider', async () => { + await withTempHome(async (homeDir) => { + writeConfig(homeDir, { baseUrl: undefined, provider: 'openai' }); + + await assert.rejects( + () => runConfigWithArgs(homeDir, ['set', 'provider', '__custom__']), + (error) => { + assert.equal(error.code, 1); + assert.match(error.stdout + error.stderr, /Custom provider requires a configured baseUrl/); + assert.equal(readConfig(homeDir).provider, 'openai'); + return true; + }, + ); + }); +}); + test('config set preserves baseUrl when switching to custom provider', async () => { await withTempHome(async (homeDir) => { writeConfig(homeDir, {