Skip to content

fix(sessions): toast on saved-prompt restore fallback#2790

Open
nikhilachale wants to merge 8 commits into
AgentWrapper:mainfrom
nikhilachale:feat-toast-restore
Open

fix(sessions): toast on saved-prompt restore fallback#2790
nikhilachale wants to merge 8 commits into
AgentWrapper:mainfrom
nikhilachale:feat-toast-restore

Conversation

@nikhilachale

Copy link
Copy Markdown
Collaborator

Summary

Adds restore outcome metadata so the desktop app can tell whether a session restore used the agent's native resume path or fell back to launching a new conversation from AO's saved prompt.

When restore falls back to the saved prompt, the renderer now shows a native notification so the user understands that AO restored the task context but did not resume the original native agent transcript.

Changes

  • Added restore mode classification in the session manager:
    • native
    • saved_prompt
    • fresh
  • Added restoreMode to POST /api/v1/sessions/{sessionId}/restore.
  • Regenerated OpenAPI and frontend TypeScript API schema.
  • Updated the frontend restore hook to show a notification only for saved_prompt fallback restores.
  • Added backend tests for restore mode reporting.
  • Added frontend tests for fallback-toast behavior and native-restore no-toast behavior.

User Impact

If an agent session cannot be natively resumed but AO can still relaunch from the saved prompt, users now get a clear desktop toast:

AO could not resume the native agent session, so it started a new conversation from the saved prompt.

Native restores remain quiet. Not-resumable failures continue to use the existing error/dialog path.

Verification

  • npm run api
  • cd backend && go test ./internal/session_manager ./internal/service/session ./internal/httpd/controllers ./internal/cli
  • cd frontend && npm test -- SessionsBoard.test.tsx TerminalPane.test.tsx
  • cd frontend && npm run typecheck

AgentWrapper and others added 5 commits February 18, 2026 22:04
Add true in-place session restore: same session ID, same worktree, same
metadata — optionally resuming the Claude Code conversation via --resume.

Core changes:
- Add TERMINAL_STATUSES, TERMINAL_ACTIVITIES, NON_RESTORABLE_STATUSES sets
  and isTerminalSession/isRestorable helpers to types.ts
- Add SessionNotRestorableError and WorkspaceMissingError error classes
- Add restore() to SessionManager with 9-step flow: find metadata →
  validate restorability → check/recreate workspace → get restore or
  launch command → create runtime → update metadata
- Add restoredAt field to Session and SessionMetadata

Plugin extensions:
- workspace-worktree: exists() + restore() (git worktree prune + re-add)
- workspace-clone: exists() + restore() (git clone + checkout)
- scm-github: branchExists() via git rev-parse
- agent-claude-code: getRestoreCommand() finds latest JSONL session file
  and builds claude --resume command

CLI + Web:
- Add `ao session restore <id>` subcommand
- Web restore API route uses sessionManager.restore() instead of spawn()
- SessionCard uses centralized TERMINAL_STATUSES/TERMINAL_ACTIVITIES
- Web types re-export core constants with sync tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The old inline isTerminal check included "merged" but when refactored
to use the TERMINAL_STATUSES set, "merged" was omitted. This caused
merged sessions (whose activity is not "exited") to incorrectly show
the "terminal" link and "terminate session" button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add enrichSessionWithRuntimeState() call before isRestorable() in
  restore() so crashed sessions (status "working", agent exited) are
  correctly detected as terminal and eligible for restore.
- Remove dead branchExists from SCM interface and scm-github plugin
  (defined but never called anywhere in the codebase).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove "working" from NON_RESTORABLE_STATUSES. The isTerminalSession()
gate already prevents restoring truly active sessions (activity is not
"exited"). This fix allows crashed agents (status "working", activity
"exited") to be restored, aligning core behavior with the UI which
already shows the restore button for this case.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split the compound condition so workspace restore gives an accurate
error message when branch metadata is null ("branch metadata is
missing") vs when the workspace plugin lacks a restore method.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@nikhilachale
nikhilachale force-pushed the feat-toast-restore branch 2 times, most recently from 98a9ccb to db18542 Compare July 18, 2026 08:09
}

// RestoreModeView is the API-facing restore-mode enum.
type RestoreModeView = sessionmanager.RestoreMode

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Low priority: since restoreMode is now API-facing response metadata, I think the service should own this outward enum instead of aliasing the session_manager type directly. The docs describe session_manager as the orchestration/resource layer and service/session as the controller-facing result/read-model layer, so a small mapping from sessionmanager.RestoreMode into service-owned RestoreModeView constants would keep the wire contract decoupled from the core command result vocabulary.

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.

3 participants