Skip to content

perf: switch external history import ranges without rescanning #2060

Description

@devRickyyy

Problem

In the local external-conversation import wizard, changing the time-range preset (for example, from 30 days to 7 days) replaces the conversation list with a loading state and scans the provider history again.

Once the initial scan has completed, switching among 7 days, 30 days, 90 days, and All should be immediate and should not require another reload.

Steps to Reproduce

  1. Open the external conversation history import wizard.
  2. Select local Codex and/or Claude Code history and run the initial scan.
  3. On the conversation selection step, switch from 30 days to 7 days.
  4. Switch to another preset, then back to a previously viewed preset.

Current Behavior

Every range change calls the scan endpoint again and temporarily removes the current results:

  • ExternalAgentSessionImportWizard.handleSelectRange always calls runScan(nextDays, archivePath).
  • runScan dispatches scan-started, sets loading, and the UI replaces the select step with the full loading state.
  • externalImportScanStateReducer clears the completed scan for every scan-started action.
  • The scan state stores only one { response, source }, and externalImportScanSourcesEqual treats days as part of the source identity, so a result cannot be reused for another range or even when returning to an earlier range.

The repeated daemon work is especially wasteful for local providers. scanExternalProviderSessions enumerates the provider JSONL files and parses each transcript before applying the UpdatedAtUnixMS cutoff. A narrower day window therefore still repeats most of the expensive filesystem and parsing work.

Desired Behavior

After one initial local-history scan:

  • Switching among all supported range presets is an in-memory projection and does not call scanWorkspaceExternalAgentSessionImports again.
  • The list remains visible; no full-screen loading state or disabled dialog is shown during a range switch.
  • Project groups, conversation counts, message counts, and selection counts update to match the active range.
  • Search text, project-registration preference, and explicit session deselections remain stable while changing ranges.

A reasonable implementation is to retain a reusable all-history summary/catalog and derive each range from lastUpdatedAtUnixMs. An equivalent indexed/cache design is acceptable if every preset is available immediately after the initial scan and does not make initial loading materially worse.

Archive imports are out of scope because the current UI does not show range controls in archive mode.

Acceptance Criteria

  • The initial local-history scan is the only scan request needed for the current provider selection and wizard lifecycle.
  • Switching between 7 days, 30 days, 90 days, and All issues no additional scan request.
  • Range switching does not clear the existing list or render the scanning state.
  • Sessions and project groups are filtered using the same updated-at cutoff semantics as the daemon.
  • Aggregate session/message counts and select-all state reflect only the active range.
  • Session deselections are preserved by ID when a session leaves and later re-enters the visible range.
  • Rapid range switching cannot apply stale results.
  • Changing the provider selection or starting a new wizard lifecycle still invalidates the reusable scan data.
  • Regression tests cover scan-call count, all four range projections, selection preservation, and source invalidation.

Code Pointers

  • apps/desktop/src/renderer/src/features/workspace-workbench/ui/ExternalAgentSessionImportWizard.tsx
  • apps/desktop/src/renderer/src/features/workspace-workbench/ui/externalAgentSessionImportWizardModel.ts
  • services/tuttid/service/agent/external_import.go
  • POST /v1/workspaces/{workspaceID}/agent-sessions/external-imports/scan

Environment

  • Surface: Desktop external conversation history import wizard
  • Sources: local Codex / Claude Code history
  • Current project checkout inspected: cfc997347ff4

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions