mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-25 18:52:39 +00:00
main
7
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 |
||
|
|
fc3b2c4eb7 |
Sanitize plugin overview rendering: no raw HTML, https links only, no relative links (#6244)
* fix(plugins): restrict overview content to safe Markdown and HTTPS destinations Registry overviews are author-controlled content read away from their repositories. Apply a shared presentation policy instead of the documentation renderer so relative links, non-HTTPS URLs, raw HTML, and author styles never become active overview content. * fix(plugins): choose the first allowed screenshot for previews |
||
|
|
7fd469ae19 |
Enable plugin registry installs by default (#6224)
* feat(plugins): enable registry installs by default * fix(plugins): explain explicit Git source for missing registry IDs * fix(plugins): tailor missing registry guidance to installation * test(app): sample footer geometry in one browser frame * fix(plugins): make registry source resolution deterministic Directory existence must not change the meaning of a registry identifier shared by CLI, RPC, and UI installs. Classify explicit host paths in the source parser and explain recovery from registry transport and revision-selection failures. * fix(plugins): recognize dot and Windows directory sources * test(cli): wait for readable daemon ownership before cancellation The cancellation test raced PID-file creation against its first write and parsed empty JSON in CI. Use the public daemon-instance reader to wait for and capture the supervisor PID before asserting cancellation cleanup. * test(app): expect missing directory install guidance |
||
|
|
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 |
||
|
|
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. |
||
|
|
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 |