From 633a3c35003a6824c83d7d5cbf5416896ff771f2 Mon Sep 17 00:00:00 2001 From: Chris Sherwood Date: Sun, 17 May 2026 11:10:16 -0700 Subject: [PATCH] fix(KB): blank-screen on panel open + tooltips on bulk-action buttons The Stored Knowledge Base Files render crashed on first open in v1.32.0-rc.5 with `ReferenceError: sourceToDisplayName is not defined`. The table column's render() called `sourceToDisplayName(record.source)` but the function was extracted to `lib/kb_file_grouping.ts` in PR #892 and never imported in KnowledgeBaseModal.tsx. The unhandled error unmounts the entire React tree, so users see a blank screen ~20s after opening the panel. Root cause: PR #895 (conditional warnings) rewrote the render() and used `sourceToDisplayName(record.source)` instead of `record.displayName`, which KbFileGroup already carries from groupAndSortKbFiles(). PR #895's review follow-up (cbae48a) compounded this by narrowing the StyledTable generic from `KbFileGroup` to `{source: string}`, hiding the type drift from tsc. This restores the post-#892 pattern: - StyledTable generic back to `KbFileGroup` - Render uses `record.displayName` (works for both per-file rows and the collapsed admin-docs row; calling sourceToDisplayName on the synthetic `__admin_docs_group__` would have rendered that literal as the row name). Also folds in tooltip copy on the three bulk-action buttons (Reset & Rebuild, Re-embed All, Sync Storage) so the difference in destructiveness is visible on hover. Uses native `title` attribute via StyledButton's prop pass-through; no new component dependency. Inertia tsconfig catches this regression cleanly (TS2304 + TS2339); the pre-push hook only runs the backend tsconfig which excludes inertia/**, so the bug shipped. Tracking the typecheck-coverage gap as a follow-up. Co-Authored-By: Claude Opus 4.7 (1M context) --- admin/inertia/components/chat/KnowledgeBaseModal.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/admin/inertia/components/chat/KnowledgeBaseModal.tsx b/admin/inertia/components/chat/KnowledgeBaseModal.tsx index 0667d88..dadfb3f 100644 --- a/admin/inertia/components/chat/KnowledgeBaseModal.tsx +++ b/admin/inertia/components/chat/KnowledgeBaseModal.tsx @@ -420,6 +420,7 @@ export default function KnowledgeBaseModal({ aiAssistantName = "AI Assistant", o onClick={() => { setResetTyped(''); setBulkMode('reset') }} disabled={isUploading || qdrantOffline || bulkBusy} loading={resetMutation.isPending} + title="Drop the entire embeddings collection and re-embed everything from scratch. Permanently removes vectors for files no longer on disk. Destructive: requires typing RESET to confirm." > Reset & Rebuild @@ -430,6 +431,7 @@ export default function KnowledgeBaseModal({ aiAssistantName = "AI Assistant", o onClick={() => setBulkMode('reembed')} disabled={isUploading || qdrantOffline || bulkBusy || storedFiles.length === 0} loading={reembedMutation.isPending} + title="Re-embed every file on disk, replacing existing vectors file-by-file. Vectors for files no longer on disk are preserved. Use this if the chunker or embedding model has changed." > Re-embed All @@ -440,6 +442,7 @@ export default function KnowledgeBaseModal({ aiAssistantName = "AI Assistant", o onClick={handleConfirmSync} disabled={syncMutation.isPending || isUploading || qdrantOffline || bulkBusy} loading={syncMutation.isPending || isUploading} + title="Scan storage for new files and queue any that haven't been embedded yet. Safe to run anytime; won't touch already-embedded content." > Sync Storage @@ -454,7 +457,7 @@ export default function KnowledgeBaseModal({ aiAssistantName = "AI Assistant", o )} - + className="font-semibold" rowLines={true} columns={[ @@ -466,7 +469,7 @@ export default function KnowledgeBaseModal({ aiAssistantName = "AI Assistant", o return (
- {sourceToDisplayName(record.source)} + {record.displayName} {warnings.map((w, i) => (