Skip to content

fix(ai-vault): delete a server-hosted session on the server that owns it - #33906

Merged
nwparker merged 1 commit into
mainfrom
fix/ai-vault-remote-delete
Oct 26, 2026
Merged

nwparker merged 1 commit into
mainfrom
fix/ai-vault-remote-delete

Conversation

@nwparker

@nwparker nwparker commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 6 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​351 $\color{#cf222e}{\Huge{\mathbf{−}}}$​43 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​308
Prod 25 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​491 $\color{#cf222e}{\Huge{\mathbf{−}}}$​77 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​414

ELI5

Agent Session History could only delete sessions stored on this computer. A session on a paired Orca server, or on an SSH host that Orca now runs a managed server on, always said "Only sessions on this device can be deleted." Now Delete asks the machine that owns the session to delete it.

What Changed

  • Before: in Agent Session History, Delete was disabled on every session from another machine.
  • After:
    • Delete works on a session that lives on a paired server or on an SSH host. Orca asks that machine to delete it, and the confirmation names the machine: "... will be deleted from Build box."
    • If the server runs an older Orca without this ability, Delete stays disabled with "Update Build box to delete its sessions from here." When Orca hasn't checked the server's version yet, clicking Delete checks it first, so you're never asked to confirm a delete the server can't do.
    • Only actions that are truly impossible stay disabled, with their existing reasons: synthetic rows (OpenCode SQLite), agents Orca never deletes, and rows whose owner is unresolved.
  • Mechanism:
    • New runtime RPC aiVault.deleteSession, advertised as aiVault.delete-session.v1. The host ignores any host id the client sends and deletes only its own files. It runs the same checks as a local delete against its own roots: known roots, scanner-discoverable paths, symlink and realpath containment, and WSL. Then it invalidates its list, parse and background caches.
    • Removal goes to the Trash on a desktop (Electron) host. A plain-Node host (orcad, headless) has no Trash, so the files are removed for good, matching remote file deletes (files.delete).
    • The desktop main process routes aiVault:deleteSession for a runtime: row to the owning server. Each row listed from a server is stamped with this desktop's pairing revision when it is scanned. The delete is fenced to that pairing, or to a same-host rotation of it, so if the same id is later re-paired to a different machine, that machine never receives the path. On success the main process invalidates its multi-host cache, which also stops scans already in flight from caching the deleted row again.
    • The browser client stamps rows and deletes on its own paired server the same way.
    • Clicking Delete on a server row checks the server's capability first. The check runs once per row, and shows "Checking …" if it takes more than a second.
    • The delete executor no longer imports Electron, so the plain-Node runtime can reuse it. Each caller passes its own remover.

Why

Since the managed-orcad migration (#27214), SSH hosts and paired servers are both runtime: hosts. One owner-routed RPC therefore covers every remote session. Proxying a raw files.delete instead would skip the delete-target validation, so the host has to run the same validator it runs for local deletes.

Thanks to @brynnclaw (#25169): that PR named the remote host by its user-facing label in the blocked-delete reason. This PR uses the same label (selectExecutionHostDisplayLabel) in the confirmation and in the "update the host" reason. Credited as co-author.

Linked Issue

Fixes #23556
Fixes #13471

Visual Proof

The change is copy in an existing confirmation dialog and tooltip, plus Delete becoming enabled on remote rows. No layout or styling change. Screenshots weren't captured: a paired server is needed to render a remote row.

Testing

  • src/main/runtime/rpc/methods/ai-vault-delete-session.test.ts (new) runs a real filesystem delete through the RPC dispatcher. The host deletes a transcript under its own roots even when the client sends another host id, refuses a path outside its roots and leaves it on disk, and advertises the capability. All three tests fail on main.

  • src/main/ipc/ai-vault.test.ts:

    • a runtime: row is routed to its owning host, this computer never touches the path, and the multi-host cache is invalidated;
    • the unresolved-owner sentinel is never routed;
    • a paired client's delete on a desktop host uses the Trash and the cache fence.
  • src/main/ai-vault/runtime-session-scanner.test.ts:

    • only the row identity goes over the wire;
    • the pairing revision is passed to the transport fence;
    • "update the host" appears only for this exact missing method, and other errors stay failures.
  • src/renderer/src/components/right-sidebar/ai-vault-session-deletability.test.ts: a server row offers Delete, an old server says "Update ", and synthetic and unroutable rows stay blocked.

  • src/renderer/src/components/right-sidebar/ai-vault-session-delete-action.test.tsx (new): a mounted row re-enables Delete when its host is updated in place.

  • runtime-session-scanner.test.ts: server rows carry this desktop's pairing stamp, not a value the host supplies.

  • Ran every test file that imports a changed module (26 files). All pass except AiVaultPanel.legacy-filter.test.tsx, which times out the same way on the unchanged base on this machine, pnpm tc, pnpm lint, the oxfmt check, the type-aware oxlint baseline, check:code-quality:changed, and check:runtime-electron-ratchet (the runtime still imports nothing from Electron).

  • Not run: the Docker managed-orcad e2e lane, and a manual delete against a live paired server.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

Review

  • Codex review and an independent review on the final head, no P0 to P2 findings left.

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Mixed versions: the new RPC and capability are additive. An old host answers method_not_found, which shows "Update ". An old client never calls the RPC. expectedEnvironmentPairingRevision is an optional IPC-only field and isn't sent to the host.
  • Cross-platform: the host runs the existing validator, which covers WSL UNC paths through tryDeleteWslUncPath. Windows, macOS and Linux hosts use the same code path.
  • Mobile: the mobile app has no Delete in its session history for any session, local or remote. With this RPC on the host, adding it there is now straightforward. Left as a follow-up.
  • Folder workspaces: delete is keyed on the transcript path, not the workspace, so folder and git workspaces behave the same.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

Agent Session History now routes Delete for a session on a paired or
SSH-managed Orca server to that server through a new aiVault.deleteSession
RPC. The host revalidates the path against its own roots, removes the
transcript (into Trash on a desktop host; permanently on a plain-Node host,
which has none), and invalidates its caches. Hosts advertise
aiVault.delete-session.v1; an older host keeps Delete disabled with
"Update <host> to delete its sessions from here."

Co-authored-by: brynnclaw <261708852+brynnclaw@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 2 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b35ba0cd-5b7e-46a9-9e98-f27c67e9a3ca
Commits

Reviewing files that changed from the base of the PR and between 007dfff and 8e85403.

Files ignored due to path filters: 1
  • src/shared/rpc-contract/rpc-params-catalog.generated.ts is excluded by !**/*.generated.*
Files selected for processing: 30
  • src/main/ai-vault/host-session-delete.ts
  • src/main/ai-vault/runtime-session-scanner.test.ts
  • src/main/ai-vault/runtime-session-scanner.ts
  • src/main/ai-vault/session-delete.test.ts
  • src/main/ai-vault/session-delete.ts
  • src/main/ipc/ai-vault-delete.ts
  • src/main/ipc/ai-vault.test.ts
  • src/main/ipc/register-core-handlers/register-core-handlers.ts
  • src/main/runtime/rpc/methods/ai-vault-delete-session.test.ts
  • src/main/runtime/rpc/methods/ai-vault.ts
  • src/main/runtime/runtime-ai-vault-commands.ts
  • src/main/runtime/runtime-service-command-surface.ts
  • src/renderer/src/components/right-sidebar/AiVaultSessionRow.tsx
  • src/renderer/src/components/right-sidebar/ai-vault-session-deletability.test.ts
  • src/renderer/src/components/right-sidebar/ai-vault-session-deletability.ts
  • src/renderer/src/components/right-sidebar/ai-vault-session-delete-action.test.tsx
  • src/renderer/src/components/right-sidebar/ai-vault-session-delete-action.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/pt.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/web/preload-api/web-ai-vault-api.ts
  • src/shared/ai-vault-runtime-capabilities.ts
  • src/shared/ai-vault-runtime-session-delete.ts
  • src/shared/ai-vault-session-deletion.ts
  • src/shared/ai-vault-types.ts
  • src/shared/rpc-contract/ai-vault-params.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@nwparker
nwparker merged commit e50fe1e into main Oct 26, 2026
41 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

1 participant