diff --git a/web/src/lib/env-state.test.ts b/web/src/lib/env-state.test.ts new file mode 100644 index 0000000000..176b57aa47 --- /dev/null +++ b/web/src/lib/env-state.test.ts @@ -0,0 +1,44 @@ +import { describe, expect, it } from "vitest"; + +import type { EnvVarInfo } from "./api"; +import { removeDeletedEnvVarFromState } from "./env-state"; + +function envVar(overrides: Partial = {}): EnvVarInfo { + return { + is_set: true, + redacted_value: "secr...alue", + description: "", + url: null, + category: "provider", + is_password: true, + tools: [], + advanced: false, + ...overrides, + }; +} + +describe("removeDeletedEnvVarFromState", () => { + it("removes a deleted custom key from dashboard state", () => { + const vars = { + WHATSAPP_DEBUG: envVar({ category: "custom", custom: true }), + OPENAI_API_KEY: envVar(), + }; + + const updated = removeDeletedEnvVarFromState(vars, "WHATSAPP_DEBUG"); + + expect(updated).not.toHaveProperty("WHATSAPP_DEBUG"); + expect(updated?.OPENAI_API_KEY).toBe(vars.OPENAI_API_KEY); + }); + + it("keeps a catalog key available while marking it unset", () => { + const vars = { OPENAI_API_KEY: envVar() }; + + const updated = removeDeletedEnvVarFromState(vars, "OPENAI_API_KEY"); + + expect(updated?.OPENAI_API_KEY).toEqual({ + ...vars.OPENAI_API_KEY, + is_set: false, + redacted_value: null, + }); + }); +}); diff --git a/web/src/lib/env-state.ts b/web/src/lib/env-state.ts new file mode 100644 index 0000000000..3116be949f --- /dev/null +++ b/web/src/lib/env-state.ts @@ -0,0 +1,21 @@ +import type { EnvVarInfo } from "./api"; + +/** Reconcile a successful DELETE /api/env response with the Keys page state. */ +export function removeDeletedEnvVarFromState( + vars: Record | null, + key: string, +): Record | null { + const info = vars?.[key]; + if (!vars || !info) return vars; + + if (info.custom) { + const updated = { ...vars }; + delete updated[key]; + return updated; + } + + return { + ...vars, + [key]: { ...info, is_set: false, redacted_value: null }, + }; +} diff --git a/web/src/pages/EnvPage.tsx b/web/src/pages/EnvPage.tsx index edcc45844c..78e2266fed 100644 --- a/web/src/pages/EnvPage.tsx +++ b/web/src/pages/EnvPage.tsx @@ -17,6 +17,7 @@ import { } from "lucide-react"; import { api } from "@/lib/api"; import type { EnvVarInfo } from "@/lib/api"; +import { removeDeletedEnvVarFromState } from "@/lib/env-state"; import { DeleteConfirmDialog } from "@/components/DeleteConfirmDialog"; import { Toast } from "@nous-research/ui/ui/components/toast"; import { useConfirmDelete } from "@nous-research/ui/hooks/use-confirm-delete"; @@ -722,14 +723,7 @@ export default function EnvPage() { setSaving(key); try { await api.deleteEnvVar(key); - setVars((prev) => - prev - ? { - ...prev, - [key]: { ...prev[key], is_set: false, redacted_value: null }, - } - : prev, - ); + setVars((prev) => removeDeletedEnvVarFromState(prev, key)); setEdits((prev) => { const n = { ...prev }; delete n[key];