Skip to content

Import existing Claude/Codex/OpenCode sessions#766

Merged
boudra merged 13 commits into
mainfrom
import-external-provider-sessions
May 9, 2026
Merged

Import existing Claude/Codex/OpenCode sessions#766
boudra merged 13 commits into
mainfrom
import-external-provider-sessions

Conversation

@boudra
Copy link
Copy Markdown
Collaborator

@boudra boudra commented May 5, 2026

Summary

Adds an "Import agent..." flow to the workspace header so users can browse provider sessions started outside Paseo (Claude Code, Codex, OpenCode) and resume them as Paseo agents.

  • Daemon: fetch_recent_provider_sessions request returns merged, deduped, cwd-scoped descriptors across enabled importable providers; import_agent_request accepts providerId + providerHandleId for provider-opaque imports.
  • Codex: pre-filter thread/list by cwd before per-thread thread/read includeTurns hydration to keep the import sheet snappy.
  • OpenCode: list persisted sessions via session.list.
  • App: workspace import sheet fans out one fetchRecentProviderSessions per enabled provider via useQueries, dedupes by handle, and falls back to a single unfiltered request for older daemons. Already-imported sessions are filtered server-side and surfaced as a distinct empty state. Sheet revalidates on reopen.

Closes / addresses

Test plan

  • Open the workspace header menu → "Import agent..." → sheet lists recent Claude/Codex/OpenCode sessions for the current cwd
  • Provider filter chips toggle visible providers
  • Importing a session opens it as a new agent tab with title hydrated from the first user message
  • Already-imported sessions are filtered out; empty state distinguishes "none recent" vs "all already imported"
  • One broken provider shows inline error; others still load
  • Sheet revalidates when reopened

@boudra boudra force-pushed the import-external-provider-sessions branch 3 times, most recently from 9aeba41 to a4e3f7d Compare May 8, 2026 02:37
@boudra boudra force-pushed the main branch 2 times, most recently from 7ec394c to 5c90449 Compare May 8, 2026 11:48
boudra added 12 commits May 9, 2026 14:26
Move provider eligibility from a session-level post-filter to the agent
manager's fan-out so disabled providers are never spawned (fixes the
Gemini-disabled hang) and derived providers (like a custom Z.AI extending
Claude) don't duplicate their base provider's sessions.

Add an IMPORTABLE_PROVIDERS allowlist (claude, codex, opencode); ACP-based
providers are excluded from import discovery entirely.
Codex's listPersistedAgents previously called thread/read includeTurns on
every thread returned by thread/list, even when the import sheet was
scoped to one cwd. With many recent threads outside the scope, that fan
of reads dominated the import-sheet open latency.

Add an optional cwd hint to ListPersistedAgentsOptions, thread it through
the agent manager, and have Codex pre-filter the cheap thread/list rows by
cwd before scheduling the per-thread hydration. Widen the thread/list
window when filtering since most rows will be from other cwds. Other
providers ignore the hint.
Sheet now reads the providers snapshot already warmed by the workspace
screen, filters to enabled importable providers (claude/codex/opencode),
and issues one fetchRecentProviderSessions request per provider via
useQueries with limit 15. Results are merged, deduped by handle, and
sorted by last activity.

Falls back to a single unfiltered request when the daemon does not
expose a provider snapshot (older servers). Per-provider failures show
inline so a single broken provider does not hide the rest.
Show "All" plus one badge per enabled importable provider above the
session list when more than one is available. Single-select narrows the
already-merged list — no refetch. Each row now shows the provider's
icon next to its label so multiple providers stay visually distinct.

Selection resets when the sheet closes.
Track how many descriptors were dropped because their handle was
already imported, surface the count back to the client as an optional
`filteredAlreadyImportedCount`, and switch the sheet copy to
"All recent sessions are already imported." when the merged list is
empty solely due to that filter.
The import sheet's queries are gated on `enabled: visible`, and react-query
already refetches stale data when `enabled` flips on, so the manual
`wasVisibleRef` + `invalidateQueries` effect was redundant. Collapse the
two `selectedProvider` reset effects into one.

Drop `expect(...).toBeTruthy()` after `findByText` / `getByText` — those
helpers throw on miss, so the assertion was noise.

Drop `| null` from `buildOpenCodePersistedAgentDescriptor`'s return type
(it never returns null) and the dead `Boolean(descriptor)` filter at the
caller.
Introduces fetchRecentProviderSessions on the daemon client plus an
importAgent overload accepting providerId/providerHandleId, and a
projection helper that renders persisted descriptors as provider-opaque
recent-session payloads with prompt previews.
Centralizes the importable-providers list, normalizes import_agent_request
shape at one boundary, and removes the per-provider fan-out fallback in
the import sheet. Old daemons without features.providersSnapshot now show
"Update host" instead of being served a degraded path.

Replaces internal-helper unit tests on the OpenCode and Codex providers
with boundary tests through listPersistedAgents; makes storageRoot
injectable on the OpenCode provider so the boundary test can target a
temp directory.

Splits the CLAUDE.md back-compat rule into two contracts: protocol stays
backward-compatible (always); features may require new daemons (no
fallback paths). Tags the two new compat shims with COMPAT(name) and
target removal dates.
@boudra boudra force-pushed the import-external-provider-sessions branch from a4e3f7d to a26b7f8 Compare May 9, 2026 07:27
Move listImportableProviderSessions out of session.ts and drop the
unused generic listPersistedAgents from AgentManager.
@boudra boudra merged commit 5b884ae into main May 9, 2026
16 checks passed
@boudra boudra deleted the import-external-provider-sessions branch May 9, 2026 08:36
@ai13f
Copy link
Copy Markdown

ai13f commented May 11, 2026

Can this be added for Pi too?

@xiaobaifly7
Copy link
Copy Markdown

@boudra please

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

Labels

None yet

Projects

None yet

3 participants