Skip to content

feat(fm): remote View/Edit — native editor (daemon) + working-copy save-back (classic SSH)#33

Merged
iret77 merged 2 commits into
mainfrom
feat/fm-remote-view-edit
Jul 5, 2026
Merged

feat(fm): remote View/Edit — native editor (daemon) + working-copy save-back (classic SSH)#33
iret77 merged 2 commits into
mainfrom
feat/fm-remote-view-edit

Conversation

@iret77

@iret77 iret77 commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

What

Completes remote View/Edit (F3/F4) in the MC-style file manager for both remote host types. Local View/Edit shipped in #32; this PR adds the two remote paths:

Host type How editing works Save-back
Daemon host (⚡ resilient / devhost) Opened natively in the code editor, buffer-synced with the SSH daemon Real, version-checked save-back via the daemon (same path as the sidebar server browser)
Classic SSH-only host (no daemon) Downloaded to a local working copy, opened in the native editor SFTP upload back on every save

This closes the last mandatory gap in the file-manager Pflichtliste.

Host type 1 — daemon host (native)

The file manager is keyed by SSH node_id; the native editor needs a daemon HostId, which is opaque and only known after the daemon handshake. Bridged pull-based, observe-only:

  • Record node_id → daemon SessionId on connect (try_open_daemon_ssh_terminal) / adopt (adopt_daemon_session).
  • Resolve a live HostId on demand (daemon_host_for_node) via RemoteServerManager::{host_id_for_session, client_for_host}.

Self-correcting (session gone → graceful fallback) and never wrong (SessionIds are monotonic, never reused). The daemon session/connect flow is untouched — zero blast radius on the persistence feature.

Host type 2 — classic SSH (working copy + save-back)

Additive, low blast radius — one new event subscription, no editor surgery:

  • FileManagerRegistry::backend_for_namespace lends the workspace a live SFTP connection already open for the host (no second connect).
  • begin_remote_sftp_edit downloads the file into a unique local working copy (original filename kept for language + tab title), opens it via add_tab_for_code_file, and records it in Workspace::remote_sftp_edits keyed by the canonical local path — holding its own backend Arc so save-back survives the file-manager pane closing.
  • A single subscription to GlobalBufferModelEvent::FileSaved drives on_remote_working_copy_saved: if the saved path is a tracked working copy, upload it back. Ordinary local saves return immediately. A save landing mid-upload is coalesced (resave_pending) and re-run, so none is dropped.

No-data-loss contract

  • The remote file is only ever written by a save-back upload, never on open.
  • A failed upload keeps the working copy and shows a prominent, persistent error — the editor already flagged the local save as done, so a silent upload failure would be dangerous.
  • Concurrent external edits are last-write-wins on the next save — inherent to editing over plain SFTP (daemon hosts get the version-checked native path instead). Documented in code.

Working copies live under the OS temp dir in unique per-edit dirs (pid + counter, never reused; small text files, OS-reclaimed). No buffer-closed event exists to hook for eager deletion; stale map entries are harmless (a closed buffer emits no further save event → nothing uploads).

Verification

  • cargo check -p warp — clean, 0 errors/warnings. build.rs enables local_tty + local_fs on non-wasm, so both new #[cfg(all(unix, feature = "local_tty"))] paths are actually compiled (the shipping feature set). The PR gate (cargo check --bin zaplex) exercises the same cfgs.
  • cargo test -p warp --lib sftp_manager::fm_registry6 passed (incl. new backend_for_namespace); the whole lib compiles clean in test cfg too.
  • Runtime acceptance:
    • Daemon host (devhost): F3/F4 → native editor; edit + Save round-trips.
    • Classic SSH host: F3/F4 → working copy opens; edit + Save uploads back to the host.

Files

  • app/src/workspace/view.rsdaemon_node_sessions + daemon_host_for_node (native path); remote_sftp_edits + RemoteSftpEdit + begin_remote_sftp_edit + on_remote_working_copy_saved + FileSaved subscription (classic-SSH path); OpenFileInEditor routes through both.
  • app/src/sftp_manager/fm_registry.rsbackend_for_namespace (+ unit test).

