Commit Graph
5 Commits
Author SHA1 Message Date
Sebastian ArenaandMohamed Boudra 41582eb5fd Terminals survive daemon restarts, crashes and updates (#7644)
* M1: terminals survive daemon restarts: stop reasons, detached terminal worker, kill cleanup

restart_server_request.killTerminals / shutdown_server_request.keepTerminals and server_info.features.terminalsSurviveRestart; CLI daemon restart --kill-terminals and daemon stop --keep-terminals (capability-gated). The terminal worker runs detached over an owner-only, secret-authenticated socket and is adopted on daemon start. One kill cleanup contract (the reaper) by birth time, used by the daemon, the supervisor and stopDaemonInstance. Settings offers Restart and close terminals.

* M1: fix review findings: reaper session/table retry, short-command creation order, remote kill-restart cleanup report, stop test port

* M1: fix review findings: reaper-owned cleanup record, session member identity by terminal id, unreadable cleanup records, Settings restart error rendered in the card

* M2: worker protocol versions and draining, worker runs from its own copy, desktop upgrades keep terminals, out-of-date daemon notice, docs/terminal-worker.md

- Daemon classifies live workers by protocol: adopts current, drains one version old, shuts
  down older, leaves a newer one running and answers list/create with
  terminal_worker_incompatible (daemon status prints it). Never more than two workers.
- esbuild worker bundle (build:lib); a built daemon copies bundle, shell integration and
  node-pty into $PASEO_HOME/terminal-worker/<version>-<hash>/ and launches from it; copies no
  record names are pruned.
- Desktop app_update/version_mismatch stop with keep terminals on macOS/Linux; Windows and a
  daemon without the capability close them.
- Out-of-date daemon sidebar notice with Update button, worded by terminalsSurviveRestart.
- PASEO-13: unreadable worker records fail status and kill-restart retry.
- PASEO-14: a session member without a terminal id is unknown, not unrelated.
- Smoke test 46 with A/B installation fixtures and per-fixture CLI shims (PASEO-9 fold).

* M2: track in-flight worker requests without leaving an unhandled rejection

detach({ afterPendingRequests }) tracked each request with request.finally(), which rejects
with the request; a fire-and-forget send that timed out surfaced as an unhandled rejection
(worker-terminal-manager.test.ts). Track settlement only.

* M2: CI round 1 fixes: worker terminal manager in the MCP key test, status cleanup field, shared socket dir

- mcp-server.test.ts (new upstream test) built the worker manager with the old fork API;
  it now starts a real detached worker in a throwaway home.
- daemon-session.test.ts expected status without terminalCleanupUnconfirmed (added in M1).
- paseo-daemon.test.ts: a home under the scratch temp dir is too long for a unix socket, so
  the worker listens in the per-user paseo-<uid> directory, which outlives workers by design;
  the test now requires it to be empty instead of absent.

* M2: run Windows PowerShell by its install path for process identity

server-tests (windows-latest): bootstrap-provider-availability.test.ts starts a daemon with a
PATH that holds only git, and the terminal worker failed to start: 'cannot read its own process
identity: spawn powershell.exe ENOENT'. Process inspection (managed-processes.ts inspect and the
terminal worker's process table) now runs %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe.

* M2: lifecycle e2e plain stop uses the shutdown RPC on Windows

CI round 2, server-integration (windows-latest): 'stop and stop --force never signal processes
a stale or earlier-boot record names' called stopDaemonInstance without a shutdown channel,
which Windows refuses ('has no graceful shutdown channel'). Plain stops in the file now pass
one, as the CLI does.

* M2: native notice outlet, Windows desktop-update wording, worker cap counts unconfirmed cleanups, create recovers after a drain

* M2: phone sidebar mounts the callout slot (iOS notice verified), worker record reads retry transient errors

* M2: native notice preconditions use explicit working directories, one block per terminal

* M1: compact sidebar shows only native callouts on every platform; PTY round trips in the MCP key test get a 5 s window

* ci: pin Playwright browser jobs to ubuntu-24.04

The pinned Playwright (1.58) has no ubuntu-26.04 build, and forks whose
ubuntu-latest already resolves to 26.04 fail at browser install. Job names
are unchanged, so required-check contexts still match.

* ci: use ubuntu-latest for Playwright jobs, same as upstream

Reverts the ubuntu-24.04 pin; upstream main's Playwright shards pass on ubuntu-latest.

* fix(server): keep terminal worker record IO off the daemon event loop

* fix(server): restore terminal creation after worker failure

A disconnected terminal worker remained the current manager indefinitely, leaving dead sessions listed and every later create bound to a closed socket. Confirm process death before retiring the member and use the existing single launch path for replacement. Reconnect live workers and replay their screens while preserving terminal identity.

* test(server): verify orphan cleanup during worker recovery

Recovery reaps orphaned programs before a later daemon stop. The previous fixed-delay assertion raced that cleanup and failed when it completed promptly. Verify orphan removal, same-daemon replacement creation and cleanup on normal or forced stop instead.

* test(server): isolate Windows dependency fixture setup

Build the local package registry in setup so its npm packing processes do not consume the installation journey deadline. Install the platform package used by Windows runtime fixtures directly, avoiding an unused wrapper postinstall probe without a timeout.

* test(server): wait for pending watchers before disposal

Observation admission starts before asynchronous path setup reaches watcher subscription. Disposing at the admission counter races setup and never exercises late watcher cleanup. Wait for the subscriptions to be pending before disposing.

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-10-28 18:04:29 +07:00
Mohamed Boudra 92b92a81c8 perf(desktop): reduce daemon management memory overhead (#5007)
Desktop and CLI helpers imported daemon bootstrap through the server root, while supervisor configuration retained the full wire schema tree. Expose existing capabilities through narrow package entrypoints and share configuration schemas without loading message definitions. Guard the dependency trees without tree-shaking so unused exports cannot hide the runtime cost.
2026-09-17 15:18:12 +02:00
Ivan MalisonandClaude Opus 5 5d15e40a2b fix(nix): restore desktop app icon matching (#2506)
* fix(nix): identify desktop app for icon matching

* fix(desktop): ignore wrapper class in CLI passthrough

* fix(nix): give the Electron launcher a real app root

The Wayland app_id — what a bar or taskbar uses to find the .desktop
entry, and therefore the icon — is fixed during Electron startup, so
neither `--class=` nor main.ts's `app.setName()` reaches it on current
Electron. Launching `electron path/to/main.js` gives Electron no
package.json to read a name from, so the window published the default
"electron" app_id and shells drew the generic Electron icon.

Launch a one-file app root named "paseo-desktop" instead, matching the
installed desktop entry and hicolor icon. Older Electron (38) derives
the app_id from the runtime app name "Paseo", so also ship a NoDisplay
alias entry under that name; the icon resolves either way and the
launcher list still shows a single Paseo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 04:34:05 +08:00
Mohamed Boudra 20385bdb50 Add opt-in browser tools for desktop tabs
* Add opt-in browser tools for desktop tabs

Adds the daemon opt-in, desktop tab routing, MCP tools, and real browser automation surfaces for Paseo desktop browser tabs.

* Fix browser tools CI expectations

* Address browser tools review findings

* Restrict browser file automation paths

* Fix browser upload test on Windows

* Harden browser navigation inputs

* Make browser tools create usable tabs

* Update browser MCP empty-state test

* Fail browser tab creation when registration times out

* Fix browser screenshots for agents

* Hide disabled browser tools from agents

* Address browser tools architecture review

* Replace browser tools review tests

* Wrap browser tab registration errors

* Mock Expo Router in app unit tests

* Handle invalid browser automation requests

* Return browser failure on desktop disconnect

* Update browser disconnect websocket test

* Relax browser timeout polling test

* Handle invalid browser responses

* Return browser failure when send fails

* Remove local diagnostics and fixture paths

* Fix dev service home fallback

* Use worktree home for dev services

* Use managed daemon in desktop dev

* fix(browser): keep agent tabs addressable

Track agent-active browser targets separately from human-focused tabs and keep resident webviews alive for automation. Browser tool visibility now comes from registration while the broker reports disabled execution.

* refactor(browser): register tools through catalog

Move browser tool registration onto the shared Paseo tool catalog so the MCP server remains only the transport adapter.

* fix(settings): translate browser tools host error
2026-06-30 22:33:18 +02:00
Mohamed Boudra faf664d803 Fix desktop CLI passthrough tty handling (#791)
* Fix desktop CLI passthrough tty handling

* Fix desktop daemon manager test drift

* Update daemon stop test after main merge

* test(cli): isolate npx cache per CLI test
2026-05-07 15:14:18 +08:00