Skip to content

feat(web): knowledge graph search — expose read_memory to the human UI #42

@Flare576

Description

@Flare576

Summary

The read_memory tool already performs semantic search across the knowledge graph (facts, topics, people, quotes) — personas use it automatically, and coding tools get it via CLI/MCP. The human sitting in the web UI has never had access to it. This is the feature that replaces Ctrl+F with something qualitatively better.

The Problem with Ctrl+F

Virtualized message lists (added in feat/virtual-scroll) make native browser search impossible — only rendered DOM nodes are searchable. But Ctrl+F was always a bandage. If you have 500 messages with Lena and want "that thing she said about startups," you're doing archaeology. What you actually want is "find the Quote Lena has about startups, and what Topics it connects to."

The Opportunity

Messages are the raw material. The real search surface is:

Entity What you find
Quotes Memorable things said, with source message attribution
Facts Things Ei knows about you, with confidence scores
Topics Subjects with perspective, stake, sentiment
People Friends, family, colleagues Ei has learned about

These are already extracted, stored, and semantically indexed. We just never gave the human a way to query them.

UX Model

Reddit-style scope toggle:

🔍 [search query________________]
   ● Search Lena's memory  ○ Search all of Ei

Scoped to a persona = the existing read_memory with the persona filter.
Global = read_memory across the full human entity.

Entry point: Global keyboard shortcut (Cmd+K / Ctrl+F intercept when chat is focused).

Results: Cards grouped by entity type — Quotes first (most conversational), then Facts, Topics, People. Each card shows match context and source persona.

Technical Path

Backend — no new work for V1. StateManager.searchHumanData() is already the entry point. The read_memory tool wraps it today. Exposing it to the frontend is a direct processor.searchMemory(query, personaId?) call.

Jump to message — cleaner than expected. Quote entities already carry message_id, start, and end for source attribution. Since the virtualizer uses msg.id as the row key:

// ChatPanelHandle gets a new method:
scrollToMessageId: (messageId: string) => void;

// Implementation (inside ChatPanel):
const index = messages.findIndex(m => m.id === messageId);
if (index !== -1) rowVirtualizer.scrollToIndex(index, { align: 'center' });

TanStack Virtual's scrollToIndex handles all the virtual positioning. The "jump to source" feature is not a workaround — it's a first-class virtualizer API.

V1 Scope

  • Search modal (🔍 button) with results from: Quotes, Facts, Topics, People (shipped v0.8.0)
  • Quote cards show source persona + timestamp (shipped v0.8.0)
  • Persona/global scope toggle (backend supports it, UI toggle not built)
  • "Jump to message" for Quotes via scrollToMessageId on ChatPanelHandle
  • Cmd+K / Ctrl+K keyboard shortcut to open modal
  • Works in web UI; TUI is out of scope for V1

Open Questions

  • Should Ctrl+F be intercepted when chat is focused, or is this a parallel entry point?
  • "Jump to message" requires the source persona to be active — should the search result auto-switch persona, or prompt the user?
  • Should results show a "preview pane" (messages surrounding the source message) as a fallback when jumping isn't possible (e.g., from a global search result without an active chat)?

Notes

This is the natural next step after virtualizing the chat panels. The message list is no longer the interface for finding things — it's the interface for having conversations. The knowledge graph is the interface for finding things.

(Also it's issue #42 and it's about looking things up. Obviously this had to be done right.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions