Skip to content

Show agent session history on mobile#6786

Merged
brennanb2025 merged 17 commits into
mainfrom
brennanb2025/add-agents-to-mobile
Jul 10, 2026
Merged

Show agent session history on mobile#6786
brennanb2025 merged 17 commits into
mainfrom
brennanb2025/add-agents-to-mobile

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

What changes

Adds Agent Session History to Orca Mobile as a per-worktree screen. From a worktree's action sheet, tap Agent Session History to browse past agent transcript sessions on that host: scope tabs (Workspace / Project / All), search (including repo: / path: operators), grouping, session cards (agent, title, last message, message count, time-ago, "current worktree" badge), and tap a session to read its message preview.

What does not change: this is browse + preview only. Resuming an agent session from mobile is a deliberate follow-up, not in this PR. Desktop behavior is unchanged — the desktop "Agent Session History" panel keeps working exactly as before.

Why the plumbing

The transcript scan that powers this used to be reachable only over Electron IPC, so the mobile client literally could not see it. This PR exposes the same host scan over the runtime RPC protocol mobile already speaks (aiVault.listSessions). The scan runs on whichever host owns the transcripts, so it is correct for local and SSH/remote hosts. The desktop IPC handler and the new RPC method share a single 15s-TTL cache, so opening the desktop panel and the mobile screen never double-scan.

Design approach

  • New runtime RPC method aiVault.listSessions (bounded limit/scopePaths params) wrapping the existing transcript scanner, advertised via a new static aiVault.v1 runtime capability so older hosts degrade gracefully (the mobile entry is hidden when the host lacks it).
  • The cached scan entry point is lifted into one shared host module (src/main/ai-vault/cached-session-list.ts) used by both the IPC handler and the RPC method. Codex-home + WSL inputs are sourced from the OrcaRuntimeService constructor (which runs in both window mode and orca serve), not the window-only handler path — otherwise remote/SSH hosts would silently drop managed-Codex sessions.
  • The pure filter/group/display logic is lifted into /shared (the desktop renderer now re-exports it) so the standalone mobile package can reuse it; Metro can't import renderer modules. /shared stays a leaf (zero renderer imports).
  • Mobile narrows the Workspace/Project tabs client-side by cwd path-prefix, because the host scan treats scope paths as a widening union, not a filter.

Design-review outcome

Ran the iterative design review to clean (3 rounds, no remaining P0/P1, no direction-level findings). It caught two load-bearing issues in the draft before implementation: (1) sourcing codex-home from the window-only handler would break it under orca serve/SSH — moved to the runtime constructor seam; (2) the renderer filter helpers import runtime values and Metro can't resolve renderer modules — so the pure core is lifted to /shared rather than imported.

Implementation & deviations

Implemented as designed. Two deviations, both noted:

  • Extracted the worktree action-sheet actions into worktree-navigation-actions.ts to keep the mobile host index file under its line budget without a max-lines disable. No behavior change.
  • Mobile Project scope narrows by path-prefix (active worktree + same-repo siblings) rather than desktop's project-key, because mobile's worktree data carries no project-key metadata. Documented in code.

Completeness verification

Read-only verification confirmed all requirements implemented (host RPC + bounds + capability, single shared cache, serve-mode codex-home, /shared leaf invariant + renderer re-export parity, capability-gated mobile entry + screen, scope/search/grouping/cards/preview, virtualization + lazy preview, interaction states, no resume code). Verdict: complete.

Headline behavior status

Implemented. The full path executes in production code: tap worktree → capability-gated action → per-worktree screen → aiVault.listSessions RPC → shared cache → on-disk transcript scan → rendered sessions, with working scope tabs / search / grouping / preview. No fixtures or dormant scaffolding. Resume is intentionally deferred (follow-up PR).

Perf audit

No actionable findings. Touched hot paths: the RPC dispatch (forwards to a cached async scan — no sync heavy work), and the mobile render (memoized sections, stable list keys, virtualized SectionList, lazy preview rendered only on tap). No polling (loads on mount/reconnect, scope switch reuses the host TTL with force:false, pull-to-refresh uses force:true). Lifecycle guarded by mountedRef/generationRef; no timers/listeners to leak.

Accepted gap: the scanner ships the full (bounded: ≤5 messages × 220 chars) previewMessages array per session even though preview is lazy-rendered. This is inherent to the existing scanner output shape (desktop receives the same payload); trimming it would require a scanner change, out of scope. Mitigated by virtualization + lazy render. QA watch item: rapid search typing on a large history (un-debounced filter, matches desktop today); add useDeferredValue only if real jank is observed.

Code-review loop

Two rounds, two independent reviewers each (four total).

  • Round 1: one High — the Workspace/Project scope tabs didn't actually narrow (the host union only widens, and the section builder hardcoded scope: 'all'). Fixed: narrow client-side by cwd path-prefix, with a fallback to unnarrowed until the worktree list loads. Added narrowing tests.
  • Round 2: both reviewers confirmed the fix correct and complete; two Low residuals — the Project path-prefix-vs-project-key approximation (documented, errs toward over-showing, browse-only) and an untested fallback branch (test added). No Critical/High/Medium remaining.

brennan-test-changes result

Validated the desktop consumer of the refactor in the running Electron app (the testable end-to-end surface in this environment): launched the PR worktree, confirmed identity (branch brennanb2025/add-agents-to-mobile), opened the desktop "Agent Session History" panel, and confirmed it renders 500 real sessions with working search (incl. repo: operator), scope tabs, and all three grouping modes, zero panel-related console errors. This exercises the lifted /shared logic through the renderer re-export and the shared cache via the IPC path. Verdict: land for the desktop-consumer concern.

Accepted validation gaps (this environment):

  • The mobile screen itself was not booted — this worktree's mobile/node_modules is incomplete (no react-native/expo), so the RN app can't run here. The new .tsx mirror the exact untyped patterns of existing mobile screens; mobile oxlint + the standalone vitest suite pass. CI runs the full mobile typecheck with complete deps.
  • The RPC over the wire from a real mobile client was not exercised (no mobile client here). The RPC handler is unit-tested and the shared cache it uses is exercised end-to-end through the desktop panel.
  • No screenshot of the new mobile UI (cannot render here). The desktop panel was visually verified live.

Static checks & focused tests

  • tsgo typecheck: node + web projects clean.
  • oxlint: clean on all touched root + mobile files. git diff --check: clean.
  • Root vitest: new aiVault.listSessions RPC tests + /shared filter parity tests pass (13); desktop IPC + renderer filter + register-core-handlers suites still pass (1331).
  • Mobile vitest (standalone package): src/agent-history 17 pass (scope-path derivation, scope narrowing incl. fallback, card view-model, capability lockstep).

Remaining risks / non-actionable

  • Mobile Project scope can diverge from desktop's project-key in rare monorepo/nested-worktree layouts (over-/under-inclusion); browse-only, never data loss. Documented.
  • Mobile typecheck + emulator QA rely on CI / a complete mobile checkout; not runnable in this worktree.

Made with Orca 🐋

Mobile backcompat review (2026-07-10) + pre-merge fixes

Full /mobile-backcompat-review (4 independent reviewers + verification): compatible — no P0 blockers. Version-skew matrix verified both directions: mobile gates every aiVault.listSessions call on the aiVault.v1 capability from status.get (old hosts get an explicit unsupported/graceful state), all new RuntimeStatus/RuntimeWorktreePsSummary fields are optional-additive, no persisted keys renamed, host paths go through the shared Windows/WSL-aware helpers, resume is blocked on SSH/runtime workspaces.

