feat: session daemon - persistent remote terminal sessions#3360
feat: session daemon - persistent remote terminal sessions#3360lyx-tec wants to merge 19 commits into
Conversation
* fix: copy-on-select overwrites clipboard when search is open (#1) Change the guard in termwrap.ts from checking focused element (document.activeElement.closest) to checking DOM presence (document.querySelector) to prevent copy-on-select from firing whenever search is open, regardless of focus state. * chore: mark verification tasks complete, archive openspec change, sync specs
WaveTerm previously ignored the ProxyCommand directive in ~/.ssh/config, causing connections via SSH config Host entries with ProxyCommand to fail with 'Disconnected from xxx'. This change: - Parses ProxyCommand from SSH config in findSshConfigKeywords - Executes the proxy command via os/exec with %h/%p/%r expansion - Wraps command stdin/stdout as net.Conn via net.Pipe() - Cleans up the subprocess on connection close via proxyCommandConn Affects: pkg/wconfig/settingsconfig.go, pkg/remote/sshclient.go, frontend/types/gotypes.d.ts
- Change 'providedInputRef' to 'searchInputRef' in search.tsx - Add ssh:proxycommand to schema/connections.json - Run go mod tidy
When SSH config has ProxyCommand like 'ssh -W %h:%p jump-host', parse and convert it to ProxyJump internally. Falls back to subprocess-based execution for non-convertible ProxyCommands.
Remove expandProxyCommand, proxyCommandConn type, and ProxyCommand execution from connectInternal. ProxyCommand is now solely handled by parseProxyCommandAsJump conversion to ProxyJump.
…yJump + searchInputRef fix
- computeDirPart returns empty string for Windows drive roots - Add listDrives() to enumerate available drives - Handle empty path for drive listing in list/fileInfo commands - Fix getParentDirectory for backslash paths - Fix back button, bookmark, and parent entry for drives
…state display (#9) * feat: term block command config dialog with Save & Restart and error state display - Add CommandConfigModal dialog (Command, Run on startup, Clear on start, Env vars) - Replace 'Run On Startup' submenu with 'Configure Command...' menu item - Inject command as keystrokes into interactive shell (not -c mode) - Write cmd:lasterror meta key on non-zero exit, clear on exit 0 - Show red error icon in block header when cmd:lasterror is set - Add MetaKey_CmdLastError to MetaTSType / metaconsts.go * fix: clear cmd:lasterror before injection, add env var injection, fix error icon guard - Clear cmd:lasterror meta at shell start and before each injection - Add shell-specific env var injection (export for bash, envvar for pwsh, set -gx for fish) - Fix error icon: only set cmd:lasterror when InjectedCommand flag is true - Use backslash-r (0x0D) instead of backslash-r-backslash-n for ConPTY keystroke injection - Add 1500ms delay for shell raw mode initialization - Convert backslash-n to backslash-r for multi-line command injection - Add clickable error icon that opens MessageModal with details - Set controller double-quote shell double-quote in Save and Restart meta (was null) - Update OpenSpec skills-workflows to v1.4.1 * feat: inject cmd via shellInputCh, remove cmd:lasterror - Replace direct PTY write with shellInputCh channel (same path as user keystrokes) - Remove InjectedCommand tracking and cmd:lasterror meta mechanism - Remove red error icon UI for cmd blocks - Remove MetaKey_CmdLastError/CmdLastError type and generated files - Clean up unused useEffect import - Rename 'Configure Command...' to 'Startup Command...'
Add SessionDaemon data model, DB migration, meta key. Implement sessiondaemon package (Manager, idle reaper). Implement SessionDaemonController (Start/Stop/SendInput). Replace DurableShellController with SessionDaemonController. ResyncController dispatch: SSH blocks auto-create anonymous daemon. Simplify handleAppendJobFile (job-only write), remove IsBlockTermDurable. Frontend: TermWrap attachToDaemon/detachFromDaemon, zoneId switching. Add wsh session CLI (create/delete/list/attach/detach/info/tag). Add RPC types, handlers, generated bindings for session commands. Frontend: SessionDaemonIndicator in header + context menu items. Add startup migration for existing Block.JobId to SessionDaemon. Fix critical: GetRuntimeStatus returns init when no JobId. Fix TOCTOU race in Manager AttachBlock/DetachBlock. Add BlockId to SessionDetachData for per-block detach. Add resyncBlockController after detach. Add Version field to controller runtime status.
|
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (91)
WalkthroughThis PR adds OPSX prompt and skill documentation in multiple locations, adds a new session-daemon feature across backend, RPC, CLI, and frontend code, introduces a database migration and OpenSpec artifacts for that feature, and adds Playwright E2E setup plus a clipboard-search test. It also updates related types, configuration, remote SSH parsing, and several frontend preview/search utilities. Estimated code review effort🎯 5 (Critical) | ⏱️ ~90+ minutes ✨ Finishing Touches🧪 Generate unit tests (beta)
|
Summary
Implements Session Daemon architecture: decouple remote SSH sessions from block views, enabling multi-block attach/detach, named sessions, idle timeout, and persistent reconnection.
Replaces DurableShellController with a SessionDaemonController + SessionDaemonManager architecture.
Key Changes
Design
V2 design:
unOutputLoop stays in JobController. SessionDaemon is a thin orchestration layer (naming, multi-block tracking, idle timeout). Does not manage PTY, output streams, or processes.
See docs/design/session-daemon-design-v2.md for full design document.