diff --git a/src/app/api/insights/provider-chain/__tests__/put.test.ts b/src/app/api/insights/provider-chain/__tests__/put.test.ts index 7721d1d46..510fa5fe7 100644 --- a/src/app/api/insights/provider-chain/__tests__/put.test.ts +++ b/src/app/api/insights/provider-chain/__tests__/put.test.ts @@ -61,8 +61,14 @@ vi.mock("@/lib/logging/context", () => ({ annotate: vi.fn(), })); +vi.mock("@/lib/ai/provider-runner", () => ({ + getLastWorkingProvider: vi.fn(), + forgetLastWorkingProvider: vi.fn(), +})); + import { PUT } from "../route"; import { prisma } from "@/lib/db"; +import { forgetLastWorkingProvider } from "@/lib/ai/provider-runner"; import { annotate } from "@/lib/logging/context"; interface Envelope { @@ -108,6 +114,9 @@ describe("PUT /api/insights/provider-chain", () => { ], }); expect(annotate).toHaveBeenCalled(); + // The remembered working provider would reorder the chain the person + // just arranged; a save drops it for this account. + expect(forgetLastWorkingProvider).toHaveBeenCalledWith("u-1"); }); it("rejects unknown provider types with 422", async () => { diff --git a/src/app/api/insights/provider-chain/__tests__/route.test.ts b/src/app/api/insights/provider-chain/__tests__/route.test.ts index fff8209ea..efb66afab 100644 --- a/src/app/api/insights/provider-chain/__tests__/route.test.ts +++ b/src/app/api/insights/provider-chain/__tests__/route.test.ts @@ -30,6 +30,7 @@ vi.mock("@/lib/ai/provider", () => ({ vi.mock("@/lib/ai/provider-runner", () => ({ getLastWorkingProvider: vi.fn(), + forgetLastWorkingProvider: vi.fn(), })); vi.mock("@/lib/logging/context", () => ({ diff --git a/src/app/api/insights/provider-chain/route.ts b/src/app/api/insights/provider-chain/route.ts index b5afc4379..8ea535990 100644 --- a/src/app/api/insights/provider-chain/route.ts +++ b/src/app/api/insights/provider-chain/route.ts @@ -10,7 +10,10 @@ import { } from "@/lib/api-response"; import { annotate } from "@/lib/logging/context"; import { resolveProviderChain } from "@/lib/ai/provider"; -import { getLastWorkingProvider } from "@/lib/ai/provider-runner"; +import { + forgetLastWorkingProvider, + getLastWorkingProvider, +} from "@/lib/ai/provider-runner"; import { prisma } from "@/lib/db"; import { parseProviderChain, @@ -149,6 +152,7 @@ export const PUT = apiHandler(async (request: NextRequest) => { where: { id: user.id }, data: { aiProviderChain: normalised }, }); + forgetLastWorkingProvider(user.id); annotate({ meta: { diff --git a/src/lib/ai/provider-runner.ts b/src/lib/ai/provider-runner.ts index 37270e54f..7bf914106 100644 --- a/src/lib/ai/provider-runner.ts +++ b/src/lib/ai/provider-runner.ts @@ -98,6 +98,15 @@ export function getLastWorkingProvider( return entry.providerType; } +/** + * Drop one user's "last working provider" memo. Called when the person saves + * a new chain: the memo reorders the chain they just arranged, and a provider + * they removed or disabled must not keep leading it for up to an hour. + */ +export function forgetLastWorkingProvider(userId: string): void { + lastWorkingCache.delete(userId); +} + function rememberWorkingProvider( userId: string, providerType: ProviderChainType,