Skip to content

feat: implement session search IPC flow and MCP tool (#909, #908)#1027

Open
kianwoon wants to merge 7 commits intoqwibitai:mainfrom
kianwoon:feat/session-search-ipc-909
Open

feat: implement session search IPC flow and MCP tool (#909, #908)#1027
kianwoon wants to merge 7 commits intoqwibitai:mainfrom
kianwoon:feat/session-search-ipc-909

Conversation

@kianwoon
Copy link

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:

  • ✅ Added conversations table with columns: id, group_folder, filename, date, content, indexed_at
  • ✅ Added conversations_fts FTS5 virtual table for full-text search
  • ✅ Added triggers to keep FTS index in sync automatically
  • ✅ Implemented indexConversations(groupFolder) - scans groups/{folder}/conversations/*.md, skips already-indexed files
  • ✅ Implemented searchConversations(groupFolder, query, limit) - performs FTS5 MATCH query, returns {filename, date, snippet}[]

Issue #909 - Session Search IPC Flow

src/ipc.ts - Host-side IPC handler:

  • ✅ Added processing for search-requests/ directory alongside existing messages/ and tasks/
  • ✅ Host reads search requests, calls searchConversations(), writes response JSON
  • ✅ Response format: {request_id, results: [{filename, date, snippet}]}
  • ✅ Proper error handling and logging

container/agent-runner/src/ipc-mcp-stdio.ts - Container-side MCP tool:

  • ✅ Added session_search(query, limit?) MCP tool
  • ✅ Writes request to /workspace/ipc/search-requests/{requestId}.json
  • ✅ Polls /workspace/ipc/search-responses/{requestId}.json with 10s timeout
  • ✅ Returns formatted results or timeout error

src/container-runner.ts - Indexing trigger:

  • ✅ Calls indexConversations(groupFolder) before spawning container process
  • ✅ Wrapped in try-catch for graceful degradation (indexing failures don't block agents)

Testing

  • npm run build succeeds for host process
  • ✅ All TypeScript types properly defined
  • ✅ Follows existing IPC patterns (messages, tasks) for consistency

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

Definition of Done

  • ✅ IPC request/response flow works end-to-end
  • ✅ MCP tool returns search results to agent
  • ✅ Timeout handling prevents agent from hanging
  • npm run build succeeds for host
  • ✅ Conversation indexing runs automatically before agent invocation

Closes #908, #909

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
@Andy-NanoClaw-AI Andy-NanoClaw-AI added Status: Needs Review Ready for maintainer review PR: Feature New feature or enhancement labels Mar 13, 2026
Copy link

@Dhebrank Dhebrank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Request Changes

Good FTS5 infrastructure and IPC round-trip design, but several issues need addressing.

Critical:

  1. Same "last output only" regression as #1022. The index.ts changes suppress all intermediate streaming outputs, only sending the final result. This breaks multi-message responses and the outputSentToUser flag (set before anything is actually sent, which breaks error recovery/cursor rollback).

High:

  1. Tool name collision. A search_conversations MCP tool already exists (vector search + LLM synthesis). This PR adds session_search (FTS5 keyword search) with overlapping purpose. The agent has to guess which to call. Reconcile or clearly differentiate.

  2. Stale content never re-indexed. INSERT OR IGNORE skips files already indexed. If a conversation file is modified after initial indexing, FTS content becomes stale. Track file mtime or use INSERT OR REPLACE.

  3. indexedCount always equals total files. INSERT OR IGNORE + unconditional increment means the count reflects all files, not newly indexed ones. Check run().changes > 0.

Medium:

  1. Missing FTS5 UPDATE trigger. Schema has conversations_ai (after insert) and conversations_ad (after delete) but no conversations_au (after update). Standard FTS5 content-sync requires all three.

  2. mkdirSync on every poll cycle for search-responses dir. Move inside the existence check or pre-create in buildVolumeMounts.

  3. 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.
@kianwoon
Copy link
Author

@Dhebrank Thanks for the detailed review. I've addressed all the issues you raised.

Changes Made

Critical (Already Fixed in Previous Commit 72eaa7a):

High Priority:

  • Tool name collision — Renamed session_searchsearch_session_fts with description clarifying it's keyword/FTS5 search vs semantic search
  • Stale content re-indexing — Added file_mtime column to track file modifications, using INSERT OR REPLACE
  • indexedCount bug — Now only counts when run().changes > 0 (actual new/updated files)

Medium Priority:

  • Missing FTS5 UPDATE trigger — Added conversations_au trigger for standard FTS5 content-sync
  • mkdirSync on every poll cycle — Moved inside existence check (only create when processing requests)
  • No ENOENT guard — Added ENOENT handling for files that disappear between readdir and read

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 feat/session-search-ipc-909 branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR: Feature New feature or enhancement Status: Needs Review Ready for maintainer review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FTS5 conversation indexing and search

3 participants