Move supported protocol capabilities into client defaults and make session traffic subscription-driven. Preserve timeline readiness and reconnect recovery across SDK, CLI, and plugin consumers.
Accept plugin requirements against the runtime version or its stable core while preserving the legacy version boundary. Validate all example manifests, correct the ACP example metadata, and prepare plugin author documentation for the beta.
* fix(plugins): keep React out of the server plugin host
* fix(plugins): align SDK guidance and tests with runtime boundaries
* fix(plugin): loosen the react peer to ~19.1.0
The plugin SDK pins its react peer to exactly 19.1.0, and that pin is
what a downstream `npm i -g @getpaseo/cli` resolves against. So every
user ends up with react 19.1.0 in their global node_modules, where
corporate dependency scanners flag it: the CVE-2025-55182 advisory range
covers 19.1.0 even though the vulnerability itself lives in
react-server-dom-webpack/-parcel/-turbopack, none of which the CLI
installs. The user is then left hand-patching node_modules or
uninstalling Paseo.
Widening the peer to ~19.1.0 lets a downstream install pick the latest
19.1.x patch (19.1.9 today) while this repo stays on 19.1.0, which the
root override still pins.
Keeping the repo itself on 19.1.0 is deliberate. react-native 0.81.5
embeds a 19.1.0 Paper renderer that hard-throws "Incompatible React
versions" on any exact mismatch, and it is reachable from Fabric builds
too: RendererImplementation.js requires the Paper shim unconditionally
in findNodeHandle, unstable_batchedUpdates, sendAccessibilityEvent and
three other entry points, and react-native-gesture-handler re-exports
findNodeHandle. Bumping the app's react is therefore not safe until
react-native moves.
The published CLI tree contains no react-native, so downstream installs
are not subject to that constraint.
Supersedes the earlier 19.1.5/19.1.9 version-bump approach on this
branch, which would have broken the mobile app.
* Enforce example import ownership including client types
* Update Nix dependency hash for plugin peer metadata
* Group plugin APIs under client and server entry trees
* Resolve plugin type dependencies through declarations
* Validate declarations for implicit plugin type imports
* Preserve optional imports and validate declaration references
* Refresh Nix hash for plugin declaration resolver
* Canonicalize plugin paths consistently on Windows
* Normalize plugin ownership paths across resolver boundaries
---------
Co-authored-by: liujin0506 <liujin0506@qq.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
* fix(protocol): keep 0.7.2 clients working with 0.8 hosts
Gate plugin timeline rows and blocked workspace setup statuses per client capability so app-store version lag does not make existing agents unloadable. Preserve canonical pagination and document the intended Hub provider-mode authority.
* test(protocol): clarify compatibility test preconditions
Supplying a list controls scroll-container ownership, not whether content can move the sheet. Preserve the shared expand-scroll-dismiss interaction for model selectors and plugin lists, with native gesture regressions and updated plugin guidance.
* 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
* feat(plugins): support modal body layout, scrolling and clipboard actions
* fix(app): keep native scroll dependencies out of web imports
* fix(nix): sync dependency hash for plugin native types
* test(plugins): express modal QA as user journeys
* feat(plugins): contribute settings screens and shared controls
* fix(plugins): localize settings and verify shared UI consumers
* test(composer): unmount draft test roots after each case
* test(app): keep launch terminals alive until cleanup
The fixed ten-second profile lifetime could expire before a busy CI browser attached or finished revisiting the composer. Keep the real process waiting for input until project teardown terminates it.
* test(server): await the initial snapshot before a buffered ref event
Watcher setup can read checkout facts before the initial refresh publishes a snapshot. Wait for publication before injecting the event so the test consistently exercises a second refresh.
* feat(hub): continue agents through standard daemon operations
Authorize ordinary agent and workspace recovery operations with hub.execute. Keep conversation routing in Hub and persist generic creation and message receipts so retries cannot silently duplicate work.
* fix(hub): expose custom providers to continuing clients
Allow Hub to advertise provider support independently of the app version. Document the companion continuation policy and migration. Preserve newly observed files in the native watcher inventory so coalesced deletions remain visible to reconciliation, addressing the Windows CI failure.
* fix(hub): allow retries after confirmed local failures
Prepare message loading before recording dispatch intent. Remove failed creation receipts only when creation cleanup completed and no live or stored agent exists. Keep ambiguous provider deliveries fail-closed. Exercise native file observation with real filesystem dependencies.
* feat(terminals): expose workspace ownership through the SDK and CLI
Directory-based terminal creation selected the oldest workspace sharing that path. Expose explicit workspace ownership in the shared public API and CLI, retain ownership and process directories in listings, and acknowledge terminal deletion after teardown.
* fix(file-observer): preserve nested shallow reconciliation scopes
A parent directory scan does not visit its descendants. Collapsing change scopes discarded nested scans and left coalesced native deletions unseen until a full audit.
* test(terminals): extract output waits from end-to-end scenarios
Allow trusted local plugins to register complete coding-agent providers through the existing agent lifecycle. Includes direct and ACP implementations, SVG provider icons, custom timeline items, runnable examples, and public authoring documentation.
Closes#3547Closes#3556
Add backend-only exact-provider controls for the Paseo tool catalog across native and MCP-backed agents, including persisted configuration, session snapshots, public documentation, and regression coverage.\n\nCo-authored-by: Matt Cowger <matt@cowger.us>
Hub execution credentials need provider snapshot access so remote workflow editors can present the daemon's native models, modes, and thinking options without gaining broader daemon read authority.
Keep stable v0.7 guidance available while the client-entry layout is previewed for v0.8. Existing reference and migration URLs redirect to the release that owns their content.
* feat(cli): accept host as a global option
Keep the command-local position for compatibility while letting users place one daemon target before the command and reuse it while changing verbs. Local daemon lifecycle commands continue to operate locally.
* fix(cli): preserve project host resolution boundary
Project creation already handled PASEO_HOST directly. Avoid routing that established behavior through a newly exported client helper so its isolated command tests keep their existing dependency boundary.
* test(cli): allow scaffold typecheck under CI load
* test(cli): provide remote cwd in schedule e2e
* docs(cli): teach only global host syntax
* 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.
* feat(providers): add Gajae Code to the ACP provider catalog
Gajae Code (gjc) ships a conformance-tested ACP agent (`gjc acp`), so it can be
a one-click catalog entry instead of a hand-written custom provider in
config.json. Command and env match what the agent's own installer writes.
* feat(providers): add Gajae Code icon
---------
Co-authored-by: Yeachan-Heo <yeachan.heo@gmail.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
* feat(website): publish Hub pricing options
Present self-hosted and hosted Hub choices together while reading the hosted offer from Hub's public catalog.
* fix(website): require a valid hosted offer
* fix(website): preserve Hub page on catalog failure
Plugins can transform live timeline source items at render time, append durable plugin rows from daemon handlers, and register client-only slash commands in the composer.
Related to #3940 and #3952.
* feat(plugins): support prepared Git installations
Let Git plugins declare explicit preparation commands without making package installation the default. Keep installation transactional, make plugin trust explicit, and use one canonical source reference for monorepos.
* fix(plugins): parse Windows source references
Add transport-only SSH connectivity for the CLI and Electron desktop through the user's OpenSSH configuration. Remote installation and daemon lifecycle remain explicit, separate operations.
Preserve actionable SSH failure details when the proxy socket closes before the SSH child exits.
Closes#3949
Co-authored-by: James Strain <jstrain@nvidia.com>
Co-authored-by: Reid Levesque <reidlevesque@users.noreply.github.com>
* feat(plugins): add React Native UI primitives
Give client plugins host-owned adaptive UI without exposing app internals. Preserve plugin runtime contexts when modal content moves through the compact portal host.
* docs(plugins): clarify host UI reference
* refactor(plugins): harden host UI boundary
Replace mocked pass-through coverage with a real browser plugin journey, keep host runtime ownership inside the evaluator, preserve toast context across compact portals, and expose modal content as a compound component.
* fix(plugins): defer native UI presentation runtime
Loading the plugin evaluator initialized the modal and toast presentation stacks even when no plugin requested host UI. Keep the capability stable while delaying platform-heavy presentation code until Modal.Content renders.
* refactor(plugins): move modal metadata to root
Keep Modal.Content body-only while the top-level Modal owns the host-rendered title and leading icon. This leaves presentation metadata stable as the compound API gains future regions.
* feat(sdk): expose a session's own commands on the agent handle
`DaemonClient.listCommands` has always been able to ask a running session
which slash commands and skills it loaded, but `PaseoAgentHandle` never
surfaced it, so SDK and plugin consumers could only see what they could
find on disk. Provider built-ins — the ones bundled inside the agent
binary rather than installed into a scannable directory — were therefore
invisible to them.
Add `agent.commands()` as a thin delegation to the existing RPC. Every
provider that implements `listCommands` (claude, codex, opencode, acp,
omp, pi) answers it, so a consumer no longer needs per-provider
filesystem knowledge to enumerate what a session can run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(sdk): expose the observed agent snapshot on the agent handle
The handle mirrored four snapshot fields (workspaceId, cwd, status, id)
and hid the rest behind current(). Add getters for capabilities,
availableModes, pendingPermissions, activeTurn, lastUsage, lastError,
features, runtimeInfo, and archivedAt so callers can read one field
without destructuring the whole snapshot and null-checking it.
Each reads the last observed snapshot and never fetches, matching the
existing getters. null means "not observed yet".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs(sdk): clarify nullable snapshot getters
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: marvin-ambrozio <marvin@gustavo.eng.br>
Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
* feat(plugins): add timeline item contributions
Keep canonical daemon history unchanged while plugins project and render custom timeline items in clients. Live matches refresh authoritative projected history before replacement so lifecycle deltas stay collapsed.
* fix(nix): update npm dependency hash
The plugin SDK lockfile change invalidated the fixed-output npm dependency derivation. Use the hash calculated by the macOS Nix build for the current lockfile.
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.
A pairing offer remains valid across daemon restarts, so remove the incorrect rotation guidance and warn users where the durable credential is displayed.
Lead with the browser-to-CLI onboarding journey, document the generated starter bundle, and align guided setup with available Hub connections and daemon-reported runtime defaults.
Adds plugin-contributed light and dark app themes, including persistence, host-aware coalescing, fallback behavior, documentation, examples, and browser/iOS QA.
* docs(hub): drop the manual auth secret from self-hosting setup
Hub generates its authentication secret on first start and stores it in the
database it is already using, so self-hosters no longer run openssl or carry
PASEO_HUB_AUTH_SECRET between restarts. The variable stays as an override for
deployments that must supply the secret from a platform secret store; Hub uses
it without persisting it, so removing it resumes the stored value.
Also corrects a claim that predates this change: rotating the secret does not
invalidate execution credentials already issued. Hub verifies those against
persisted hashes rather than the secret, so only browser sessions end.
Documentation companion to https://github.com/getpaseo/hub/pull/50.
* docs(hub): lead with the local guided setup
* docs(hub): document XDG data directory
* docs: make Hub self-hosting the quickstart
The daemon imports the plugin SDK at runtime, but the workspace was named
@paseo/plugin and marked private, so it was never published. 0.5.0-beta.1
shipped @getpaseo/server depending on a package that does not exist and
`npm install @getpaseo/cli@beta` failed with a 404 for every user.
Two things hid it. sync-workspace-versions only rewrites deps matching
@getpaseo/*, so the "*" range on @paseo/plugin survived untouched into the
published tarball. And `npm pack --dry-run`, which is all release:check and
CI run, lists files without ever resolving the dependency graph.
Renaming to @getpaseo/plugin rather than publishing the old name: @paseo is
not our scope on npm, so that name could never have been published at all.
The rename also brings the package under the version-sync filter, which is
what pins it correctly from here on.
Plugins scaffolded against the old name still import @paseo/plugin. Both
spellings resolve through plugin-sdk-specifiers.ts, tagged COMPAT with a
removal date, so existing plugins keep loading.
This does not repair 0.5.0-beta.1 — a published tarball's dependencies
cannot be changed. The package publishes with the next release.
The plugin compiler spawned esbuild through app.asar, and the subprocess
imported the React client barrel. Point esbuild at the unpacked binary,
add a react-free @paseo/plugin/server entry, and pass a typed PluginTheme
so plugin UI follows the active theme on desktop and mobile.
* feat(skills): manage orchestration skills per host
Agent skills execute on the daemon host, so their bundle, selection, and filesystem convergence must share that owner. Preserve the existing install semantics while letting every capable client manage the selected host and migrating the legacy desktop preference once.
* fix(client): keep skill management internal
Keep host skill management on the low-level daemon client used by the app. Do not expose daemon settings or the desktop-only compatibility migration through the shared Paseo API handed to plugins.
* fix(e2e): declare skills fixture dependencies
Use Playwright's required destructuring form for the test-scoped daemon sandbox fixture so CI can collect the real-host skills suite.
* test(skills): use native managed paths
Assert fixed skill targets relative to the daemon user's real home with platform-native path joining so the ownership contract holds on Windows and POSIX hosts.
Keep the entry point focused on contribution wiring so client UI and daemon handlers can use their own runtime APIs safely. Surface compilation failures and lifecycle transitions in the retained plugin log tail.