| author | |
| committer | |
| log | 62f568b88b58e1e7cf422c21ee2e08f10977b714 |
| tree | fa5776a23aa6a8a1dd0183cfc897893a0c79e6fc |
| parent | eb8ed80300bd719b49fc80ad8708f9839bb48c92 |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>2 files changed, 26 insertions(+), 1 deletions(-)
apps/server/src/serverSettings.test.ts+18| ... | @@ -656,6 +656,24 @@ it.layer(NodeServices.layer)("server settings", (it) => { | ... | @@ -656,6 +656,24 @@ it.layer(NodeServices.layer)("server settings", (it) => { |
| 656 | }).pipe(Effect.provide(makeServerSettingsLayer())), | 656 | }).pipe(Effect.provide(makeServerSettingsLayer())), |
| 657 | ); | 657 | ); |
| 658 | 658 | ||
| 659 | it.effect("skips a disabled provider instance when picking the text generation fallback", () => | ||
| 660 | Effect.gen(function* () { | ||
| 661 | const serverConfig = yield* ServerConfig.ServerConfig; | ||
| 662 | const fileSystem = yield* FileSystem.FileSystem; | ||
| 663 | const serverSettings = yield* ServerSettingsModule.ServerSettingsService; | ||
| 664 | // The Providers UI writes providerInstances only, so the legacy providers | ||
| 665 | // map decodes to defaults where codex is enabled and listed first. | ||
| 666 | yield* fileSystem.writeFileString( | ||
| 667 | serverConfig.settingsPath, | ||
| 668 | '{"providerInstances":{"codex":{"driver":"codex","enabled":false,"config":{}}}}', | ||
| 669 | ); | ||
| 670 | |||
| 671 | const settings = yield* serverSettings.getSettings; | ||
| 672 | |||
| 673 | assert.equal(settings.textGenerationModelSelection.instanceId, "claudeAgent"); | ||
| 674 | }).pipe(Effect.provide(makeServerSettingsLayer())), | ||
| 675 | ); | ||
| 676 | |||
| 659 | it.effect("keeps unused providers disabled in existing sparse settings files", () => | 677 | it.effect("keeps unused providers disabled in existing sparse settings files", () => |
| 660 | Effect.gen(function* () { | 678 | Effect.gen(function* () { |
| 661 | const serverConfig = yield* ServerConfig.ServerConfig; | 679 | const serverConfig = yield* ServerConfig.ServerConfig; |
apps/server/src/serverSettings.ts+8-1| ... | @@ -21,6 +21,7 @@ import { | ... | @@ -21,6 +21,7 @@ import { |
| 21 | type UsageLimitSourceConfig, | 21 | type UsageLimitSourceConfig, |
| 22 | ProviderDriverKind, | 22 | ProviderDriverKind, |
| 23 | ProviderInstanceId, | 23 | ProviderInstanceId, |
| 24 | resolveProviderInstanceEnabled, | ||
| 24 | ServerSettings, | 25 | ServerSettings, |
| 25 | ServerSettingsError, | 26 | ServerSettingsError, |
| 26 | type ServerSettingsPatch, | 27 | type ServerSettingsPatch, |
| ... | @@ -321,7 +322,13 @@ function resolveTextGenerationProvider(settings: ServerSettings): ServerSettings | ... | @@ -321,7 +322,13 @@ function resolveTextGenerationProvider(settings: ServerSettings): ServerSettings |
| 321 | } | 322 | } |
| 322 | 323 | ||
| 323 | function fallbackTextGenerationProvider(settings: ServerSettings): ServerSettings { | 324 | function fallbackTextGenerationProvider(settings: ServerSettings): ServerSettings { |
| 324 | const fallbackEntry = Object.entries(settings.providers).find(([, provider]) => provider.enabled); | 325 | // Same precedence as isModelSelectionProviderEnabled: an explicit provider |
| 326 | // instance wins over the legacy providers map, which decodes to defaults | ||
| 327 | // (codex enabled) when the Providers UI has only written providerInstances. | ||
| 328 | const fallbackEntry = Object.entries(settings.providers).find(([driver, provider]) => { | ||
| 329 | const instance = settings.providerInstances[ProviderInstanceId.make(driver)]; | ||
| 330 | return instance === undefined ? provider.enabled : resolveProviderInstanceEnabled(instance); | ||
| 331 | }); | ||
| 325 | const fallback = fallbackEntry ? ProviderDriverKind.make(fallbackEntry[0]) : undefined; | 332 | const fallback = fallbackEntry ? ProviderDriverKind.make(fallbackEntry[0]) : undefined; |
| 326 | if (!fallback) { | 333 | if (!fallback) { |
| 327 | return settings; | 334 | return settings; |