From 5fa3dbd2cf19c19da132b7d1c0b9dbaa9c1cef20 Mon Sep 17 00:00:00 2001 From: Sulthan Nauval Abdillah Date: Tue, 11 Aug 2026 01:03:00 +0000 Subject: [PATCH] fix(ops): KB panel must not fetch groups while deactivated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - the plan-106 gate stopped RENDERING the library while off, but the kbGroups useAsync lived in KbPanel itself and hooks fire on mount regardless of what is returned — the doomed request still went out (503) exactly as before; caught by the live browser drive, which asserts on the network log, not the DOM - the library (groups fetch + selection state + Documents/Graph) moves to a child KbPanelBody mounted only when the KB is enabled, so the request cannot exist while off - full activation-flow drive against a real gateway + probe mock now passes: off shows the activation card with NO kb/groups call from the panel, bad key surfaces the probe 400 inline and persists nothing, good key activates and mounts the library (groups 200), deactivate keeps the credential, reactivate is one click, remove-key returns to the empty inputs - the remaining page-load kb/groups 503 comes from console-shell's chat KB selector prefetch, which is deliberately fail-soft (.catch(() => {})) and renders no error — out of this fix's scope --- src/components/ops/kb-panel.tsx | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/components/ops/kb-panel.tsx b/src/components/ops/kb-panel.tsx index f9d56c3..091b662 100644 --- a/src/components/ops/kb-panel.tsx +++ b/src/components/ops/kb-panel.tsx @@ -71,14 +71,27 @@ const errMsg = (e: unknown) => (e instanceof Error ? e.message : String(e)); type LibraryView = "documents" | "graph"; export function KbPanel() { - // Gate on activation BEFORE mounting the library: KbList fetches on mount - // and a 503 from a disabled/keyless KB stacked error panels under the - // activation card (plan 106). Older gateways omit `enabled`; treat - // configured-as-enabled there. + // Gate on activation BEFORE mounting the library. The library lives in a + // CHILD component (KbPanelBody) because hooks fire on mount regardless of + // what is rendered — a `useAsync(kbGroups)` in THIS component would fetch + // even while the early-return shows only the activation card. Caught by + // the live browser drive: the render was gated but the request was not + // (plan 106 requires no kb/groups call while off). Older gateways omit + // `enabled`; treat configured-as-enabled there. const kbStatus = useAsync(() => api.getKnowledge(), []); const kbEnabled = kbStatus.data ? (kbStatus.data.enabled ?? kbStatus.data.embedding_configured) : false; + + if (kbStatus.loading) return null; + if (!kbEnabled) { + // Activation screen only — no Documents/Graph chrome, no doomed fetches. + return ; + } + return ; +} + +function KbPanelBody({ onStatusChanged }: { onStatusChanged: () => void }) { const groups = useAsync(() => api.kbGroups(), []); const [selected, setSelected] = React.useState(null); const [view, setView] = React.useState("documents"); @@ -93,15 +106,9 @@ export function KbPanel() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [groups.data]); - if (kbStatus.loading) return null; - if (!kbEnabled) { - // Activation screen only — no Documents/Graph chrome, no doomed fetches. - return ; - } - return (
- +