mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-24 02:02:42 +00:00
44fdf72c8ff98aa264ff360e80467c2b4e0bd183
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
74c8172f8b |
Wait for a plugin reload to finish instead of failing at the request deadline (#6306)
* Wait for plugin reload completion instead of the request deadline The daemon answers plugin.reload.request only once the plugin is running again or has failed, and a reload queues behind other plugin lifecycle work such as an install with a preparation command. The shared client applied its sixty-second session RPC deadline to that request, so a slow reload failed with "Timeout waiting for message" while the daemon kept loading the plugin, inviting a reload the daemon was still running. Reload now waits for the daemon's own answer. Enable and disable keep the session deadline, and a real startup failure still reaches the caller. * Cover a slow plugin reload end to end The CLI fixture now holds its own git build on a gate file, starts a reload of an installed plugin behind that queued install, observes the reload request at the proxy, keeps the gate closed past the client's former one-minute deadline, and then asserts the reload's real result: CLI exit 0, the plugin running, and exactly one reactivation. Listing the plugin during the wait stays readable and does not restart it. A plugin that cannot start still fails its reload with the daemon's error. The request proxy that recorded install sources becomes a small observer that records any session request, so the wait is measured from the request boundary rather than from process start. Verified: npx tsx packages/cli/tests/e2e/plugin-lifecycle.test.ts exits 0 in 135 s; the same fixture without the new scenario takes 66 s. * Document how a reload reports its result The CLI docs now say `paseo plugin reload` waits for the daemon to stop and start the plugin, that cancelling the command or losing the connection does not stop the daemon's work, and that `plugin ls` shows the previous state until the reload finishes. The plugin reference records the lifecycle fact behind it: a reload queues behind the daemon's other plugin work, the daemon answers when the plugin is running again or has failed, and status reads, Settings and the logs are not the reload's outcome. * Cover the Settings reload wait end to end Adds a browser scenario for the ticket's user-facing half: with a gated git install holding the daemon's plugin lifecycle queue, the row's Reload goes out, the test keeps the gate closed past sixty seconds, asserts the row stays pending with no error feedback, then releases the build and asserts the daemon's plugin.reload.response and the app's "Reloaded e2e-plugin" result. The scenario turns plugins on through the daemon instead of the global switch, whose transient "Plugins enabled" confirmation is not its subject. The wait is measured from the reload request frame, which is an outbound frame, not from the response stream. Verified: npx playwright test --project=browser e2e/browser/plugin-management.spec.ts -g "keeps Reload pending past a minute" -> 1 passed (1.5m); plugin-reload-pending.png, plugin-reload-past-deadline.png and plugin-reload-completed.png show the pending row, the surface past the former deadline with no error, and the finished reload. * Correct the status guidance for a cancelled reload Review finding: the note said a listing keeps the plugin's previous state until the reload finishes, but that only holds while the reload is still queued. Once it executes, the daemon removes the plugin from the runtime catalog before stopping it (plugins/runtime.ts:377-382) and resolvePluginStatus maps an enabled plugin that is not running to "failed" (plugins/index.ts:71-78), so a listing read in that window shows failed for a healthy reload. Both passages now separate the two windows and say that neither a listing nor the logs report the outcome of the outstanding reload. The interim "failed" itself is TUC-1401. * Harden the reload coverage against failures and lost connections Review findings folded into the tests: The Settings scenario releases its gated build in a finally block. Before this, a failing assertion left the build polling forever, the daemon's plugin lifecycle queue stayed blocked, and the fixture teardown's own removePlugin timed out behind it. It also asserts the row's actions are enabled again once the reload settles, next to the result feedback. The connection-close regression now reconnects and asserts nothing resends the lost reload; the no-replay invariant already covered for legacy requests now holds for a pending reload too. Verified: npx vitest run packages/client/src/daemon-client.test.ts -> 161 passed. npx playwright test --project=browser e2e/browser/plugin-management.spec.ts -g "keeps Reload pending past a minute" -> 1 passed (1.4m). * Let the gated build finish before its files go Review finding on packages/cli/tests/e2e/plugin-lifecycle.test.ts:450: the finally block released the gate and deleted the gate directory without waiting for the install and the reload it had started. The build polls for the gate file, so cleanup could delete the release before the child saw it and leave the build waiting until daemon shutdown. The fixture now keeps both promises, releases the gate, and awaits them before deleting their files. Verified: npx tsx packages/cli/tests/e2e/plugin-lifecycle.test.ts -> exit 0, 161 s. * Read the reload scenario as intent, not transport code Review finding: the new browser scenario kept frame parsing, selectors, polling, deadline arithmetic, screenshots and gate cleanup in one body. docs/testing.md asks for complex setup in reusable helpers. The wire observation, the gated queue hold, the row-state assertions, the deadline wait and the surface captures are helpers now, and the body reads as the flow: open Settings, hold the queue, reload, still pending past the deadline, release, read the daemon's result. Verified: npx playwright test --project=browser e2e/browser/plugin-management.spec.ts -g "keeps Reload pending past a minute" -> 1 passed (1.4m). * Keep the reload lifecycle fact in one document Review finding: the cli.md paragraph repeated the queue and interim-state explanation that the plugin reference already owns. CLAUDE.md: "One fact, one doc. Every other mention is a link." The reference keeps the full explanation; the CLI page states what the command does and links there. * Release the gated build when its setup fails Review finding: holdPluginLifecycleQueue started the install, then waited up to 30 seconds for the build's started marker. A preparation that took longer made the helper throw before it returned its cleanup handle and before the test entered its try block, so nothing wrote the release file: the build polled forever, the daemon's plugin lifecycle queue stayed blocked, and the fixture's own removePlugin timed out behind it. The helper now owns that failure path: it releases the gate and drains the install before rethrowing, so a queue it hands out is always settleable. Verified on Linux (Chromium, Playwright): - With the started marker suppressed in a temporary local patch, the run fails at the 30-second marker wait inside the helper and the teardown still completes (both attempts ~33 seconds, no removePlugin request timeout). - With the marker in place, the scenario passes: 1 passed (1.4m). * Keep an early install failure out of the unhandled path Review finding: the marker wait in holdPluginLifecycleQueue ran before the install promise had a rejection handler, so a preparation that failed or a connection that closed before the build wrote its marker surfaced as an unhandled rejection, which fails the run before the helper's own catch can drain the queue. The helper attaches a handler the moment the install starts and races the marker wait against the install, so an early failure reaches the caller as the daemon's own error, a build that never writes its marker still fails as a 30-second marker timeout, and every path releases the gate and drains the install. Verified on Linux (Chromium, Playwright), patching the build command locally for each failure branch: - Early failure (build exits 1): fails in 4.2 s with the daemon's DaemonRpcError for plugin.source.install.request, no unhandled rejection, teardown completes. - No marker (build waits for the gate): fails at the 30-second marker wait, no unhandled rejection, teardown completes with no removePlugin request timeout. - Unpatched: 1 passed (1.5m). * Keep a failed launch from ending the run before its cleanup |
||
|
|
a292b402cf |
Resolve local plugin directories in the CLI's working directory (#6239)
* fix(cli): resolve local plugin directories from the caller's cwd Relative plugin sources were sent unchanged, so a daemon started elsewhere inspected the wrong directory. Resolve directory sources and expand the caller's home before sending, preserving subdirectory suffixes and managed source identifiers. * fix(cli): preserve absolute plugin paths across host platforms A remote daemon may use another operating system. Recognize absolute POSIX and Windows directory sources before resolving relative paths on the CLI host. |
||
|
|
047f40e623 |
Install npm plugins and review source updates (#4975)
* feat(plugins): unify source installation and simplify plugin settings * feat(plugins): install npm sources and review CLI updates Treat install selectors as one-time choices. Keep source identity separate from the installed revision, and resolve ordinary updates from the current upstream default. npm only acquires directories; plugin loading remains independent of npm. * fix(plugins): preserve CLI diagnostics and exercise reviewed updates Move new source capability coverage to real browser journeys. Update the requirements regression to exercise preview and apply, and preserve the existing duplicate-selector diagnostic across positional option scopes. * test(plugins): remove unused pending helper * test(plugins): pack registry fixtures with the Windows command runner * test(plugins): assert failed client contribution setup * docs(plugins): consolidate guides and document npm publishing * docs(plugins): introduce publishing choices before npm instructions * test(plugins): own browser journey cleanup in a fixture * feat(plugins): prepare scaffolded packages for publishing |
||
|
|
0110302b6f |
fix(daemon): keep lifecycle operations on the selected instance (#4575)
* fix(daemon): keep lifecycle operations on the selected instance Restart reconstructed launch inputs and address fallback could redirect a home-selected shutdown to another daemon. Let supervisors publish bound endpoints, retain their worker restart contract, and share captured local lifecycle ownership between CLI and Desktop. * test(daemon): verify bounded desktop readiness and cancellable artifacts * test(cli): verify reload target hints and durable offline pairing * test(daemon): align lifecycle fixtures with ownership and targeting * fix(daemon): preserve reachability when status details time out Provider discovery can outlast a status request after authentication succeeds. Keep local connection facts separate from unavailable details, while explicit remote queries retain their error outcome. Migrate CLI and packaged Desktop fixtures to persistent managed configuration and explicit targets. Isolate generic Git observation from forge discovery and reuse disposable CLI homes on Windows. * test(daemon): observe restart through the worker status RPC The bounded CLI status observation may omit worker details while an authenticated connection remains healthy. Exercise the app-style restart through its full RPC and retain the replacement observation, with a real slow provider probe covering the distinction. |
||
|
|
a5d2b7d863 |
Declare and enforce plugin Paseo version requirements (#4430)
* feat(plugins): enforce declared Paseo version requirements Treat manifests without a Paseo requirement as pre-0.8 plugins so the first breaking plugin release offers an explicit migration path. Check the daemon and app independently before plugin execution, and preserve installed Git revisions when updates are incompatible. * fix(nix): refresh dependency hash for plugin requirements * refactor(plugins): validate test manifest inputs and name compatibility input |
||
|
|
53d824a320 |
feat(plugins): split client and server plugin entries (#4206)
* feat(plugins): phase 1 split runtime entries after green gate The compiler now builds explicit client and server entries, so runtime boundaries are source-owned instead of registration-name filtering. Compiler and runtime tests prove the entry split, directory and suffix boundaries, client Node import errors, migration failure, and client-only operation without a subprocess. * feat(plugins): phase 2 run client entries after green gate Explicit client and server contexts replace the mixed plugin context. The app runner owns every client registration and its idempotent removal, including late contributions and composer pills; focused contribution tests prove the removal contract, and all five migrated examples reached running on the isolated worktree daemon. * feat(cli): phase 3 scaffold runtime split after green gate The generated project demonstrates the required shared RPC contract, server handler, client surface, and sidebar wiring. The scaffold test and an isolated init, typecheck, install, and running check prove the phase acceptance path. * docs(plugins): phase 4 publish migration after green gate Gate: current docs and the paseo-plugin skill describe only explicit client/server entries. The standalone migration guide maps every former registration, and migration-doc.test.ts proves every client add* method remains represented. * fixup! feat(plugins): phase 1 split runtime entries after green gate Gate: compiler 13, runtime 24, typecheck, lint, and format passed. The dependency fixture proved node_modules/client was incorrectly treated as a plugin boundary. * fixup! feat(plugins): phase 2 run client entries after green gate Gate: client runtime and registry tests, typecheck, lint, format * fixup! docs(plugins): phase 4 publish migration after green gate Gate: migration docs test, paragraph audit, typecheck, lint, format * fixup! feat(plugins): phase 1 split runtime entries after green gate Gate: compiler organization tests, typecheck, lint, targeted format * fixup! feat(plugins): phase 2 run client entries after green gate Gate: shared SDK tests, runtime tests, typecheck, lint, targeted format * fixup! feat(cli): phase 3 scaffold runtime split after green gate * fixup! docs(plugins): phase 4 publish migration after green gate * fixup! feat(plugins): phase 1 split runtime entries after green gate * docs(plugins): rewrite public plugin docs for runtime entries and mobile guardrails * fixup! feat(cli): phase 3 scaffold runtime split after green gate The scaffold now keeps DOM globals out of the program and declares only window.open inside client/web.ts. The scaffold test invokes tsc in a fresh process, proves the generated project passes, and proves a stray document access fails. * fixup! docs(plugins): phase 4 publish migration after green gate The internal guide and plugin skill now forbid both the DOM lib and triple-slash DOM references. They direct web adapters to declare only the globals used by client/web.ts. * fixup! feat(plugins): phase 1 split runtime entries after green gate Removing the obsolete Babel parser changes the locked npm dependency graph. The macOS Nix desktop gate reported the new fixed-output hash, which this commit records. * fixup! feat(plugins): phase 1 split runtime entries after green gate Reject relative imports that escape the plugin root while continuing to skip resolved node_modules internals. The compiler regression test proves the escaped import is rejected and the dependency-internal fixture remains accepted. * fixup! feat(plugins): phase 1 split runtime entries after green gate Classify absolute imports and reject plugin-authored paths that escape into node_modules. Dependency internals remain exempt based on their importer path. Red-first compiler regressions cover both bypasses, and the existing dependency fixture remains green. * fixup! feat(plugins): phase 1 split runtime entries after green gate Classify canonical esbuild resolution results so dependency-relative and symlink imports cannot escape client/server boundaries. The two compiler regressions failed before the fix and pass afterward. * test(ci): synchronize flaky state transitions Wait for repository watcher registration before emitting buffered ref events, let sidebar order polling retry unlaid-out rows, and wait for the inactive browser parking state before screenshot capture. These changes directly address the three observed CI failures; the affected server, Playwright, and desktop browser tests pass locally. * test(ci): synchronize Mermaid completion layout assertion The Playwright streaming acceptance test exposed a completion remount between visibility and layout sampling. Check the existing completion promise around the measurement so that transition is not reported as diagram loss. * fixup! feat(plugins): phase 1 split runtime entries after green gate Resolve bare package imports before boundary classification so symlinked dependency entries cannot expose server modules to the client bundle. The focused regression proves the bypass and the compiler file passes 20/20. * fixup! feat(plugins): phase 1 split runtime entries after green gate Allow canonical paths only within a matching linked package root while preserving runtime and containment checks for imports that leave it. The linked-dependency regression fails before the fix and compiler tests pass 21/21 afterward. * fixup! feat(plugins): phase 1 split runtime entries after green gate Reject matching package manifests that contain the plugin or live inside it, so linked-dependency roots cannot exempt plugin or workspace files. The ancestor-manifest regression fails before the fix and compiler tests pass 22/22 afterward. * fixup! feat(plugins): phase 1 split runtime entries after green gate Validate plugin-local lexical boundaries before canonical linked-root exemptions and require remembered-root imports to originate inside that root. The linked-root bypass regression fails before the fix and compiler tests pass 23/23 afterward. |
||
|
|
ecfb77b014 |
feat(plugins): install and update Git sources (#3920)
Make every trusted Git repository directly distributable without introducing a registry or package manager. Managed checkouts retain their resolved commit, track branches explicitly, and stage validation before activation so failed updates restore the running version. |
||
|
|
23853a1515 |
Add managed local plugin lifecycle (#3222)
* feat(plugins): add local plugin surfaces and RPCs Keep plugin execution scoped to its daemon while allowing one local TypeScript entry point to contribute validated RPCs and native client surfaces. Paseo owns host selection, navigation chrome, and per-installation query caches. * feat(plugins): add Linear attachment source * fix(nix): refresh npm dependency hash * test(server): exclude internal sessions from Hub counts * test(server): distinguish Hub execution sessions * feat(plugins): make local plugins explicitly opt-in Keep plugin loading dormant until configuration enables it, and collect unsupported examples under one directory. * refactor(plugins): establish host boundaries * fix(nix): refresh plugin dependency hash * fix(plugins): complete packaging and startup rollback * feat(plugins): add managed local lifecycle Make trusted local plugins recoverable and authorable through daemon-owned lifecycle operations, host settings, and a capability-gated CLI. Reloads fully stop the previous plugin before starting new code, while generated projects provide strict TSX checking without changing runtime dependency ownership. * fix(nix): refresh plugin dependency hash |