Skip to content

feat: research lens — recursive term explanations with concept chain - #661

Open
laohuan12138 wants to merge 1 commit into
agegr:mainfrom
laohuan12138:feat/research-lens
Open

feat: research lens — recursive term explanations with concept chain#661
laohuan12138 wants to merge 1 commit into
agegr:mainfrom
laohuan12138:feat/research-lens

Conversation

@laohuan12138

Copy link
Copy Markdown

What

Adds a research lens (研究模式) to Pi Web: select any term while reading an AI answer and get a streaming AI explanation in place — then keep drilling down. Nested lookups form an explicit concept chain so the reader always knows how they got here, and the whole chain can be reviewed, exported and revisited.

Features

Recursive explanations

  • Selecting text inside any rendered markdown (chat messages or an explanation card) shows an inline "✦ Explain" trigger; clicking it opens an animated card (fade-in, rotating conic border) where the explanation streams in token by token
  • Explanation bodies render through the shared MarkdownBody, so any term inside them is selectable again — nesting is unbounded, and every nested card carries a breadcrumb (nginx › reverse proxy)
  • The model's live reasoning (thinking_delta) is shown inside the loading card, so the wait is visible instead of a silent spinner

Concept chain panel

  • Floating panel showing the research path as a tree (term + one-line summary + follow-up count), per-session, persisted to localStorage
  • Click a node to reopen (and flash-locate) its card; cards keep their position across close/reopen; subtrees can be pruned
  • When both a parent and child card are open, a flowing dashed SVG bezier connects them and re-attaches on drag

In-card follow-up questions

  • Each card has an ask bar; Q/A renders inside the card below the explanation (also selectable for recursion). Follow-ups never become chain nodes — they show as a count badge on their term instead

Review affordances

  • Hovering an already-explained term anywhere shows a lightweight preview (closes on mouse-out, scrollable, can open the full card); explained terms are highlighted in the original text via the CSS Custom Highlight API
  • Three explanation depths (brief / standard / deep), re-explaining on demand

Web grounding (联网核实)

  • A globe toggle on each card re-runs the explanation grounded in keyless DuckDuckGo HTML search results, with instructions to cite source domains inline. Search failures degrade silently to model knowledge and are surfaced in the toggle's tooltip. Reachability follows the server's HTTPS_PROXY via the existing global dispatcher

Exports (chain panel)

  • Markdown research note
  • Interactive mind map: a self-contained HTML file (collapsible tree, works offline by double-click) with the FreeMind .mm XML embedded behind a download link for XMind/FreeMind users
  • Anki cards: .csv with directive headers + UTF-8 BOM, HTML answer side, follow-up Q/A appended, tags derived from the chain root

Settings

  • Settings → General → Research mode toggle (default on, localStorage, synced live across hook instances and tabs)

Implementation notes

  • POST /api/research/define streams SSE. Model resolution: fast ModelRuntime.create() first, full createAgentSessionServices({ cwd }) (cached per cwd) only when the provider is unknown — npm-package providers register only through extension loading. Streaming uses modelRuntime.streamSimple(...) so custom API providers work
  • Chains are scoped per session: { scope, nodes, openIds } live in one atomically-swapped state so a session switch can never write one session's chain under another's key; deleting a session prunes its chain (forgetResearchChain)
  • The ::highlight() rule is injected through CSSOM at runtime because Lightning CSS (Turbopack) rejects ::highlight() at build time — a broken globals.css blanks the app
  • Hover preview positioning measures the rendered height in a layout effect (above the term, then below, then clamped on screen); scrolls originating inside the preview don't dismiss it
  • Prompt shaping keeps cards scannable: definition-first, bullet-friendly, no markdown headings, key terms bolded (which is exactly what makes the next selection recursive)

Files

  • New: lib/term-research.ts (+16 unit tests), lib/web-search.ts, hooks/useTermResearch.ts, hooks/useResearchEnabled.ts, app/api/research/define/route.ts, components/research/{TermResearchOverlay,TermCard,ConceptChain}.tsx
  • Touched: ChatWindow (mount + gate), SessionSidebar (chain cleanup on session delete), SettingsPanel (toggle), globals.css (overlay styles), i18n en/zh-CN/zh-TW, AGENTS.md docs

Testing

  • tsc --noEmit clean, ESLint clean, npm test — 16 new unit tests for the pure helpers (context trimming, prompt building, chain markdown/FreeMind/Anki generation, escaping), all passing
  • Manually exercised end-to-end in the browser: nested explanations (3+ levels), web-grounded re-explanation with graceful no-proxy degradation, all three exports, session switch/delete isolation, settings toggle on/off, drag/position persistence, hover preview placement at viewport edges

Select any term in rendered markdown to get a streaming AI explanation
in an animated, draggable card; terms inside explanations recurse as
child nodes, forming an explicit research path.

- Concept chain panel: per-session tree with summaries and counts,
  subtree pruning, click-to-reopen with locate flash, per-session
  localStorage persistence
- In-card follow-up questions: streamed markdown Q/A scoped to the
  term's explanation, count badge on chain nodes
- Hover preview for already-explained terms (caret-based full-string
  match, CJK-safe); explained terms highlighted in the original text
  via the CSS Custom Highlight API (rule injected through CSSOM because
  Lightning CSS rejects ::highlight at build time)
- Optional web grounding: keyless DuckDuckGo HTML search injects
  <web-search-results> context with source-citation instructions;
  failures degrade silently to model knowledge
- Exports: Markdown note, self-contained interactive HTML mind map
  (embeds a .mm download for XMind/FreeMind), Anki-importable CSV
- Settings → General 'Research mode' toggle (localStorage, synced
  across hook instances and tabs)
- i18n: en / zh-CN / zh-TW; 16 unit tests for the pure helpers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant