From f27db3036a33bcc9376b7be6fc6d676c8fa6fdc6 Mon Sep 17 00:00:00 2001 From: cl1107 Date: Wed, 22 Apr 2026 14:00:34 +0800 Subject: [PATCH] feat: add session search modal (#128) --- packages/client/src/App.vue | 2 + packages/client/src/api/hermes/sessions.ts | 17 + .../components/hermes/chat/MessageItem.vue | 14 +- .../components/hermes/chat/MessageList.vue | 39 +- .../hermes/chat/SessionSearchModal.vue | 435 ++++++++++++++++++ .../src/components/layout/AppSidebar.vue | 13 +- .../client/src/composables/useKeyboard.ts | 16 + .../src/composables/useSessionSearch.ts | 19 + packages/client/src/i18n/locales/en.ts | 11 + packages/client/src/i18n/locales/zh.ts | 11 + packages/client/src/stores/hermes/chat.ts | 5 +- .../server/src/controllers/hermes/sessions.ts | 19 +- packages/server/src/routes/hermes/sessions.ts | 2 + .../server/src/services/hermes/sessions-db.ts | 287 ++++++++++-- tests/client/session-search.test.ts | 211 +++++++++ tests/client/sidebar-search.test.ts | 93 ++++ tests/server/sessions-db.test.ts | 153 +++++- tests/server/sessions-routes.test.ts | 134 +++--- 18 files changed, 1355 insertions(+), 126 deletions(-) create mode 100644 packages/client/src/components/hermes/chat/SessionSearchModal.vue create mode 100644 packages/client/src/composables/useSessionSearch.ts create mode 100644 tests/client/session-search.test.ts create mode 100644 tests/client/sidebar-search.test.ts diff --git a/packages/client/src/App.vue b/packages/client/src/App.vue index 6fcfcd99..f5d58f0b 100644 --- a/packages/client/src/App.vue +++ b/packages/client/src/App.vue @@ -7,6 +7,7 @@ import { useTheme } from '@/composables/useTheme' import AppSidebar from '@/components/layout/AppSidebar.vue' import { useKeyboard } from '@/composables/useKeyboard' import { useAppStore } from '@/stores/hermes/app' +import SessionSearchModal from '@/components/hermes/chat/SessionSearchModal.vue' const { isDark } = useTheme() const appStore = useAppStore() @@ -58,6 +59,7 @@ useKeyboard() + diff --git a/packages/client/src/api/hermes/sessions.ts b/packages/client/src/api/hermes/sessions.ts index 1201ac12..240477b4 100644 --- a/packages/client/src/api/hermes/sessions.ts +++ b/packages/client/src/api/hermes/sessions.ts @@ -5,6 +5,7 @@ export interface SessionSummary { source: string model: string title: string | null + preview?: string started_at: number ended_at: number | null last_active?: number @@ -25,6 +26,12 @@ export interface SessionDetail extends SessionSummary { messages: HermesMessage[] } +export interface SessionSearchResult extends SessionSummary { + matched_message_id: number | null + snippet: string + rank: number +} + export interface HermesMessage { id: number session_id: string @@ -48,6 +55,16 @@ export async function fetchSessions(source?: string, limit?: number): Promise { + const params = new URLSearchParams() + params.set('q', q) + if (source) params.set('source', source) + if (limit) params.set('limit', String(limit)) + const query = params.toString() + const res = await request<{ results: SessionSearchResult[] }>(`/api/hermes/search/sessions?${query}`) + return res.results +} + export async function fetchSession(id: string): Promise { try { const res = await request<{ session: SessionDetail }>(`/api/hermes/sessions/${id}`) diff --git a/packages/client/src/components/hermes/chat/MessageItem.vue b/packages/client/src/components/hermes/chat/MessageItem.vue index ffd6a19d..b23adcae 100644 --- a/packages/client/src/components/hermes/chat/MessageItem.vue +++ b/packages/client/src/components/hermes/chat/MessageItem.vue @@ -11,7 +11,7 @@ import { const TOOL_PAYLOAD_DISPLAY_LIMIT = 2000; -const props = defineProps<{ message: Message }>(); +const props = defineProps<{ message: Message; highlight?: boolean }>(); const { t } = useI18n(); const isSystem = computed(() => props.message.role === "system"); @@ -126,7 +126,11 @@ const renderedToolResult = computed(() => {