Fixes applied from the review:

  • Gate the session-header Agent History action on aiVault.v1 (was the one ungated entry point; old hosts saw a dead-end "update host" panel).
  • Corrected two stale contract comments (RPC schema clamps scopePaths, doesn't reject; the filters move to /shared also added quoted repo:/path: operator parsing).

User-visible workspace-list changes to be aware of (intentional desktop parity, verified against desktop source):

  • Smart sort now renders desktop's persisted sidebar order (sortOrder desc, per worktrees:persistSortOrder); unranked/headless hosts fall back to agent-attention order. unread is no longer a sort key.
  • Pinned workspaces now appear in both Pinned and their canonical group — matches desktop's "pinned is an overlay" model (worktree-list-groups.ts).
  • Ungrouped mode is now a single All section whose key matches desktop's ALL_GROUP_KEY, making the desktop-synced collapsedGroups state coherent across surfaces. One-time effect: users who had "All" collapsed will see the whole ungrouped list collapsed once after upgrade.

Merged origin/main (@143c36e56): reconciled with #7423 (AI Vault subagent display) — kept its aiVault:listSubagentSessions handler on top of the shared-cache refactor (getAiVaultWslHomeDirs now exported from cached-session-list), and moved its sessionModelLabel into src/shared/ai-vault-session-display behind the renderer re-export. Post-merge: typecheck clean, 747 desktop ai-vault/runtime tests and 1392 mobile tests pass.

Bring the desktop "Agent Session History" panel to Orca Mobile as a
per-worktree screen: browse past agent transcript sessions across the
host with scope tabs (Workspace/Project/All), search, grouping, session
cards, and tap-to-read message previews.

The transcript scan previously ran only over Electron IPC, so mobile
could not reach it. Expose it over the runtime RPC protocol mobile
already speaks (aiVault.listSessions) so the scan runs on whichever host
owns the transcripts — correct for local and SSH/remote hosts. Both the
desktop IPC handler and the new RPC method share one cache, so opening
the desktop panel and the mobile screen never double-scan.

The pure filter/group/display logic is lifted into /shared (the renderer
re-exports it) so the standalone mobile package can reuse it. Mobile
narrows scoped tabs client-side by cwd path-prefix because the host scan
treats scope paths as a widening union.

Resume-from-mobile is intentionally a follow-up.
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

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
📝 Walkthrough

Walkthrough

This PR adds Agent Session History to the mobile app and refactors related AI Vault logic. Shared session display and filtering code moves into src/shared, aiVault.listSessions is added through shared cache/runtime/RPC wiring, and the mobile app gains scope-path derivation, state handling, list and panel components, a new route, and host navigation actions.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The PR description is detailed, but it does not follow the required template and is missing Summary, Screenshots, Testing, AI Review Report, Security Audit, and Notes sections. Rewrite the description using the repository template and add the required sections, including testing status, screenshots or no-visual-change note, review report, security audit, and notes.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding agent session history to mobile.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (2)
src/shared/ai-vault-session-filters.test.ts (1)

79-85: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a quoted operator regression case.

When fixing the parser, cover repo:"my repo" and path:"/Users/ada/My Project" here so paths/repo labels with spaces stay supported.

mobile/src/agent-history/agent-history-scope-paths.test.ts (1)

39-45: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a Windows-path regression case.

This helper depends on case-insensitive Windows normalization, but the suite only locks in POSIX inputs. A C:\Repo\App vs c:/repo/app fixture would pin the cross-platform contract here.

Suggested coverage
+  it('dedupes equivalent Windows paths case-insensitively', () => {
+    const windowsActive = worktree({ worktreeId: 'w1', path: 'C:\\Repo\\App', repoId: 'repo-1' })
+    const windowsDupe = worktree({ worktreeId: 'w2', path: 'c:/repo/app', repoId: 'repo-1' })
+    expect(
+      deriveMobileAiVaultScopePaths('project', windowsActive, [windowsActive, windowsDupe])
+    ).toEqual(['C:\\Repo\\App'])
+  })

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b36d8821-3fe9-4898-864b-f49703a05369

📥 Commits

Reviewing files that changed from the base of the PR and between 22b00a7 and efe9a21.

📒 Files selected for processing (28)
  • mobile/app/h/[hostId]/agent-history/[worktreeId].tsx
  • mobile/app/h/[hostId]/index.tsx
  • mobile/app/h/_layout.tsx
  • mobile/src/agent-history/MobileAgentSessionHistoryList.tsx
  • mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx
  • mobile/src/agent-history/agent-history-capability.ts
  • mobile/src/agent-history/agent-history-scope-paths.test.ts
  • mobile/src/agent-history/agent-history-scope-paths.ts
  • mobile/src/agent-history/agent-history-sections.ts
  • mobile/src/agent-history/agent-history-session-card.test.ts
  • mobile/src/agent-history/agent-history-session-card.ts
  • mobile/src/agent-history/agent-history-styles.ts
  • mobile/src/agent-history/use-mobile-agent-history-state.ts
  • mobile/src/agent-history/worktree-navigation-actions.ts
  • src/main/ai-vault/cached-session-list.ts
  • src/main/index.ts
  • src/main/ipc/ai-vault.ts
  • src/main/runtime/orca-runtime.ts
  • src/main/runtime/rpc/methods/ai-vault.test.ts
  • src/main/runtime/rpc/methods/ai-vault.ts
  • src/main/runtime/rpc/methods/index.ts
  • src/renderer/src/components/right-sidebar/ai-vault-session-display.ts
  • src/renderer/src/components/right-sidebar/ai-vault-session-filters.ts
  • src/renderer/src/components/right-sidebar/ai-vault-session-projects.ts
  • src/shared/ai-vault-session-display.ts
  • src/shared/ai-vault-session-filters.test.ts
  • src/shared/ai-vault-session-filters.ts
  • src/shared/protocol-version.ts

Comment thread mobile/app/h/[hostId]/index.tsx
Comment thread mobile/src/agent-history/MobileAgentSessionHistoryList.tsx
Comment thread mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx
Comment thread mobile/src/agent-history/use-mobile-agent-history-state.ts
Comment thread src/main/runtime/rpc/methods/ai-vault.test.ts
Comment thread src/shared/ai-vault-session-filters.ts
- Authorize aiVault.listSessions in the mobile RPC allowlist so the
  mobile client's call is not rejected before dispatch (without this the
  screen could never load sessions at runtime).
