From 62f568b88b58e1e7cf422c21ee2e08f10977b714 Mon Sep 17 00:00:00 2001 From: Theo Browne Date: Sun, 6 Sep 2026 02:56:28 -0700 Subject: [PATCH] fix(server): skip disabled provider instances for text generation fallback (#10346) Co-authored-by: Claude Fable 5.1 --- apps/server/src/serverSettings.test.ts | 18 ++++++++++++++++++ apps/server/src/serverSettings.ts | 9 ++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/apps/server/src/serverSettings.test.ts b/apps/server/src/serverSettings.test.ts index 6e837308e8cb13dcb012976703e5f1d97512828a..9769ebf0a5f642b16500059198fbd9c3602c6edd 100644 --- a/apps/server/src/serverSettings.test.ts +++ b/apps/server/src/serverSettings.test.ts @@ -656,6 +656,24 @@ it.layer(NodeServices.layer)("server settings", (it) => { }).pipe(Effect.provide(makeServerSettingsLayer())), ); + it.effect("skips a disabled provider instance when picking the text generation fallback", () => + Effect.gen(function* () { + const serverConfig = yield* ServerConfig.ServerConfig; + const fileSystem = yield* FileSystem.FileSystem; + const serverSettings = yield* ServerSettingsModule.ServerSettingsService; + // The Providers UI writes providerInstances only, so the legacy providers + // map decodes to defaults where codex is enabled and listed first. + yield* fileSystem.writeFileString( + serverConfig.settingsPath, + '{"providerInstances":{"codex":{"driver":"codex","enabled":false,"config":{}}}}', + ); + + const settings = yield* serverSettings.getSettings; + + assert.equal(settings.textGenerationModelSelection.instanceId, "claudeAgent"); + }).pipe(Effect.provide(makeServerSettingsLayer())), + ); + it.effect("keeps unused providers disabled in existing sparse settings files", () => Effect.gen(function* () { const serverConfig = yield* ServerConfig.ServerConfig; diff --git a/apps/server/src/serverSettings.ts b/apps/server/src/serverSettings.ts index 5f2550534883e0138bd81c7dc62632b2634b53fe..84e978320a30193c2cb7d8fb0f6d264691efdf49 100644 --- a/apps/server/src/serverSettings.ts +++ b/apps/server/src/serverSettings.ts @@ -21,6 +21,7 @@ import { type UsageLimitSourceConfig, ProviderDriverKind, ProviderInstanceId, + resolveProviderInstanceEnabled, ServerSettings, ServerSettingsError, type ServerSettingsPatch, @@ -321,7 +322,13 @@ function resolveTextGenerationProvider(settings: ServerSettings): ServerSettings } function fallbackTextGenerationProvider(settings: ServerSettings): ServerSettings { - const fallbackEntry = Object.entries(settings.providers).find(([, provider]) => provider.enabled); + // Same precedence as isModelSelectionProviderEnabled: an explicit provider + // instance wins over the legacy providers map, which decodes to defaults + // (codex enabled) when the Providers UI has only written providerInstances. + const fallbackEntry = Object.entries(settings.providers).find(([driver, provider]) => { + const instance = settings.providerInstances[ProviderInstanceId.make(driver)]; + return instance === undefined ? provider.enabled : resolveProviderInstanceEnabled(instance); + }); const fallback = fallbackEntry ? ProviderDriverKind.make(fallbackEntry[0]) : undefined; if (!fallback) { return settings; -- 2.54.0