🤖 Generated with Claude Code

iret77 and others added 2 commits July 5, 2026 12:37
The SFTP file manager (F3/F4) now opens a file on a remote host in the
native code editor when that host has a live persistent (daemon)
session: the editor buffer syncs with the daemon and writes back
safely — real Save, not a throwaway download. This is the devhost /
resilient-host case the user actually works in.

The file manager is keyed by the SSH `node_id`; the native editor needs
a daemon `HostId`, which is opaque and only known after the daemon
handshake completes. Bridge it pull-based: record `node_id → daemon
SessionId` when a resilient host connects (`try_open_daemon_ssh_terminal`)
or is adopted (`adopt_daemon_session`), and resolve a live `HostId` on
demand via `RemoteServerManager::{host_id_for_session, client_for_host}`
at open time (`daemon_host_for_node`). Re-checking the live manager on
every lookup makes a stale entry harmless (session gone → graceful
fallback), and since `SessionId`s are never reused an entry can only
ever resolve to its own host or to nothing — never a wrong host. The
daemon session/connect flow itself is untouched; the mapping is
observe-only, so no blast radius on the persistence feature.

Classic SSH-only hosts (no daemon) fall back to an honest toast instead
of editing a copy that would never save back; SFTP working-copy
save-back over classic SSH is the next increment.

Verified: `cargo check -p warp` compiles clean (build.rs enables
`local_tty` + `local_fs` = the shipping feature set; the native path is
actually compiled, not cfg'd out). Runtime acceptance: F3/F4 on a file
in a file-manager pane on a devhost (daemon) tab round-trips edit+save.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…k (F3/F4)

Completes remote View/Edit for the second host type: a classic SSH host
with no persistent daemon. F3/F4 on such a host now downloads the file to
a local working copy, opens it in the native editor, and uploads it back
over SFTP on every save — real Save, end to end.

Mechanism (additive, low blast radius — one new subscription, no editor
surgery):
- `FileManagerRegistry::backend_for_namespace` hands the workspace a live
  SFTP connection already open for the host, so there is no second connect.
- `begin_remote_sftp_edit` downloads into a unique local working copy
  (original filename kept for language detection + tab title), opens it via
  `add_tab_for_code_file`, and records it in `Workspace::remote_sftp_edits`
  keyed by the canonical local path — holding its own backend `Arc` so
  save-back survives the file-manager pane closing.
- A single subscription to `GlobalBufferModelEvent::FileSaved` drives
  `on_remote_working_copy_saved`: if the saved path is a tracked working
  copy, upload it back. Ordinary local saves return immediately. A save
  that lands mid-upload is coalesced (`resave_pending`) and re-run, so none
  is dropped.

No-data-loss contract: the remote file is only ever written by a save-back
upload (never on open); a failed upload keeps the working copy and shows a
prominent, persistent error — the editor already flagged the local save as
done, so a silent upload failure would be dangerous. Concurrent external
edits are last-write-wins on the next save, inherent to editing over plain
SFTP; daemon hosts get the version-checked native path instead.

Working copies live under the OS temp dir in unique per-edit dirs (pid +
counter, never reused); small text files, OS-reclaimed. There is no
buffer-closed event to hook for eager deletion, and stale map entries are
harmless: a closed buffer emits no further save event, so nothing uploads.

Verified: `cargo check -p warp` clean (0 errors/warnings); `fm_registry`
unit tests incl. new `backend_for_namespace` pass. Runtime acceptance:
F3/F4 on a file in a file-manager pane connected to a non-daemon SSH host,
edit + Save, confirm the change lands on the host.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@iret77 iret77 changed the title feat(fm): remote View/Edit — native editor on daemon hosts (F3/F4) feat(fm): remote View/Edit — native editor (daemon) + working-copy save-back (classic SSH) Jul 5, 2026
@iret77 iret77 merged commit 877c88e into main Jul 5, 2026
2 checks passed
@iret77 iret77 deleted the feat/fm-remote-view-edit branch July 5, 2026 12:45
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