mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-03-09 16:07:49 +00:00
* 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
55 lines
1.8 KiB
JavaScript
55 lines
1.8 KiB
JavaScript
import express from 'express';
|
|
import sessionManager from '../sessionManager.js';
|
|
import { sessionNamesDb } from '../database/db.js';
|
|
import { getGeminiCliSessionMessages } from '../projects.js';
|
|
|
|
const router = express.Router();
|
|
|
|
router.get('/sessions/:sessionId/messages', async (req, res) => {
|
|
try {
|
|
const { sessionId } = req.params;
|
|
|
|
if (!sessionId || typeof sessionId !== 'string' || !/^[a-zA-Z0-9_.-]{1,100}$/.test(sessionId)) {
|
|
return res.status(400).json({ success: false, error: 'Invalid session ID format' });
|
|
}
|
|
|
|
let messages = sessionManager.getSessionMessages(sessionId);
|
|
|
|
// Fallback to Gemini CLI sessions on disk
|
|
if (messages.length === 0) {
|
|
messages = await getGeminiCliSessionMessages(sessionId);
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
messages: messages,
|
|
total: messages.length,
|
|
hasMore: false,
|
|
offset: 0,
|
|
limit: messages.length
|
|
});
|
|
} catch (error) {
|
|
console.error('Error fetching Gemini session messages:', error);
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
router.delete('/sessions/:sessionId', async (req, res) => {
|
|
try {
|
|
const { sessionId } = req.params;
|
|
|
|
if (!sessionId || typeof sessionId !== 'string' || !/^[a-zA-Z0-9_.-]{1,100}$/.test(sessionId)) {
|
|
return res.status(400).json({ success: false, error: 'Invalid session ID format' });
|
|
}
|
|
|
|
await sessionManager.deleteSession(sessionId);
|
|
sessionNamesDb.deleteName(sessionId, 'gemini');
|
|
res.json({ success: true });
|
|
} catch (error) {
|
|
console.error(`Error deleting Gemini session ${req.params.sessionId}:`, error);
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
export default router;
|