feat: implement session search IPC flow and MCP tool (#909, #908)#1027
feat: implement session search IPC flow and MCP tool (#909, #908)#1027kianwoon wants to merge 7 commits intoqwibitai:mainfrom
Conversation
When the SDK returns multiple streaming results, all of them were being sent to the user, causing duplicate/confusing replies. This fix tracks the last output and sends only that after streaming completes. Changes: - Added `lastOutput` variable to track the final result - Modified streaming callback to update `lastOutput` instead of sending immediately - Added post-streaming send of only the last output Fixes qwibitai#1020
…wibitai#908) Implements FTS5 conversation search with IPC/MCP integration: **Issue qwibitai#908 - FTS5 conversation indexing and search:** - Add conversations table and conversations_fts FTS5 virtual table - Implement indexConversations(groupFolder) for incremental indexing - Implement searchConversations(groupFolder, query, limit) for FTS5 search **Issue qwibitai#909 - Session search IPC flow:** - Add search-requests/ and search-responses/ IPC directories - Host IPC watcher processes session_search requests - Add session_search MCP tool with 10s timeout - Trigger conversation indexing before agent spawn **Files modified:** - src/db.ts: FTS5 schema and search functions - src/ipc.ts: Session search IPC handler - src/container-runner.ts: Indexing trigger before agent spawn - container/agent-runner/src/ipc-mcp-stdio.ts: session_search MCP tool Closes qwibitai#908, qwibitai#909
Dhebrank
left a comment
There was a problem hiding this comment.
Review: Request Changes
Good FTS5 infrastructure and IPC round-trip design, but several issues need addressing.
Critical:
- Same "last output only" regression as #1022. The
index.tschanges suppress all intermediate streaming outputs, only sending the final result. This breaks multi-message responses and theoutputSentToUserflag (set before anything is actually sent, which breaks error recovery/cursor rollback).
High:
-
Tool name collision. A
search_conversationsMCP tool already exists (vector search + LLM synthesis). This PR addssession_search(FTS5 keyword search) with overlapping purpose. The agent has to guess which to call. Reconcile or clearly differentiate. -
Stale content never re-indexed.
INSERT OR IGNOREskips files already indexed. If a conversation file is modified after initial indexing, FTS content becomes stale. Track file mtime or useINSERT OR REPLACE. -
indexedCountalways equals total files.INSERT OR IGNORE+ unconditional increment means the count reflects all files, not newly indexed ones. Checkrun().changes > 0.
Medium:
-
Missing FTS5 UPDATE trigger. Schema has
conversations_ai(after insert) andconversations_ad(after delete) but noconversations_au(after update). Standard FTS5 content-sync requires all three. -
mkdirSyncon every poll cycle for search-responses dir. Move inside the existence check or pre-create inbuildVolumeMounts. -
No ENOENT guard on search request file reads (other IPC handlers have this).
The FTS5 search and IPC round-trip architecture are solid — just needs the output regression fixed and the tool collision resolved.
Addresses review feedback on qwibitai#1022. The previous "last output only" fix had three critical issues: 1. Dropped all intermediate results (distinct messages were lost) 2. outputSentToUser flag was set before anything was actually sent 3. Degraded streaming UX (users saw nothing until completion) New approach: Content-based deduplication - Sends messages immediately (restoring streaming UX) - Only skips if current message exactly matches the last sent - Preserves all distinct outputs from the agent - outputSentToUser flag now correctly set only on actual send Fixes qwibitai#1020
Addresses Dhebrank's review feedback on session search IPC feature. **Critical (Already Fixed in Previous Commit):** - Same "last output only" regression as qwibitai#1022 - Fixed by content deduplication **High Priority:** - Tool name collision - Renamed `session_search` to `search_session_fts` with clarifying description - Stale content re-indexing - Added `file_mtime` column, use INSERT OR REPLACE - indexedCount bug - Only count when run().changes > 0 **Medium Priority:** - Missing FTS5 UPDATE trigger - Added `conversations_au` trigger for UPDATE operations - mkdirSync on every poll cycle - Moved inside existence check - No ENOENT guard - Added ENOENT handling for disappeared files **Files Modified:** - src/db.ts: Added file_mtime column, UPDATE trigger, fixed counting logic - src/ipc.ts: Fixed mkdirSync placement, added ENOENT guard - container/agent-runner/src/ipc-mcp-stdio.ts: Renamed tool, clarified description All 201 tests pass.
|
@Dhebrank Thanks for the detailed review. I've addressed all the issues you raised. Changes MadeCritical (Already Fixed in Previous Commit
High Priority:
Medium Priority:
Database Schema Changes-- Added file_mtime column for change detection
ALTER TABLE conversations ADD COLUMN file_mtime REAL NOT NULL;
-- Added missing UPDATE trigger for FTS5 sync
CREATE TRIGGER conversations_au AFTER UPDATE ON conversations BEGIN
INSERT INTO conversations_fts(conversations_fts, rowid, content) VALUES('delete', old.id, old.content);
INSERT INTO conversations_fts(rowid, content) VALUES (new.id, new.content);
END;All 201 tests pass. The fix is committed on |
Summary
Implements FTS5 conversation search with IPC/MCP integration, addressing both Issue #908 (FTS5 conversation indexing and search) and Issue #909 (Session search IPC flow and MCP tool).
Changes
Issue #908 - FTS5 Conversation Indexing and Search
src/db.ts:conversationstable with columns: id, group_folder, filename, date, content, indexed_atconversations_ftsFTS5 virtual table for full-text searchindexConversations(groupFolder)- scansgroups/{folder}/conversations/*.md, skips already-indexed filessearchConversations(groupFolder, query, limit)- performs FTS5 MATCH query, returns{filename, date, snippet}[]Issue #909 - Session Search IPC Flow
src/ipc.ts- Host-side IPC handler:search-requests/directory alongside existingmessages/andtasks/searchConversations(), writes response JSON{request_id, results: [{filename, date, snippet}]}container/agent-runner/src/ipc-mcp-stdio.ts- Container-side MCP tool:session_search(query, limit?)MCP tool/workspace/ipc/search-requests/{requestId}.json/workspace/ipc/search-responses/{requestId}.jsonwith 10s timeoutsrc/container-runner.ts- Indexing trigger:indexConversations(groupFolder)before spawning container processTesting
npm run buildsucceeds for host processFiles Modified
src/db.ts- FTS5 schema and search functionssrc/ipc.ts- Session search IPC handlersrc/container-runner.ts- Indexing trigger before agent spawncontainer/agent-runner/src/ipc-mcp-stdio.ts- session_search MCP toolDefinition of Done
npm run buildsucceeds for hostCloses #908, #909