Merge pull request #4222 from andomeder/wip/pr1-skip-disconnected-explicit-provider-fallbacks

fix(background-agent): skip disconnected explicit-provider fallbacks
This commit is contained in:
YeonGyu-Kim
2026-05-21 12:57:58 +09:00
committed by GitHub
2 changed files with 7 additions and 11 deletions
@@ -431,26 +431,26 @@ describe("tryFallbackRetry", () => {
}) })
describe("#given disconnected fallback providers with connected preferred provider", () => { describe("#given disconnected fallback providers with connected preferred provider", () => {
test("keeps fallback entry and selects connected preferred provider", async () => { test("skips explicit-provider fallback entries when none of their providers are connected", async () => {
readProviderModelsCacheMock.mockReturnValueOnce({ readProviderModelsCacheMock.mockReturnValueOnce({
connected: ["provider-a"], connected: ["provider-a"],
models: {}, models: {},
updatedAt: new Date("2026-05-16T00:00:00.000Z").toISOString(), updatedAt: new Date("2026-05-16T00:00:00.000Z").toISOString(),
}) })
selectFallbackProviderMock.mockImplementationOnce(
(_providers: string[], preferredProviderID?: string) => preferredProviderID ?? "provider-b",
)
const args = createDefaultArgs({ const args = createDefaultArgs({
fallbackChain: [{ model: "fallback-model-1", providers: ["provider-b"], variant: undefined }], fallbackChain: [{ model: "fallback-model-1", providers: ["provider-b"], variant: undefined }],
model: { providerID: "provider-a", modelID: "original-model" }, model: { providerID: "provider-a", modelID: "original-model" },
}) })
const providerCallsBefore = selectFallbackProviderMock.mock.calls.length
const result = await tryFallbackRetry(args) const result = await tryFallbackRetry(args)
expect(result).toBe(true) expect(result).toBe(false)
expect(args.task.model?.providerID).toBe("provider-a") expect(args.task.model?.providerID).toBe("provider-a")
expect(args.task.model?.modelID).toBe("fallback-model-1") expect(args.task.model?.modelID).toBe("original-model")
expect(selectFallbackProviderMock.mock.calls.length).toBe(providerCallsBefore)
}) })
}) })
@@ -80,14 +80,10 @@ export async function tryFallbackRetry(args: {
const providerModelsCache = deps.readProviderModelsCache() const providerModelsCache = deps.readProviderModelsCache()
const connectedProviders = providerModelsCache?.connected ?? deps.readConnectedProvidersCache() const connectedProviders = providerModelsCache?.connected ?? deps.readConnectedProvidersCache()
const connectedSet = connectedProviders ? new Set(connectedProviders.map(p => p.toLowerCase())) : null const connectedSet = connectedProviders ? new Set(connectedProviders.map(p => p.toLowerCase())) : null
const preferredProvider = task.model?.providerID?.toLowerCase()
const isReachable = (entry: FallbackEntry): boolean => { const isReachable = (entry: FallbackEntry): boolean => {
if (!connectedSet) return true if (!connectedSet) return true
if (entry.providers.some((provider) => connectedSet.has(provider.toLowerCase()))) { return entry.providers.some((provider) => connectedSet.has(provider.toLowerCase()))
return true
}
return preferredProvider ? connectedSet.has(preferredProvider) : false
} }
let selectedAttemptCount = attemptCount let selectedAttemptCount = attemptCount