Skip to content

feat(ai-hist): Conversations panel — browse Claude/Codex/Cursor/Relay history#20

Merged
khaliqgant merged 10 commits into
mainfrom
feat/ai-hist-conversations
May 22, 2026
Merged

feat(ai-hist): Conversations panel — browse Claude/Codex/Cursor/Relay history#20
khaliqgant merged 10 commits into
mainfrom
feat/ai-hist-conversations

Conversation

@khaliqgant

Copy link
Copy Markdown
Member

Summary

Adds a "Conversations" view to pear, backed by ai-hist (see companion PR AgentWorkforce/ai-hist#3). Matches the conversation-history UX in the Codex and Claude apps: searchable list of recent sessions on the left, full prompt thread on the right, source-color chips, one-click "copy resume command" to re-launch a session in its native CLI.

What's in

  • Main process: `src/main/ai-hist.ts` lazy-loads the SDK so a missing native binding or missing DB file doesn't crash startup. `src/main/ipc-handlers.ts` exposes `ai-hist:*` channels.
  • Preload bridge: typed `pear.aiHist.{status, recent, listSessions, getSession, search, stats, resumeCommand, reload}` namespace.
  • Renderer: `src/renderer/src/components/ai-hist/ConversationsPanel.tsx` — Allotment two-pane layout, source filter chips, relative timestamps, "copy resume command" button.
  • Sidebar entry point: "Conversations" button in the sidebar footer.
  • Tab/view wiring: new `'ai-hist'` value in `AppTabKind` / `ViewMode`.

Acceptance

  • ✅ `npm run build` succeeds.
  • ✅ Zero new typecheck errors (39 web / 37 node errors all pre-existing on `origin/main`).
  • ✅ Smoke-tested SDK against the live 35,797-row DB locally.

Try it

```bash
git checkout feat/ai-hist-conversations
npm install
npm run dev
```

Then click "Conversations" in the sidebar footer. If you don't have ai-hist installed yet, the panel shows a friendly install hint.

Coupling to AgentWorkforce/relayhistory#3

The SDK is consumed via `file:../ai-hist/sdk-ts` while ai-hist#3 is in review. Once that lands and the SDK is published to npm, swap to a versioned dep.

Implementation note

The SDK uses sql.js (WASM SQLite), not better-sqlite3. Original plan was the native lib for speed, but Electron 42's V8 ABI broke its compile. sql.js needs zero electron-rebuild, the perf is fine for the ai-hist scale (LIKE-based search ran ~78ms across the 35K-row DB), and it removes a class of cross-platform install pain.

🤖 Generated with Claude Code

… history

Adds a "Conversations" view backed by the new ai-hist SDK
(AgentWorkforce/relayhistory#3). Matches the conversation-history UX in the
Codex and Claude apps: searchable list of recent sessions on the left,
full prompt thread on the right, source-color chips, one-click
"copy resume command" to re-launch the session in its native CLI.

- src/main/ai-hist.ts: lazy-loading manager around `openAiHist()`.
  Surfaces missing-DB / load failures via getStatus() rather than
  crashing app startup.
- src/main/ipc-handlers.ts + src/preload/index.ts: ai-hist:* IPC
  channels and a typed `pear.aiHist.*` namespace.
- src/renderer/src/components/ai-hist/ConversationsPanel.tsx:
  two-pane Allotment layout with search, source filter chips,
  session list, and per-session prompt thread.
- src/renderer/src/components/sidebar/Sidebar.tsx: "Conversations"
  button in the sidebar footer.
- src/renderer/src/stores/ui-store.ts + src/renderer/src/App.tsx:
  registers `ai-hist` as a new AppTabKind / ViewMode.

The SDK uses sql.js (WASM SQLite) under the hood — no electron-rebuild
required. ai-hist (the Python sync tool) needs to be installed
separately; the panel shows a friendly install hint when the DB isn't
present.

The SDK is consumed via `file:../ai-hist/sdk-ts` for now. Once
ai-hist#3 lands and the SDK is published to npm, swap this to a
versioned dep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Free

Run ID: 51cfb50e-b8ef-4122-9c66-bbf1cbdb77d1

📥 Commits

Reviewing files that changed from the base of the PR and between cc6a47f and 8446f2c.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • package.json

📝 Walkthrough

Walkthrough

Adds ai-hist SDK integration and a Conversations UI: main-process AiHistManager with lazy loading and fast SQL paths, IPC handlers and preload bridge, UI tab/sidebar entries for "Conversations", and a two-pane ConversationsPanel with session search, grouping, resume, and copy workflows.

Changes

AI History Feature

Layer / File(s) Summary
SDK wrapper and IPC handlers
package.json, src/main/ai-hist.ts, src/main/ipc-handlers.ts
AiHistManager lazy-loads the ai-hist SDK on first use, dedupes concurrent loads, exposes list/search/get/stats/resume/reload, implements fast SQL paths with fallbacks, and registers ai-hist:* IPC handlers.
Preload API and type bridge
src/preload/index.ts, src/renderer/src/lib/ipc.ts
Adds 'ai-hist' to ViewMode and exports AI-history types; PearAPI gains an aiHist namespace with typed IPC methods; spawnAgent input accepts optional args?: string[].
UI tab system extensions
src/renderer/src/stores/ui-store.ts
Adds 'ai-hist' to ViewMode/AppTabKind and updates tab helpers to support the "Conversations" mode and title.
Sidebar navigation button
src/renderer/src/components/sidebar/ProjectSidebar.tsx
Adds MessageSquare icon and a "Conversations" project-scoped button that opens the ai-hist tab with active styling.
ConversationsPanel component
src/renderer/src/components/ai-hist/ConversationsPanel.tsx
Two-pane UI: left pane lists/searches sessions grouped by project root with filters and query-token stale guards; right pane shows session entries, resume-in-pear (spawnAgent + host selection) and copy-command flows, status banner, and formatting helpers.
App integration and routing
src/renderer/src/App.tsx
Imports ConversationsPanel and renders it when the active tab kind is ai-hist.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

🐰 I nibble through sessions, prompt by prompt,
I hop to resume where a command was drawn,
Clipboard crumbs glint bright, I copy with a thump,
Conversations gathered, dusk to dawn!


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

Comment @coderabbitai help to get the list of available commands and usage tips.

khaliqgant and others added 9 commits May 22, 2026 11:37
The ai-hist SDK now ships as `type: module`. require() of an ESM
package fails at runtime on older Node, so switch the lazy-load path
in src/main/ai-hist.ts to `await import('ai-hist')`. The IPC surface
is unchanged (handlers already return Promises); resumeCommand is now
async too.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ai-hist@0.1.1 is now on npm. Swap the `file:../ai-hist/sdk-ts` link
to a real versioned dep so end users of pear don't need the ai-hist
repo cloned alongside.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ck resume

- ProjectSidebar: adds a "Conversations" entry under the active project
  (replaces the global sidebar footer button). Each project gets its
  own tab via `{ kind: 'ai-hist', projectId }`; the ai-hist tab id now
  includes projectId so tabs don't collide across projects.
- ConversationsPanel: reads the scoped projectId from the active tab,
  pulls a larger session window (limit 500), and groups sessions by
  which project root the session.project path matches. Without a
  scope, groups every pear project's roots + an "Other" bucket.
- Session row UX:
  - single click  → load the full prompt thread in the right pane
  - double click  → spawn the session as a pear agent in the matching
    project (broker.spawnAgent with cli + --resume <sessionId>), open
    the agents tab, focus the new agent
- Detail header: replaces the single "Copy resume command" button with
  a primary "Resume in pear" + a secondary "Copy" button.
- Broker.spawnAgent: preload + renderer PearAPI now expose the `args`
  field that SpawnPtyInput already accepted server-side, so the
  renderer can pass `['--resume', sessionId]` (claude/cursor) or
  `['resume', sessionId]` (codex) without parsing a shell string.
- Renderer ipc.ts: added the AiHist* types + the aiHist namespace
  (was preload-only before, which left the renderer's PearAPI
  untyped).

Sidebar.tsx: removed the global Conversations button since the entry
point now lives under each project.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… dev

ai-hist 0.2.0 (JSONL fallback, AgentWorkforce/relayhistory#5) isn't on npm
yet. Use the local checkout so the Conversations panel picks up the
fallback before publish.

Switch back to `"ai-hist": "^0.2.0"` once #5 is merged + published.
The right pane was conditionally rendering an empty <ul> when
getSession returned [] or rejected, so a failed load looked identical
to "loading complete with zero prompts" — i.e. invisible. Adds:

  - detailError state captured from the IPC promise's catch handler;
    rendered as a red error card in the right pane.
  - Explicit empty-state message including the session id so users
    can report which session id the SDK rejected.

These are diagnostic affordances, not a fix for the underlying
getSession behavior — they make any future failure visible instead
of silent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ai-hist 0.2.1 is now on npm with the JSONL fallback +
non-blocking loads. Swap the file: link back to a real
versioned dep.
…sible

Root cause of "clicking a conversation shows nothing": the Conversations
panel used `Allotment` for the two-pane split, but Allotment's required
CSS (allotment/dist/style.css) was never imported anywhere in the
renderer. Without it, the right pane rendered at zero width and the
transcript was visible to React but not to the user.

Switching to plain CSS flex (`w-[380px]` left, `flex-1` right) sidesteps
the missing-stylesheet bug and removes the Allotment dependency from
this view. Users don't need a draggable splitter for this layout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lifts the conversation-loading and search freeze out of the SDK by
doing the slow work in pear's main-process wrapper instead. Drafted
by codex-2 via Relaycast after Khaliq reported "search freezes".

Three changes:

1. `src/main/ai-hist.ts`: new `fastListSessions` + `fastSearchSessions`
   methods on the manager. They reach into the SDK's already-open
   sql.js DB handle, pull the raw rows matching the filters, and group
   in-memory in JS (Map keyed by source/session_id/project). Falls
   back to the SDK's slow methods on any error so we stay safe if the
   internal handle is ever unavailable. New `searchSessions` IPC
   handler exposed via `ai-hist:search-sessions`.

2. `src/preload/index.ts` + `src/renderer/src/lib/ipc.ts`: expose
   `pear.aiHist.searchSessions(query, opts)` returning
   `AiHistSession[]` so the renderer can avoid the previous two-call
   dance (`search()` followed by `listSessions(500)` to grouping by
   session_id intersection).

3. `src/renderer/src/components/ai-hist/ConversationsPanel.tsx`:
   - 150 ms debounce on the search input (was firing per keystroke).
   - When the query is non-empty, call `searchSessions` instead of
     `search + listSessions + client-side intersect`.

Benchmarks against ~91 MB / 35,857-row DB:
- old SDK `listSessions({ limit: 500 })`: ~17.1s
- new row-scan session list:                ~255ms
- new search-session path (filtered):       ~277ms

Co-Authored-By: codex-2 (via Relaycast) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0.2.3 includes the listSessions window-function rewrite + auto-created
session_id/timestamp indexes (~68x faster on a 35K-row DB). Pear's
main-wrapper bypass (cc6a47f) still works as a safety net, but with
0.2.3 the underlying SDK is fast too — both paths agree.
@khaliqgant khaliqgant merged commit bccd17a into main May 22, 2026
2 checks passed
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