- Name each SectionList section's rows `data` (the field React Native
  reads) instead of `cards`, fixing a type error and silent empty-section
  rendering.
- Match quoted repo:/path: search operator values so labels and paths
  with spaces match (e.g. path:"/Users/ada/My Project").
- Hold a scoped tab in loading until the worktree list resolves instead
  of firing an unscoped fetch that briefly shows unrelated host history;
  proceed once loaded even if the worktree is absent (no stuck spinner).
- Clear cached host capabilities on disconnect/host-switch and failed
  status.get so a capability-gated action can't linger for a host that
  doesn't support it.
- Cover the real OrcaRuntimeService codex-home forwarding path and the
  quoted-operator parser with tests.
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Stabilization update

Merged current main into the branch (was ~82 commits behind) to de-risk drift and run CI against the latest tree. All feature checks are green:

  • Fast verify shard (typecheck + lint): pass
  • Mobile typecheck (full, with complete deps): 0 errors
  • Feature test surface: host RPC + /shared filter parity + mobile RPC allowlist + renderer filter consumers + IPC + mobile agent-history suite — all pass (1373 root + 17 mobile)
  • All 6 CodeRabbit comments addressed (5 fixed, 1 withdrawn by CodeRabbit after discussion)

One red check is not from this PR: the full-suite verify shard fails on a single test — src/renderer/src/components/terminal-pane/pty-connection.test.ts > "does NOT re-assert while a mobile-fit override parks the PTY at phone dims". This file and its production dependencies (pty-connection.ts, mobile-fit-overrides.ts) are byte-identical to origin/main; this PR touches no terminal/PTY code. It fails deterministically in isolation both locally and on CI after merging main, which points at the recent main-side PTY size-reconcile changes (e.g. #6725, #6684) rather than anything in this branch. Flagging for triage; it is outside this PR's scope to fix.

@stage-review

stage-review Bot commented Jun 30, 2026

Copy link
Copy Markdown

Ready to review this PR? Stage has broken it down into 7 individual chapters for you:

Title
1 Lift session display and filtering to shared
2 Define AI Vault runtime capability
3 Unify session list caching and sources
4 Expose AI Vault sessions over RPC
5 Implement mobile agent history logic
6 Build mobile agent history UI
7 Wire agent history into mobile navigation
Open in Stage

Chapters generated by Stage for commit e641cd4 on Jun 30, 2026 8:50pm UTC.

brennanb2025 and others added 11 commits July 2, 2026 19:20
Co-authored-by: Orca <help@stably.ai>
…ts-to-mobile

# Conflicts:
#	mobile/app/h/_layout.tsx
#	src/main/index.ts
#	src/main/ipc/ai-vault.ts
#	src/main/runtime/orca-runtime.ts
#	src/main/runtime/runtime-rpc.ts
#	src/shared/runtime-types.ts
Co-authored-by: Orca <help@stably.ai>
…ts-to-mobile

Reconciles the mobile aiVault.listSessions RPC with main's runtime-host
scanning (#7631), OMP sessions (#7618/#7628), host-aware attribution
(#7367), and zero-turn recovery (#7889):

- One aiVault.listSessions serves mobile (no executionHostId), the desktop
  parent, and web clients: bounded params kept, results served from the
  shared host-local cache and restamped per-caller at the RPC edge.
- Desktop's runtime-host RPC client caps scopePaths to the shared bound so
  large desktops degrade gracefully instead of failing validation.
- Desktop IPC local scope delegates to the shared cache module (single
  cache with the RPC path); ssh/runtime/all merges keep main's outer cache.
- Main's zero-turn empty-session semantics and ExecutionHostId-typed
  project attribution replayed onto the /shared lifted filter core.
- Mobile resume forwards session.filePath so OMP resumes by absolute
  transcript path (desktop parity).

Co-authored-by: Orca <help@stably.ai>
…ment

The extracted cache module's .finally() cleared inflight tracking
unconditionally, dropping the if (inflightKey === key) guard its sibling
outer cache kept: an older scan resolving after a different-key scan
replaced the tracking would null the newer scan's dedup slot, so a
re-request started a duplicate transcript rescan. Mirrors the sibling
guard; the regression test flushes a macrotask so a reverted guard fails
fast on the call count instead of hanging.

Co-authored-by: Orca <help@stably.ai>
…ts-to-mobile

Take main's side of the mobile session-screen PR probe: the source-control
hub (#7923) now loads branch identity inside MobileSourceControlPanel, so
the session screen only gates the dock icon on the GitHub remote probe.

Co-authored-by: Orca <help@stably.ai>
…capability

- Clamp scopePaths (64) instead of rejecting, cap limit at 2000, and make
  executionHostId optional so mobile can omit it; restamp per caller.
- Retain successful mobile terminal-create mutation ids for 60s so resume
  retries dedupe after transient socket drops.
- Gate the session-header Agent History action on the aiVault.v1 capability
  (mirrors the host-list action) so old hosts never show a dead-end entry.
- Fix stale contract comments (scopePaths clamp semantics; filters move
  includes quoted repo:/path: operator parsing).
…2025/add-agents-to-mobile

# Conflicts:
#	src/main/ipc/ai-vault.ts
#	src/renderer/src/components/right-sidebar/ai-vault-session-display.ts
AiVaultSession.subagent became required on main; the five fixtures added on
this branch predate it. Top-level scanned sessions carry null.
@brennanb2025
brennanb2025 merged commit 8f6e44e into main Jul 10, 2026
3 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