mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-06-03 02:55:39 +08:00
feat: add full-text search across conversations (#482)
* feat: add full-text search across conversations in sidebar Add a search mode toggle (Projects/Conversations) to the sidebar search bar. In Conversations mode, search text content across all JSONL session files with debounced API calls, highlighted snippets, and click-to-navigate results. * fix: address PR review feedback - session summary tracking, search sequence invalidation, fallback navigation, SSE streaming - Track session summaries per-session in a Map instead of file-scoped variable - Increment searchSeqRef when clearing conversation search to invalidate in-flight requests - Add fallback session navigation when session not loaded in sidebar paging - Stream search results via SSE for progressive display with progress indicator * feat(search): add Codex/Gemini search and scroll-to-message navigation - Search now includes Codex sessions (JSONL from ~/.codex/sessions/) and Gemini sessions (in-memory via sessionManager) in addition to Claude - Search results include provider info and display a provider badge - Click handler resolves the correct provider instead of hardcoding claude - Clicking a search result loads all messages and scrolls to the matched message with a highlight flash animation * fix(search): Codex search path matching and scroll reliability - Fix Codex search scanning all sessions for every project by checking session_meta cwd match BEFORE scanning messages (was inflating match count and hitting limit before reaching later projects) - Fix Codex search missing user messages in response_item entries (role=user with input_text content parts) - Fix scroll-to-message being overridden by initial scrollToBottom using searchScrollActiveRef to inhibit competing scroll effects - Fix snippet matching using contiguous substring instead of filtered words (which created non-existent phrases) * feat(search): add Gemini CLI session support for search and history viewing Gemini CLI sessions stored in ~/.gemini/tmp/<project>/chats/*.json are now indexed for conversation search and can be loaded for viewing. Previously only sessions created through the UI (sessionManager) were searchable. * fix(search): full-word matching and longer highlight flash - Search now uses word boundaries (\b) instead of substring matching, so "hi" no longer matches "this" - Highlight flash extended to 4s with thicker outline and subtle background tint for better visibility
This commit is contained in:
@@ -60,6 +60,12 @@ function Sidebar({
|
||||
editingSession,
|
||||
editingSessionName,
|
||||
searchFilter,
|
||||
searchMode,
|
||||
setSearchMode,
|
||||
conversationResults,
|
||||
isSearching,
|
||||
searchProgress,
|
||||
clearConversationResults,
|
||||
deletingProjects,
|
||||
deleteConfirmation,
|
||||
sessionDeleteConfirmation,
|
||||
@@ -220,6 +226,37 @@ function Sidebar({
|
||||
searchFilter={searchFilter}
|
||||
onSearchFilterChange={setSearchFilter}
|
||||
onClearSearchFilter={() => setSearchFilter('')}
|
||||
searchMode={searchMode}
|
||||
onSearchModeChange={(mode: 'projects' | 'conversations') => {
|
||||
setSearchMode(mode);
|
||||
if (mode === 'projects') clearConversationResults();
|
||||
}}
|
||||
conversationResults={conversationResults}
|
||||
isSearching={isSearching}
|
||||
searchProgress={searchProgress}
|
||||
onConversationResultClick={(projectName: string, sessionId: string, provider: string, messageTimestamp?: string | null, messageSnippet?: string | null) => {
|
||||
const resolvedProvider = (provider || 'claude') as SessionProvider;
|
||||
const project = projects.find(p => p.name === projectName);
|
||||
const searchTarget = { __searchTargetTimestamp: messageTimestamp || null, __searchTargetSnippet: messageSnippet || null };
|
||||
const sessionObj = {
|
||||
id: sessionId,
|
||||
__provider: resolvedProvider,
|
||||
__projectName: projectName,
|
||||
...searchTarget,
|
||||
};
|
||||
if (project) {
|
||||
handleProjectSelect(project);
|
||||
const sessions = getProjectSessions(project);
|
||||
const existing = sessions.find(s => s.id === sessionId);
|
||||
if (existing) {
|
||||
handleSessionClick({ ...existing, ...searchTarget }, projectName);
|
||||
} else {
|
||||
handleSessionClick(sessionObj, projectName);
|
||||
}
|
||||
} else {
|
||||
handleSessionClick(sessionObj, projectName);
|
||||
}
|
||||
}}
|
||||
onRefresh={() => {
|
||||
void refreshProjects();
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user