fix(plugins): publish the plugin SDK under the @getpaseo scope

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.
This commit is contained in:
Mohamed Boudra
2026-08-19 15:52:51 +02:00
parent ce905d9483
commit 929d2b717e
42 changed files with 216 additions and 188 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ RUN set -eux; \
npm pack --workspace=@getpaseo/relay --pack-destination /tmp/paseo-packs; \ npm pack --workspace=@getpaseo/relay --pack-destination /tmp/paseo-packs; \
npm pack --workspace=@getpaseo/protocol --pack-destination /tmp/paseo-packs; \ npm pack --workspace=@getpaseo/protocol --pack-destination /tmp/paseo-packs; \
npm pack --workspace=@getpaseo/client --pack-destination /tmp/paseo-packs; \ npm pack --workspace=@getpaseo/client --pack-destination /tmp/paseo-packs; \
npm pack --workspace=@paseo/plugin --pack-destination /tmp/paseo-packs; \ npm pack --workspace=@getpaseo/plugin --pack-destination /tmp/paseo-packs; \
npm pack --workspace=@getpaseo/server --pack-destination /tmp/paseo-packs; \ npm pack --workspace=@getpaseo/server --pack-destination /tmp/paseo-packs; \
npm pack --workspace=@getpaseo/cli --pack-destination /tmp/paseo-packs npm pack --workspace=@getpaseo/cli --pack-destination /tmp/paseo-packs
+9 -9
View File
@@ -53,7 +53,7 @@ my-plugin/
``` ```
Paseo compiles TypeScript and TSX when loading the plugin, so these packages are development dependencies only. Paseo compiles TypeScript and TSX when loading the plugin, so these packages are development dependencies only.
The generated declaration file supplies `@paseo/plugin` and `@paseo/plugin/server` types until the The generated declaration file supplies `@getpaseo/plugin` and `@getpaseo/plugin/server` types until the
SDK is distributed as a public package. Regenerate new plugins with the matching Paseo CLI when the SDK is distributed as a public package. Regenerate new plugins with the matching Paseo CLI when the
SDK contract changes. SDK contract changes.
@@ -96,15 +96,15 @@ code lives behind filename boundaries:
| `*.server.ts` | Node APIs, filesystem and process access, credentials, and handlers. | | `*.server.ts` | Node APIs, filesystem and process access, credentials, and handlers. |
| `*.shared.ts` | Zod RPC contracts and plain values used by both runtimes. | | `*.shared.ts` | Zod RPC contracts and plain values used by both runtimes. |
Shared files import contracts from `@paseo/plugin/server`. Client files import hooks from Shared files import contracts from `@getpaseo/plugin/server`. Client files import hooks from
`@paseo/plugin`. Plugin UI runs on desktop and mobile across multiple themes: color every `@getpaseo/plugin`. Plugin UI runs on desktop and mobile across multiple themes: color every
`Text` from `theme.colors.foreground` or `theme.colors.foregroundMuted`, and size layout from `Text` from `theme.colors.foreground` or `theme.colors.foregroundMuted`, and size layout from
`layout.compact`. See `public-docs/plugins/reference.md`. `layout.compact`. See `public-docs/plugins/reference.md`.
| Module | Use it for | | Module | Use it for |
| ---------------------- | -------------------------------------------------------- | | ------------------------- | -------------------------------------------------------- |
| `@paseo/plugin` | hooks and UI types | | `@getpaseo/plugin` | hooks and UI types |
| `@paseo/plugin/server` | `defineRpc`, `defineAttachmentSource`, and handler types | | `@getpaseo/plugin/server` | `defineRpc`, `defineAttachmentSource`, and handler types |
The compiler removes client registrations and imports from the server entry point, and server The compiler removes client registrations and imports from the server entry point, and server
registrations and imports from the client entry point. Importing a `*.server` module from a client registrations and imports from the client entry point. Importing a `*.server` module from a client
@@ -113,7 +113,7 @@ such as `StyleSheet.create` belong in `*.client.tsx`; placing them in `index.ts`
server bundle. server bundle.
```ts ```ts
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { Greeting } from "./greeting.client"; import { Greeting } from "./greeting.client";
import { createGreeting } from "./greeting.server"; import { createGreeting } from "./greeting.server";
import { greetRpc } from "./greeting.shared"; import { greetRpc } from "./greeting.shared";
@@ -178,7 +178,7 @@ search picker, drafts, selected pill, and submission. The plugin returns complet
credentials and vendor API calls stay in the daemon handler. credentials and vendor API calls stay in the daemon handler.
```ts ```ts
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { search } from "./issues.server"; import { search } from "./issues.server";
import { issues, searchIssues } from "./issues.shared"; import { issues, searchIssues } from "./issues.shared";
+1 -1
View File
@@ -120,7 +120,7 @@ republish the packages:
```bash ```bash
PASEO_VERSION=$(node -p "require('./package.json').version") PASEO_VERSION=$(node -p "require('./package.json').version")
for package in highlight relay protocol client server cli; do for package in highlight relay protocol client plugin server cli; do
npm dist-tag add "@getpaseo/$package@$PASEO_VERSION" beta npm dist-tag add "@getpaseo/$package@$PASEO_VERSION" beta
done done
``` ```
+34 -60
View File
@@ -6247,6 +6247,10 @@
"resolved": "packages/highlight", "resolved": "packages/highlight",
"link": true "link": true
}, },
"node_modules/@getpaseo/plugin": {
"resolved": "packages/plugin",
"link": true
},
"node_modules/@getpaseo/protocol": { "node_modules/@getpaseo/protocol": {
"resolved": "packages/protocol", "resolved": "packages/protocol",
"link": true "link": true
@@ -9556,10 +9560,6 @@
"node": "^20.19.0 || >=22.12.0" "node": "^20.19.0 || >=22.12.0"
} }
}, },
"node_modules/@paseo/plugin": {
"resolved": "packages/plugin",
"link": true
},
"node_modules/@pinojs/redact": { "node_modules/@pinojs/redact": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz",
@@ -11181,8 +11181,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-android-arm64": { "node_modules/@rollup/rollup-android-arm64": {
"version": "4.59.0", "version": "4.59.0",
@@ -11195,8 +11194,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.59.0", "version": "4.59.0",
@@ -11209,8 +11207,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-darwin-x64": { "node_modules/@rollup/rollup-darwin-x64": {
"version": "4.59.0", "version": "4.59.0",
@@ -11223,8 +11220,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-freebsd-arm64": { "node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.59.0", "version": "4.59.0",
@@ -11237,8 +11233,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"freebsd" "freebsd"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-freebsd-x64": { "node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.59.0", "version": "4.59.0",
@@ -11251,8 +11246,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"freebsd" "freebsd"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": { "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.59.0", "version": "4.59.0",
@@ -11265,8 +11259,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-arm-musleabihf": { "node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.59.0", "version": "4.59.0",
@@ -11279,8 +11272,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-arm64-gnu": { "node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.59.0", "version": "4.59.0",
@@ -11293,8 +11285,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-arm64-musl": { "node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.59.0", "version": "4.59.0",
@@ -11307,8 +11298,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-loong64-gnu": { "node_modules/@rollup/rollup-linux-loong64-gnu": {
"version": "4.59.0", "version": "4.59.0",
@@ -11321,8 +11311,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-loong64-musl": { "node_modules/@rollup/rollup-linux-loong64-musl": {
"version": "4.59.0", "version": "4.59.0",
@@ -11335,8 +11324,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-ppc64-gnu": { "node_modules/@rollup/rollup-linux-ppc64-gnu": {
"version": "4.59.0", "version": "4.59.0",
@@ -11349,8 +11337,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-ppc64-musl": { "node_modules/@rollup/rollup-linux-ppc64-musl": {
"version": "4.59.0", "version": "4.59.0",
@@ -11363,8 +11350,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-riscv64-gnu": { "node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.59.0", "version": "4.59.0",
@@ -11377,8 +11363,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-riscv64-musl": { "node_modules/@rollup/rollup-linux-riscv64-musl": {
"version": "4.59.0", "version": "4.59.0",
@@ -11391,8 +11376,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-s390x-gnu": { "node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.59.0", "version": "4.59.0",
@@ -11405,8 +11389,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-x64-gnu": { "node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.59.0", "version": "4.59.0",
@@ -11419,8 +11402,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-linux-x64-musl": { "node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.59.0", "version": "4.59.0",
@@ -11433,8 +11415,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-openbsd-x64": { "node_modules/@rollup/rollup-openbsd-x64": {
"version": "4.59.0", "version": "4.59.0",
@@ -11447,8 +11428,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"openbsd" "openbsd"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-openharmony-arm64": { "node_modules/@rollup/rollup-openharmony-arm64": {
"version": "4.59.0", "version": "4.59.0",
@@ -11461,8 +11441,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"openharmony" "openharmony"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-win32-arm64-msvc": { "node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.59.0", "version": "4.59.0",
@@ -11475,8 +11454,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-win32-ia32-msvc": { "node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.59.0", "version": "4.59.0",
@@ -11489,8 +11467,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-win32-x64-gnu": { "node_modules/@rollup/rollup-win32-x64-gnu": {
"version": "4.59.0", "version": "4.59.0",
@@ -11503,8 +11480,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
], ]
"peer": true
}, },
"node_modules/@rollup/rollup-win32-x64-msvc": { "node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.59.0", "version": "4.59.0",
@@ -11517,8 +11493,7 @@
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
], ]
"peer": true
}, },
"node_modules/@rtsao/scc": { "node_modules/@rtsao/scc": {
"version": "1.1.0", "version": "1.1.0",
@@ -19112,7 +19087,6 @@
"dev": true, "dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"optional": true, "optional": true,
"peer": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -36154,12 +36128,12 @@
"@getpaseo/client": "*", "@getpaseo/client": "*",
"@getpaseo/expo-two-way-audio": "*", "@getpaseo/expo-two-way-audio": "*",
"@getpaseo/highlight": "*", "@getpaseo/highlight": "*",
"@getpaseo/plugin": "*",
"@getpaseo/protocol": "*", "@getpaseo/protocol": "*",
"@gorhom/bottom-sheet": "^5.2.14", "@gorhom/bottom-sheet": "^5.2.14",
"@gorhom/portal": "^1.0.14", "@gorhom/portal": "^1.0.14",
"@marijn/find-cluster-break": "^1.0.2", "@marijn/find-cluster-break": "^1.0.2",
"@mattermost/react-native-paste-input": "2.0.1", "@mattermost/react-native-paste-input": "2.0.1",
"@paseo/plugin": "*",
"@react-native-async-storage/async-storage": "2.2.0", "@react-native-async-storage/async-storage": "2.2.0",
"@react-native-masked-view/masked-view": "^0.3.2", "@react-native-masked-view/masked-view": "^0.3.2",
"@react-native/normalize-colors": "^0.81.5", "@react-native/normalize-colors": "^0.81.5",
@@ -38625,13 +38599,13 @@
} }
}, },
"packages/plugin": { "packages/plugin": {
"name": "@paseo/plugin", "name": "@getpaseo/plugin",
"version": "0.5.0-beta.1", "version": "0.5.0-beta.1",
"dependencies": { "dependencies": {
"use-sync-external-store": "^1.6.0" "use-sync-external-store": "^1.6.0"
}, },
"devDependencies": { "devDependencies": {
"@getpaseo/client": "*", "@getpaseo/client": "0.5.0-beta.1",
"@types/node": "^20.9.0", "@types/node": "^20.9.0",
"@types/react": "~19.2.0", "@types/react": "~19.2.0",
"react": "19.1.0", "react": "19.1.0",
@@ -38640,7 +38614,7 @@
"zod": "^4.4.3" "zod": "^4.4.3"
}, },
"peerDependencies": { "peerDependencies": {
"@getpaseo/client": "*", "@getpaseo/client": "0.5.0-beta.1",
"react": "19.1.0", "react": "19.1.0",
"zod": "^4.4.3" "zod": "^4.4.3"
} }
@@ -38886,12 +38860,12 @@
"@babel/parser": "^7.29.8", "@babel/parser": "^7.29.8",
"@getpaseo/client": "0.5.0-beta.1", "@getpaseo/client": "0.5.0-beta.1",
"@getpaseo/highlight": "0.5.0-beta.1", "@getpaseo/highlight": "0.5.0-beta.1",
"@getpaseo/plugin": "0.5.0-beta.1",
"@getpaseo/protocol": "0.5.0-beta.1", "@getpaseo/protocol": "0.5.0-beta.1",
"@getpaseo/relay": "0.5.0-beta.1", "@getpaseo/relay": "0.5.0-beta.1",
"@isaacs/ttlcache": "^2.1.4", "@isaacs/ttlcache": "^2.1.4",
"@modelcontextprotocol/sdk": "^1.20.1", "@modelcontextprotocol/sdk": "^1.20.1",
"@opencode-ai/sdk": "1.14.46", "@opencode-ai/sdk": "1.14.46",
"@paseo/plugin": "*",
"@xterm/headless": "^6.0.0", "@xterm/headless": "^6.0.0",
"ai": "5.0.78", "ai": "5.0.78",
"ajv": "^8.20.0", "ajv": "^8.20.0",
+7 -7
View File
@@ -47,8 +47,8 @@
"build": "npm run build --workspaces --if-present", "build": "npm run build --workspaces --if-present",
"build:highlight": "npm run build --workspace=@getpaseo/highlight", "build:highlight": "npm run build --workspace=@getpaseo/highlight",
"build:highlight:clean": "npm run build:clean --workspace=@getpaseo/highlight", "build:highlight:clean": "npm run build:clean --workspace=@getpaseo/highlight",
"build:plugin": "npm run build --workspace=@paseo/plugin", "build:plugin": "npm run build --workspace=@getpaseo/plugin",
"build:plugin:clean": "npm run build:clean --workspace=@paseo/plugin", "build:plugin:clean": "npm run build:clean --workspace=@getpaseo/plugin",
"build:relay": "npm run build --workspace=@getpaseo/relay", "build:relay": "npm run build --workspace=@getpaseo/relay",
"build:relay:clean": "npm run build:clean --workspace=@getpaseo/relay", "build:relay:clean": "npm run build:clean --workspace=@getpaseo/relay",
"build:protocol": "npm run build --workspace=@getpaseo/protocol", "build:protocol": "npm run build --workspace=@getpaseo/protocol",
@@ -102,11 +102,11 @@
"version:all:beta:major": "node scripts/set-release-version.mjs --mode beta-major", "version:all:beta:major": "node scripts/set-release-version.mjs --mode beta-major",
"version:all:beta:next": "node scripts/set-release-version.mjs --mode beta-next", "version:all:beta:next": "node scripts/set-release-version.mjs --mode beta-next",
"version:all:promote": "node scripts/set-release-version.mjs --mode promote", "version:all:promote": "node scripts/set-release-version.mjs --mode promote",
"release:check": "npm run release:prepare && npm run typecheck --workspace=@getpaseo/highlight && npm run typecheck --workspace=@getpaseo/relay && npm run typecheck --workspace=@getpaseo/protocol && npm run build:client:clean && npm run typecheck --workspace=@getpaseo/client && npm run build:server:clean && npm run typecheck --workspace=@getpaseo/server && npm run typecheck --workspace=@getpaseo/cli && npm pack --dry-run --workspace=@getpaseo/highlight && npm pack --dry-run --workspace=@getpaseo/relay && npm pack --dry-run --workspace=@getpaseo/protocol && npm pack --dry-run --workspace=@getpaseo/client && npm pack --dry-run --workspace=@getpaseo/server && npm pack --dry-run --workspace=@getpaseo/cli", "release:check": "npm run release:prepare && npm run typecheck --workspace=@getpaseo/highlight && npm run typecheck --workspace=@getpaseo/relay && npm run typecheck --workspace=@getpaseo/protocol && npm run build:client:clean && npm run typecheck --workspace=@getpaseo/client && npm run typecheck --workspace=@getpaseo/plugin && npm run build:server:clean && npm run typecheck --workspace=@getpaseo/server && npm run typecheck --workspace=@getpaseo/cli && npm pack --dry-run --workspace=@getpaseo/highlight && npm pack --dry-run --workspace=@getpaseo/relay && npm pack --dry-run --workspace=@getpaseo/protocol && npm pack --dry-run --workspace=@getpaseo/client && npm pack --dry-run --workspace=@getpaseo/plugin && npm pack --dry-run --workspace=@getpaseo/server && npm pack --dry-run --workspace=@getpaseo/cli",
"release:publish:dry-run": "npm publish --dry-run --workspace=@getpaseo/highlight --access public && npm publish --dry-run --workspace=@getpaseo/relay --access public && npm publish --dry-run --workspace=@getpaseo/protocol --access public && npm publish --dry-run --workspace=@getpaseo/client --access public && npm publish --dry-run --workspace=@getpaseo/server --access public && npm publish --dry-run --workspace=@getpaseo/cli --access public", "release:publish:dry-run": "npm publish --dry-run --workspace=@getpaseo/highlight --access public && npm publish --dry-run --workspace=@getpaseo/relay --access public && npm publish --dry-run --workspace=@getpaseo/protocol --access public && npm publish --dry-run --workspace=@getpaseo/client --access public && npm publish --dry-run --workspace=@getpaseo/plugin --access public && npm publish --dry-run --workspace=@getpaseo/server --access public && npm publish --dry-run --workspace=@getpaseo/cli --access public",
"release:publish:beta:dry-run": "npm publish --dry-run --workspace=@getpaseo/highlight --access public --tag beta && npm publish --dry-run --workspace=@getpaseo/relay --access public --tag beta && npm publish --dry-run --workspace=@getpaseo/protocol --access public --tag beta && npm publish --dry-run --workspace=@getpaseo/client --access public --tag beta && npm publish --dry-run --workspace=@getpaseo/server --access public --tag beta && npm publish --dry-run --workspace=@getpaseo/cli --access public --tag beta", "release:publish:beta:dry-run": "npm publish --dry-run --workspace=@getpaseo/highlight --access public --tag beta && npm publish --dry-run --workspace=@getpaseo/relay --access public --tag beta && npm publish --dry-run --workspace=@getpaseo/protocol --access public --tag beta && npm publish --dry-run --workspace=@getpaseo/client --access public --tag beta && npm publish --dry-run --workspace=@getpaseo/plugin --access public --tag beta && npm publish --dry-run --workspace=@getpaseo/server --access public --tag beta && npm publish --dry-run --workspace=@getpaseo/cli --access public --tag beta",
"release:publish": "npm publish --workspace=@getpaseo/highlight --access public && npm publish --workspace=@getpaseo/relay --access public && npm publish --workspace=@getpaseo/protocol --access public && npm publish --workspace=@getpaseo/client --access public && npm publish --workspace=@getpaseo/server --access public && npm publish --workspace=@getpaseo/cli --access public", "release:publish": "npm publish --workspace=@getpaseo/highlight --access public && npm publish --workspace=@getpaseo/relay --access public && npm publish --workspace=@getpaseo/protocol --access public && npm publish --workspace=@getpaseo/client --access public && npm publish --workspace=@getpaseo/plugin --access public && npm publish --workspace=@getpaseo/server --access public && npm publish --workspace=@getpaseo/cli --access public",
"release:publish:beta": "npm publish --workspace=@getpaseo/highlight --access public --tag beta && npm publish --workspace=@getpaseo/relay --access public --tag beta && npm publish --workspace=@getpaseo/protocol --access public --tag beta && npm publish --workspace=@getpaseo/client --access public --tag beta && npm publish --workspace=@getpaseo/server --access public --tag beta && npm publish --workspace=@getpaseo/cli --access public --tag beta", "release:publish:beta": "npm publish --workspace=@getpaseo/highlight --access public --tag beta && npm publish --workspace=@getpaseo/relay --access public --tag beta && npm publish --workspace=@getpaseo/protocol --access public --tag beta && npm publish --workspace=@getpaseo/client --access public --tag beta && npm publish --workspace=@getpaseo/plugin --access public --tag beta && npm publish --workspace=@getpaseo/server --access public --tag beta && npm publish --workspace=@getpaseo/cli --access public --tag beta",
"release:push": "node scripts/push-current-release-tag.mjs", "release:push": "node scripts/push-current-release-tag.mjs",
"release:beta:patch": "npm run release:check && npm run version:all:beta:patch && npm run release:publish:beta && npm run release:push", "release:beta:patch": "npm run release:check && npm run version:all:beta:patch && npm run release:publish:beta && npm run release:push",
"release:beta:minor": "npm run release:check && npm run version:all:beta:minor && npm run release:publish:beta && npm run release:push", "release:beta:minor": "npm run release:check && npm run version:all:beta:minor && npm run release:publish:beta && npm run release:push",
@@ -31,7 +31,7 @@ function isSettledWorkspaceUrl(url: URL): boolean {
function pluginSource(): string { function pluginSource(): string {
return `import React, { useRef } from "react"; return `import React, { useRef } from "react";
import { Text, View } from "react-native"; import { Text, View } from "react-native";
import { useAgent, useWorkspace } from "@paseo/plugin"; import { useAgent, useWorkspace } from "@getpaseo/plugin";
function WorkspacePanel({ workspaceId, host, layout }) { function WorkspacePanel({ workspaceId, host, layout }) {
const workspace = useWorkspace(workspaceId, (value) => ({ id: value.id })); const workspace = useWorkspace(workspaceId, (value) => ({ id: value.id }));
+1 -1
View File
@@ -49,12 +49,12 @@
"@getpaseo/client": "*", "@getpaseo/client": "*",
"@getpaseo/expo-two-way-audio": "*", "@getpaseo/expo-two-way-audio": "*",
"@getpaseo/highlight": "*", "@getpaseo/highlight": "*",
"@getpaseo/plugin": "*",
"@getpaseo/protocol": "*", "@getpaseo/protocol": "*",
"@gorhom/bottom-sheet": "^5.2.14", "@gorhom/bottom-sheet": "^5.2.14",
"@gorhom/portal": "^1.0.14", "@gorhom/portal": "^1.0.14",
"@marijn/find-cluster-break": "^1.0.2", "@marijn/find-cluster-break": "^1.0.2",
"@mattermost/react-native-paste-input": "2.0.1", "@mattermost/react-native-paste-input": "2.0.1",
"@paseo/plugin": "*",
"@react-native-async-storage/async-storage": "2.2.0", "@react-native-async-storage/async-storage": "2.2.0",
"@react-native-masked-view/masked-view": "^0.3.2", "@react-native-masked-view/masked-view": "^0.3.2",
"@react-native/normalize-colors": "^0.81.5", "@react-native/normalize-colors": "^0.81.5",
@@ -1,6 +1,6 @@
import { z } from "zod"; import { z } from "zod";
import type { AgentAttachment } from "@getpaseo/protocol/messages"; import type { AgentAttachment } from "@getpaseo/protocol/messages";
import { PluginAttachmentItemSchema, type PluginAttachmentItem } from "@paseo/plugin"; import { PluginAttachmentItemSchema, type PluginAttachmentItem } from "@getpaseo/plugin";
import type { UserComposerAttachment } from "@/attachments/types"; import type { UserComposerAttachment } from "@/attachments/types";
export const PluginResourceComposerAttachmentSchema = z.object({ export const PluginResourceComposerAttachmentSchema = z.object({
@@ -2,8 +2,8 @@ import { useCallback, useMemo, useState, type ReactElement, type RefObject } fro
import { View } from "react-native"; import { View } from "react-native";
import { withUnistyles } from "react-native-unistyles"; import { withUnistyles } from "react-native-unistyles";
import type { DaemonClient } from "@getpaseo/client/internal/daemon-client"; import type { DaemonClient } from "@getpaseo/client/internal/daemon-client";
import type { PluginAttachmentItem, PluginAttachmentSourceContribution } from "@paseo/plugin"; import type { PluginAttachmentItem, PluginAttachmentSourceContribution } from "@getpaseo/plugin";
import { searchPluginAttachments } from "@paseo/plugin/host"; import { searchPluginAttachments } from "@getpaseo/plugin/host";
import type { LucideIcon } from "lucide-react-native"; import type { LucideIcon } from "lucide-react-native";
import type { UserComposerAttachment } from "@/attachments/types"; import type { UserComposerAttachment } from "@/attachments/types";
import type { AttachmentMenuItem } from "@/composer/input/input"; import type { AttachmentMenuItem } from "@/composer/input/input";
@@ -1,4 +1,4 @@
import type { PluginAgentSnapshot, PluginWorkspaceSnapshot } from "@paseo/plugin"; import type { PluginAgentSnapshot, PluginWorkspaceSnapshot } from "@getpaseo/plugin";
import type { Agent, WorkspaceDescriptor } from "@/stores/session-store"; import type { Agent, WorkspaceDescriptor } from "@/stores/session-store";
const workspaceSnapshots = new WeakMap<WorkspaceDescriptor, PluginWorkspaceSnapshot>(); const workspaceSnapshots = new WeakMap<WorkspaceDescriptor, PluginWorkspaceSnapshot>();
@@ -1,4 +1,4 @@
import type { PluginClientStateSource } from "@paseo/plugin/host"; import type { PluginClientStateSource } from "@getpaseo/plugin/host";
import { useSessionStore } from "@/stores/session-store"; import { useSessionStore } from "@/stores/session-store";
import { selectWorkspace } from "@/stores/session-store-hooks/selectors"; import { selectWorkspace } from "@/stores/session-store-hooks/selectors";
import { normalizeWorkspaceOpaqueId } from "@/utils/workspace-identity"; import { normalizeWorkspaceOpaqueId } from "@/utils/workspace-identity";
@@ -6,7 +6,7 @@ import {
type PluginAgentSnapshot, type PluginAgentSnapshot,
type PluginCommandCenterItemContribution, type PluginCommandCenterItemContribution,
type PluginWorkspaceSnapshot, type PluginWorkspaceSnapshot,
} from "@paseo/plugin"; } from "@getpaseo/plugin";
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import { z } from "zod"; import { z } from "zod";
import type { InstalledPlugin } from "../types"; import type { InstalledPlugin } from "../types";
@@ -1,6 +1,6 @@
import { callPluginRpc } from "@paseo/plugin/host"; import { callPluginRpc } from "@getpaseo/plugin/host";
import type { PluginCommandCapabilities } from "@paseo/plugin"; import type { PluginCommandCapabilities } from "@getpaseo/plugin";
import type { PluginClientStateSource } from "@paseo/plugin/host"; import type { PluginClientStateSource } from "@getpaseo/plugin/host";
import type { CommandCenterContribution } from "@/command-center/contributions"; import type { CommandCenterContribution } from "@/command-center/contributions";
import { getCommandCenterIcon } from "@/command-center/icon"; import { getCommandCenterIcon } from "@/command-center/icon";
import { resolvePluginIcon } from "../icons"; import { resolvePluginIcon } from "../icons";
+2 -2
View File
@@ -162,11 +162,11 @@ describe("evaluatePluginClientBundle", () => {
).toThrow("must return a cleanup function"); ).toThrow("must return a cleanup function");
}); });
it("resolves @paseo/plugin/server for shared RPC contracts", () => { it("resolves @getpaseo/plugin/server for shared RPC contracts", () => {
const plugin = evaluatePluginClientBundle( const plugin = evaluatePluginClientBundle(
"example", "example",
`(function(require) { `(function(require) {
const { defineRpc, defineAttachmentSource } = require("@paseo/plugin/server"); const { defineRpc, defineAttachmentSource } = require("@getpaseo/plugin/server");
const search = defineRpc({ name: "issues.search", input: {}, output: {} }); const search = defineRpc({ name: "issues.search", input: {}, output: {} });
const module = { exports: {} }; const module = { exports: {} };
module.exports.default = function(plugin) { module.exports.default = function(plugin) {
+4 -4
View File
@@ -17,8 +17,8 @@ import {
useAgent, useAgent,
useWorkspace, useWorkspace,
useRpc, useRpc,
} from "@paseo/plugin"; } from "@getpaseo/plugin";
import { createPluginContext, type PluginRegistrationCollector } from "@paseo/plugin/host"; import { createPluginContext, type PluginRegistrationCollector } from "@getpaseo/plugin/host";
import type { EvaluatedPlugin } from "./types"; import type { EvaluatedPlugin } from "./types";
import type { ComponentType } from "react"; import type { ComponentType } from "react";
import { resolvePluginIcon } from "./icons"; import { resolvePluginIcon } from "./icons";
@@ -149,7 +149,7 @@ export function evaluatePluginClientBundle(id: string, bundle: string): Evaluate
if (name === "react") return React; if (name === "react") return React;
if (name === "react/jsx-runtime") return ReactJsxRuntime; if (name === "react/jsx-runtime") return ReactJsxRuntime;
if (name === "react-native") return ReactNative; if (name === "react-native") return ReactNative;
if (name === "@paseo/plugin") { if (name === "@getpaseo/plugin") {
return { return {
defineAttachmentSource, defineAttachmentSource,
defineRpc, defineRpc,
@@ -159,7 +159,7 @@ export function evaluatePluginClientBundle(id: string, bundle: string): Evaluate
useRpc, useRpc,
}; };
} }
if (name === "@paseo/plugin/server") { if (name === "@getpaseo/plugin/server") {
return { defineAttachmentSource, defineRpc }; return { defineAttachmentSource, defineRpc };
} }
if (name === "@tanstack/react-query") return ReactQuery; if (name === "@tanstack/react-query") return ReactQuery;
@@ -1,5 +1,5 @@
import { QueryClientProvider } from "@tanstack/react-query"; import { QueryClientProvider } from "@tanstack/react-query";
import { PaseoApiProvider, PluginRpcProvider } from "@paseo/plugin/host"; import { PaseoApiProvider, PluginRpcProvider } from "@getpaseo/plugin/host";
import type { ReactNode } from "react"; import type { ReactNode } from "react";
import type { InstalledPlugin } from "./types"; import type { InstalledPlugin } from "./types";
import type { PluginSurfaceRuntime } from "./surface-runtime"; import type { PluginSurfaceRuntime } from "./surface-runtime";
@@ -1,7 +1,7 @@
import type { DaemonClient } from "@getpaseo/client/internal/daemon-client"; import type { DaemonClient } from "@getpaseo/client/internal/daemon-client";
import type { PaseoApi } from "@getpaseo/client"; import type { PaseoApi } from "@getpaseo/client";
import { PaseoApiProvider } from "@paseo/plugin/host"; import { PaseoApiProvider } from "@getpaseo/plugin/host";
import { usePaseo } from "@paseo/plugin"; import { usePaseo } from "@getpaseo/plugin";
import React from "react"; import React from "react";
import { renderToStaticMarkup } from "react-dom/server"; import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, it, vi } from "vitest"; import { describe, expect, it, vi } from "vitest";
+1 -1
View File
@@ -1,5 +1,5 @@
import { router, useLocalSearchParams } from "expo-router"; import { router, useLocalSearchParams } from "expo-router";
import type { PluginSurfaceProps, PluginTheme } from "@paseo/plugin"; import type { PluginSurfaceProps, PluginTheme } from "@getpaseo/plugin";
import { ChevronDown, X } from "lucide-react-native"; import { ChevronDown, X } from "lucide-react-native";
import { useCallback, useMemo, useRef, useState, type ComponentType } from "react"; import { useCallback, useMemo, useRef, useState, type ComponentType } from "react";
import { Platform, Pressable, Text, View } from "react-native"; import { Platform, Pressable, Text, View } from "react-native";
+1 -1
View File
@@ -1,4 +1,4 @@
import type { PluginTheme } from "@paseo/plugin"; import type { PluginTheme } from "@getpaseo/plugin";
import type { Theme } from "@/styles/theme"; import type { Theme } from "@/styles/theme";
export function toPluginTheme(theme: Theme): PluginTheme { export function toPluginTheme(theme: Theme): PluginTheme {
+1 -1
View File
@@ -5,7 +5,7 @@ import type {
PluginSidebarContribution, PluginSidebarContribution,
PluginSurfaceContribution, PluginSurfaceContribution,
PluginWorkspacePanelContribution, PluginWorkspacePanelContribution,
} from "@paseo/plugin"; } from "@getpaseo/plugin";
export interface EvaluatedPlugin { export interface EvaluatedPlugin {
id: string; id: string;
@@ -3,8 +3,8 @@ import type {
PluginHostProps, PluginHostProps,
PluginTheme, PluginTheme,
PluginWorkspacePanelProps, PluginWorkspacePanelProps,
} from "@paseo/plugin"; } from "@getpaseo/plugin";
import { PluginClientStateProvider } from "@paseo/plugin/host"; import { PluginClientStateProvider } from "@getpaseo/plugin/host";
import { CircleAlert } from "lucide-react-native"; import { CircleAlert } from "lucide-react-native";
import { useMemo } from "react"; import { useMemo } from "react";
import { Platform, Text, View } from "react-native"; import { Platform, Text, View } from "react-native";
@@ -1,4 +1,4 @@
import type { PluginWorkspacePanelContribution } from "@paseo/plugin"; import type { PluginWorkspacePanelContribution } from "@getpaseo/plugin";
import type { InstalledPlugin } from "../types"; import type { InstalledPlugin } from "../types";
import type { PluginWorkspaceTabTarget } from "@/workspace-tabs/model"; import type { PluginWorkspaceTabTarget } from "@/workspace-tabs/model";
@@ -50,7 +50,7 @@ describe("plugin scaffold", () => {
await Promise.all([ await Promise.all([
writeFile( writeFile(
path.join(directory, "inspect.shared.ts"), path.join(directory, "inspect.shared.ts"),
`import { defineRpc } from "@paseo/plugin/server"; `import { defineRpc } from "@getpaseo/plugin/server";
import { z } from "zod"; import { z } from "zod";
export const inspect = defineRpc({ export const inspect = defineRpc({
@@ -62,7 +62,7 @@ export const inspect = defineRpc({
), ),
writeFile( writeFile(
path.join(directory, "inspect.server.ts"), path.join(directory, "inspect.server.ts"),
`import type { PluginHandlerContext } from "@paseo/plugin/server"; `import type { PluginHandlerContext } from "@getpaseo/plugin/server";
import type { output as ZodOutput } from "zod"; import type { output as ZodOutput } from "zod";
import { inspect } from "./inspect.shared"; import { inspect } from "./inspect.shared";
@@ -83,7 +83,7 @@ import {
useAgent, useAgent,
usePaseo, usePaseo,
useWorkspace, useWorkspace,
} from "@paseo/plugin"; } from "@getpaseo/plugin";
export function Surface() { export function Surface() {
const paseo = usePaseo(); const paseo = usePaseo();
@@ -111,7 +111,7 @@ export function AgentPanel({ workspaceId, agentId }: PluginAgentPanelProps) {
), ),
writeFile( writeFile(
path.join(directory, "index.ts"), path.join(directory, "index.ts"),
`import type { PluginContext } from "@paseo/plugin"; `import type { PluginContext } from "@getpaseo/plugin";
import { AgentPanel, Surface } from "./main.client"; import { AgentPanel, Surface } from "./main.client";
import { inspectConfig } from "./inspect.server"; import { inspectConfig } from "./inspect.server";
import { inspect } from "./inspect.shared"; import { inspect } from "./inspect.shared";
+6 -6
View File
@@ -2,7 +2,7 @@ import { mkdir, readdir, writeFile } from "node:fs/promises";
import path from "node:path"; import path from "node:path";
import { PluginIdSchema } from "@getpaseo/protocol/messages"; import { PluginIdSchema } from "@getpaseo/protocol/messages";
const SDK_DECLARATIONS = `declare module "@paseo/plugin/server" { const SDK_DECLARATIONS = `declare module "@getpaseo/plugin/server" {
import type { PaseoApi } from "@getpaseo/client"; import type { PaseoApi } from "@getpaseo/client";
import type { ZodType, input as ZodInput, output as ZodOutput } from "zod"; import type { ZodType, input as ZodInput, output as ZodOutput } from "zod";
@@ -56,7 +56,7 @@ const SDK_DECLARATIONS = `declare module "@paseo/plugin/server" {
export const PluginAttachmentSearchPayloadSchema: import("zod").ZodType<PluginAttachmentSearchPayload>; export const PluginAttachmentSearchPayloadSchema: import("zod").ZodType<PluginAttachmentSearchPayload>;
} }
declare module "@paseo/plugin" { declare module "@getpaseo/plugin" {
import type { ComponentType } from "react"; import type { ComponentType } from "react";
import type { PaseoApi } from "@getpaseo/client"; import type { PaseoApi } from "@getpaseo/client";
import type { ZodType, input as ZodInput, output as ZodOutput } from "zod"; import type { ZodType, input as ZodInput, output as ZodOutput } from "zod";
@@ -64,7 +64,7 @@ declare module "@paseo/plugin" {
PluginAttachmentSourceContribution, PluginAttachmentSourceContribution,
PluginHandlerContext, PluginHandlerContext,
PluginRpcContract, PluginRpcContract,
} from "@paseo/plugin/server"; } from "@getpaseo/plugin/server";
export { export {
PluginAttachmentItemSchema, PluginAttachmentItemSchema,
@@ -76,7 +76,7 @@ declare module "@paseo/plugin" {
type PluginAttachmentSourceContribution, type PluginAttachmentSourceContribution,
type PluginHandlerContext, type PluginHandlerContext,
type PluginRpcContract, type PluginRpcContract,
} from "@paseo/plugin/server"; } from "@getpaseo/plugin/server";
export interface PluginTheme { export interface PluginTheme {
readonly colors: { readonly colors: {
@@ -242,7 +242,7 @@ const TSCONFIG = {
include: ["**/*.ts", "**/*.tsx"], include: ["**/*.ts", "**/*.tsx"],
}; };
const ENTRY = `import type { PluginContext } from "@paseo/plugin"; const ENTRY = `import type { PluginContext } from "@getpaseo/plugin";
import { MainSurface } from "./main.client"; import { MainSurface } from "./main.client";
export default function contribute(plugin: PluginContext) { export default function contribute(plugin: PluginContext) {
@@ -251,7 +251,7 @@ export default function contribute(plugin: PluginContext) {
} }
`; `;
const CLIENT_SURFACE = `import type { PluginSurfaceProps } from "@paseo/plugin"; const CLIENT_SURFACE = `import type { PluginSurfaceProps } from "@getpaseo/plugin";
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { Text, View } from "react-native"; import { Text, View } from "react-native";
+7 -4
View File
@@ -1,7 +1,7 @@
{ {
"name": "@paseo/plugin", "name": "@getpaseo/plugin",
"version": "0.5.0-beta.1", "version": "0.5.0-beta.1",
"private": true, "description": "Paseo plugin SDK package",
"files": [ "files": [
"dist", "dist",
"!dist/**/*.map" "!dist/**/*.map"
@@ -24,6 +24,9 @@
"default": "./dist/host.js" "default": "./dist/host.js"
} }
}, },
"publishConfig": {
"access": "public"
},
"scripts": { "scripts": {
"clean": "node ../../scripts/clean-package-dist.mjs", "clean": "node ../../scripts/clean-package-dist.mjs",
"build": "tsc -p tsconfig.json --incremental false", "build": "tsc -p tsconfig.json --incremental false",
@@ -36,7 +39,7 @@
"use-sync-external-store": "^1.6.0" "use-sync-external-store": "^1.6.0"
}, },
"devDependencies": { "devDependencies": {
"@getpaseo/client": "*", "@getpaseo/client": "0.5.0-beta.1",
"@types/node": "^20.9.0", "@types/node": "^20.9.0",
"@types/react": "~19.2.0", "@types/react": "~19.2.0",
"react": "19.1.0", "react": "19.1.0",
@@ -45,7 +48,7 @@
"zod": "^4.4.3" "zod": "^4.4.3"
}, },
"peerDependencies": { "peerDependencies": {
"@getpaseo/client": "*", "@getpaseo/client": "0.5.0-beta.1",
"react": "19.1.0", "react": "19.1.0",
"zod": "^4.4.3" "zod": "^4.4.3"
} }
+1 -1
View File
@@ -49,7 +49,7 @@ function collectBareSpecifiers(entry: string): string[] {
return bare; return bare;
} }
describe("@paseo/plugin/server", () => { describe("@getpaseo/plugin/server", () => {
it("does not load react or the client hook graph", () => { it("does not load react or the client hook graph", () => {
const specifiers = collectBareSpecifiers(path.join(srcDir, "server.ts")); const specifiers = collectBareSpecifiers(path.join(srcDir, "server.ts"));
expect(specifiers.filter((specifier) => forbiddenSpecifiers.has(specifier))).toEqual([]); expect(specifiers.filter((specifier) => forbiddenSpecifiers.has(specifier))).toEqual([]);
+1 -1
View File
@@ -74,12 +74,12 @@
"@babel/parser": "^7.29.8", "@babel/parser": "^7.29.8",
"@getpaseo/client": "0.5.0-beta.1", "@getpaseo/client": "0.5.0-beta.1",
"@getpaseo/highlight": "0.5.0-beta.1", "@getpaseo/highlight": "0.5.0-beta.1",
"@getpaseo/plugin": "0.5.0-beta.1",
"@getpaseo/protocol": "0.5.0-beta.1", "@getpaseo/protocol": "0.5.0-beta.1",
"@getpaseo/relay": "0.5.0-beta.1", "@getpaseo/relay": "0.5.0-beta.1",
"@isaacs/ttlcache": "^2.1.4", "@isaacs/ttlcache": "^2.1.4",
"@modelcontextprotocol/sdk": "^1.20.1", "@modelcontextprotocol/sdk": "^1.20.1",
"@opencode-ai/sdk": "1.14.46", "@opencode-ai/sdk": "1.14.46",
"@paseo/plugin": "*",
"@xterm/headless": "^6.0.0", "@xterm/headless": "^6.0.0",
"ai": "5.0.78", "ai": "5.0.78",
"ajv": "^8.20.0", "ajv": "^8.20.0",
@@ -73,14 +73,18 @@ afterEach(async () => {
}); });
describe("plugin author module externals", () => { describe("plugin author module externals", () => {
it("leaves @paseo/plugin/server external in both bundles", async () => { // COMPAT(plugin-sdk-scope): plugins written against the unpublished @paseo/plugin name must
const directory = await mkdtemp(path.join(tmpdir(), "paseo-plugin-compiler-")); // keep compiling. Drop that case with the specifiers in plugin-sdk-specifiers.ts.
temporaryDirectories.push(directory); it.each(["@getpaseo/plugin", "@paseo/plugin"])(
const entryPath = path.join(directory, "index.ts"); "leaves %s/server external in both bundles",
await writeFile( async (sdk) => {
entryPath, const directory = await mkdtemp(path.join(tmpdir(), "paseo-plugin-compiler-"));
`import type { PluginContext } from "@paseo/plugin"; temporaryDirectories.push(directory);
import { defineRpc } from "@paseo/plugin/server"; const entryPath = path.join(directory, "index.ts");
await writeFile(
entryPath,
`import type { PluginContext } from "${sdk}";
import { defineRpc } from "${sdk}/server";
import { z } from "zod"; import { z } from "zod";
const ping = defineRpc({ const ping = defineRpc({
@@ -94,12 +98,13 @@ export default function contribute(plugin: PluginContext) {
return () => undefined; return () => undefined;
} }
`, `,
); );
const { clientBundle, serverBundle } = await compilePlugin(entryPath); const { clientBundle, serverBundle } = await compilePlugin(entryPath);
expect(clientBundle).toContain("@paseo/plugin/server"); expect(clientBundle).toContain(`${sdk}/server`);
expect(serverBundle).toContain("@paseo/plugin/server"); expect(serverBundle).toContain(`${sdk}/server`);
expect(clientBundle).not.toContain("Invalid plugin RPC method"); expect(clientBundle).not.toContain("Invalid plugin RPC method");
expect(serverBundle).not.toContain("Invalid plugin RPC method"); expect(serverBundle).not.toContain("Invalid plugin RPC method");
}); },
);
}); });
@@ -4,6 +4,7 @@ import { createRequire } from "node:module";
import path from "node:path"; import path from "node:path";
import { parse } from "@babel/parser"; import { parse } from "@babel/parser";
import type { Plugin } from "esbuild"; import type { Plugin } from "esbuild";
import { PLUGIN_SDK_SPECIFIERS } from "./plugin-sdk-specifiers.js";
const nodeRequire = createRequire(import.meta.url); const nodeRequire = createRequire(import.meta.url);
const ESBUILD_BINARY_PATH = "ESBUILD_BINARY_PATH"; const ESBUILD_BINARY_PATH = "ESBUILD_BINARY_PATH";
@@ -307,15 +308,14 @@ async function compileTarget(entryPath: string, target: PluginBuildTarget): Prom
external: external:
target === "client" target === "client"
? [ ? [
"@paseo/plugin", ...PLUGIN_SDK_SPECIFIERS,
"@paseo/plugin/server",
"@tanstack/react-query", "@tanstack/react-query",
"react", "react",
"react/jsx-runtime", "react/jsx-runtime",
"react-native", "react-native",
"zod", "zod",
] ]
: ["@paseo/plugin", "@paseo/plugin/server", "zod"], : [...PLUGIN_SDK_SPECIFIERS, "zod"],
plugins: [createRuntimeBoundaryPlugin(target), createUnusedPlatformModulePlugin(target)], plugins: [createRuntimeBoundaryPlugin(target), createUnusedPlatformModulePlugin(target)],
logLevel: "silent", logLevel: "silent",
treeShaking: true, treeShaking: true,
@@ -21,7 +21,7 @@ test("plugin handlers create workspaces and agents through their Paseo API", asy
); );
await writeFile( await writeFile(
path.join(pluginDirectory, "index.tsx"), path.join(pluginDirectory, "index.tsx"),
`import { defineRpc, type PluginContext } from "@paseo/plugin"; `import { defineRpc, type PluginContext } from "@getpaseo/plugin";
import { z } from "zod"; import { z } from "zod";
const create = defineRpc({ const create = defineRpc({
@@ -5,10 +5,11 @@ import {
defineRpc, defineRpc,
type PluginHandlerContext, type PluginHandlerContext,
type PluginRpcContract, type PluginRpcContract,
} from "@paseo/plugin/server"; } from "@getpaseo/plugin/server";
import { createPaseoApi, type PaseoApi } from "@getpaseo/client"; import { createPaseoApi, type PaseoApi } from "@getpaseo/client";
import { DaemonClient } from "@getpaseo/client/internal/daemon-client"; import { DaemonClient } from "@getpaseo/client/internal/daemon-client";
import { createPluginDaemonTransportFactory } from "./daemon-transport.js"; import { createPluginDaemonTransportFactory } from "./daemon-transport.js";
import { isPluginSdkSpecifier } from "./plugin-sdk-specifiers.js";
type RpcHandler = (input: unknown, context: PluginHandlerContext) => unknown | Promise<unknown>; type RpcHandler = (input: unknown, context: PluginHandlerContext) => unknown | Promise<unknown>;
@@ -64,7 +65,7 @@ function register(contract: PluginRpcContract, handler: RpcHandler): void {
const pluginAuthorRuntime = { defineAttachmentSource, defineRpc }; const pluginAuthorRuntime = { defineAttachmentSource, defineRpc };
function runtimeRequire(name: string): unknown { function runtimeRequire(name: string): unknown {
if (name === "@paseo/plugin" || name === "@paseo/plugin/server") return pluginAuthorRuntime; if (isPluginSdkSpecifier(name)) return pluginAuthorRuntime;
return nodeRequire(name); return nodeRequire(name);
} }
@@ -0,0 +1,17 @@
// Specifiers a plugin author can import to reach the SDK. The daemon never resolves these
// from disk: the compiler marks them external and the plugin subprocess hands back its own
// runtime, so a plugin typechecks against generated declarations without installing anything.
//
// COMPAT(plugin-sdk-scope): @paseo/plugin was the SDK name through 0.5.0-beta.1 and was never
// published — that scope is not ours. Plugins scaffolded against that name still import it, so
// both spellings resolve. Remove the @paseo/* entries after 2026-11-19.
export const PLUGIN_SDK_SPECIFIERS = [
"@getpaseo/plugin",
"@getpaseo/plugin/server",
"@paseo/plugin",
"@paseo/plugin/server",
] as const;
export function isPluginSdkSpecifier(name: string): boolean {
return (PLUGIN_SDK_SPECIFIERS as readonly string[]).includes(name);
}
@@ -501,7 +501,7 @@ export default function contribute(plugin: unknown) {
import { platform } from "node:os"; import { platform } from "node:os";
import { Text } from "react-native"; import { Text } from "react-native";
import { z } from "zod"; import { z } from "zod";
import { defineAttachmentSource, defineRpc } from "@paseo/plugin"; import { defineAttachmentSource, defineRpc } from "@getpaseo/plugin";
const greetRpc = defineRpc({ const greetRpc = defineRpc({
name: "greet", name: "greet",
@@ -560,6 +560,34 @@ export default function contribute(plugin: any) {
await runtime.stopAll(); await runtime.stopAll();
}); });
// COMPAT(plugin-sdk-scope): plugins scaffolded through 0.5.0-beta.1 import the unpublished
// @paseo/plugin name. Drop with the specifiers in plugin-sdk-specifiers.ts.
it("loads a plugin that imports the pre-rename @paseo/plugin specifier", async () => {
const directory = await createPlugin(
"legacy-sdk",
`import { z } from "zod";
import { defineRpc } from "@paseo/plugin/server";
const pingRpc = defineRpc({
name: "ping",
input: z.object({}),
output: z.object({ ok: z.boolean() }),
});
export default function contribute(plugin: any) {
plugin.handle(pingRpc, async () => ({ ok: true }));
return () => undefined;
}`,
);
const runtime = createTestRuntime();
await runtime.startPlugin("legacy-sdk", directory);
await expect(runtime.invoke("legacy-sdk", "ping", {})).resolves.toMatchObject({ ok: true });
await runtime.stopAll();
});
it("keeps client and server modules in their target runtime", async () => { it("keeps client and server modules in their target runtime", async () => {
const directory = await mkdtemp(path.join(tmpdir(), "paseo-plugin-")); const directory = await mkdtemp(path.join(tmpdir(), "paseo-plugin-"));
temporaryDirectories.push(directory); temporaryDirectories.push(directory);
@@ -571,7 +599,7 @@ export default function contribute(plugin: any) {
), ),
writeFile( writeFile(
path.join(directory, "index.ts"), path.join(directory, "index.ts"),
`import type { PluginContext } from "@paseo/plugin"; `import type { PluginContext } from "@getpaseo/plugin";
import { Surface } from "./surface.client"; import { Surface } from "./surface.client";
import { inspectRpc } from "./inspect.shared"; import { inspectRpc } from "./inspect.shared";
import { inspectHost } from "./inspect.server"; import { inspectHost } from "./inspect.server";
@@ -597,7 +625,7 @@ export function Surface() {
), ),
writeFile( writeFile(
path.join(directory, "inspect.shared.ts"), path.join(directory, "inspect.shared.ts"),
`import { defineRpc } from "@paseo/plugin/server"; `import { defineRpc } from "@getpaseo/plugin/server";
import { z } from "zod"; import { z } from "zod";
export const inspectRpc = defineRpc({ export const inspectRpc = defineRpc({
@@ -643,7 +671,7 @@ export function inspectHost(_input: z.input<typeof inspectRpc.input>) {
), ),
writeFile( writeFile(
path.join(directory, "index.ts"), path.join(directory, "index.ts"),
`import type { PluginContext } from "@paseo/plugin"; `import type { PluginContext } from "@getpaseo/plugin";
import { Surface } from "./surface.client"; import { Surface } from "./surface.client";
export default function contribute(plugin: PluginContext) { export default function contribute(plugin: PluginContext) {
@@ -683,7 +711,7 @@ export function Surface() { return readSecret(); }`,
), ),
writeFile( writeFile(
path.join(directory, "index.ts"), path.join(directory, "index.ts"),
`import type { PluginContext } from "@paseo/plugin"; `import type { PluginContext } from "@getpaseo/plugin";
import { inspect } from "./inspect.server"; import { inspect } from "./inspect.server";
import { inspectRpc } from "./inspect.shared"; import { inspectRpc } from "./inspect.shared";
@@ -695,7 +723,7 @@ export default function contribute(plugin: PluginContext) {
), ),
writeFile( writeFile(
path.join(directory, "inspect.shared.ts"), path.join(directory, "inspect.shared.ts"),
`import { defineRpc } from "@paseo/plugin"; `import { defineRpc } from "@getpaseo/plugin";
import { z } from "zod"; import { z } from "zod";
export const inspectRpc = defineRpc({ export const inspectRpc = defineRpc({
name: "inspect", name: "inspect",
@@ -728,7 +756,7 @@ export function inspect() { void Surface; return {}; }`,
const directory = await createPlugin( const directory = await createPlugin(
"invalid-output", "invalid-output",
`import { z } from "zod"; `import { z } from "zod";
import { defineRpc } from "@paseo/plugin"; import { defineRpc } from "@getpaseo/plugin";
const brokenRpc = defineRpc({ const brokenRpc = defineRpc({
name: "broken", name: "broken",
input: z.object({}), input: z.object({}),
+1 -1
View File
@@ -1,4 +1,4 @@
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { searchIssues } from "./issues.server"; import { searchIssues } from "./issues.server";
import { issueAttachments, searchIssuesRpc } from "./issues.shared"; import { issueAttachments, searchIssuesRpc } from "./issues.shared";
+1 -1
View File
@@ -1,4 +1,4 @@
import type { PluginAttachmentSearchPayload } from "@paseo/plugin/server"; import type { PluginAttachmentSearchPayload } from "@getpaseo/plugin/server";
import type { output as ZodOutput } from "zod"; import type { output as ZodOutput } from "zod";
import { searchIssuesRpc } from "./issues.shared"; import { searchIssuesRpc } from "./issues.shared";
import { createLinearIssueSearch } from "./linear"; import { createLinearIssueSearch } from "./linear";
+1 -1
View File
@@ -1,4 +1,4 @@
import { defineAttachmentSource, defineRpc } from "@paseo/plugin/server"; import { defineAttachmentSource, defineRpc } from "@getpaseo/plugin/server";
import { z } from "zod"; import { z } from "zod";
const SearchPayloadSchema = z.object({ const SearchPayloadSchema = z.object({
@@ -1,4 +1,4 @@
import { defineRpc } from "@paseo/plugin/server"; import { defineRpc } from "@getpaseo/plugin/server";
import { z } from "zod"; import { z } from "zod";
export const incrementRpc = defineRpc({ export const incrementRpc = defineRpc({
+1 -1
View File
@@ -1,4 +1,4 @@
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { ExamplePanel } from "./main.client"; import { ExamplePanel } from "./main.client";
import { increment } from "./increment.server"; import { increment } from "./increment.server";
import { incrementRpc } from "./increment.shared"; import { incrementRpc } from "./increment.shared";
+1 -1
View File
@@ -1,5 +1,5 @@
import { useMutation } from "@tanstack/react-query"; import { useMutation } from "@tanstack/react-query";
import { type PluginWorkspacePanelProps, useRpc, useWorkspace } from "@paseo/plugin"; import { type PluginWorkspacePanelProps, useRpc, useWorkspace } from "@getpaseo/plugin";
import React, { useCallback, useMemo } from "react"; import React, { useCallback, useMemo } from "react";
import { Pressable, Text, View } from "react-native"; import { Pressable, Text, View } from "react-native";
import { incrementRpc } from "./increment.shared"; import { incrementRpc } from "./increment.shared";
+2 -2
View File
@@ -46,7 +46,7 @@ Plugins run on desktop, browser, iOS, and Android. Paseo ships several themes. C
Replace `main.client.tsx` with: Replace `main.client.tsx` with:
```tsx ```tsx
import { type PluginWorkspacePanelProps, useWorkspace } from "@paseo/plugin"; import { type PluginWorkspacePanelProps, useWorkspace } from "@getpaseo/plugin";
import { useMemo } from "react"; import { useMemo } from "react";
import { Text, View } from "react-native"; import { Text, View } from "react-native";
@@ -83,7 +83,7 @@ export function WorkspaceOverview({ theme, layout, workspaceId }: PluginWorkspac
Replace `index.ts` with: Replace `index.ts` with:
```ts ```ts
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { WorkspaceOverview } from "./main.client"; import { WorkspaceOverview } from "./main.client";
export default function contribute(plugin: PluginContext) { export default function contribute(plugin: PluginContext) {
+18 -18
View File
@@ -41,7 +41,7 @@ The manifest contains the default plugin ID:
Plugin, surface, sidebar-item, workspace-panel, Command Center item, and attachment-source IDs start with a lowercase letter and contain lowercase letters, numbers, or hyphens. Plugin, surface, sidebar-item, workspace-panel, Command Center item, and attachment-source IDs start with a lowercase letter and contain lowercase letters, numbers, or hyphens.
The generated declaration file supplies `@paseo/plugin` and `@paseo/plugin/server` types for local typechecking. Paseo supplies the runtime modules. Regenerate a fresh project with the matching CLI when the plugin contract changes. The generated declaration file supplies `@getpaseo/plugin` and `@getpaseo/plugin/server` types for local typechecking. Paseo supplies the runtime modules. Regenerate a fresh project with the matching CLI when the plugin contract changes.
Add runtime-specific files as the plugin grows: Add runtime-specific files as the plugin grows:
@@ -60,10 +60,10 @@ my-plugin/
## SDK modules ## SDK modules
| Module | Use it for | | Module | Use it for |
| ---------------------- | -------------------------------------------------------- | | ------------------------- | -------------------------------------------------------- |
| `@paseo/plugin` | hooks and UI types | | `@getpaseo/plugin` | hooks and UI types |
| `@paseo/plugin/server` | `defineRpc`, `defineAttachmentSource`, and handler types | | `@getpaseo/plugin/server` | `defineRpc`, `defineAttachmentSource`, and handler types |
Paseo rejects imports from `*.server` files into client modules and imports from `*.client` files into server modules. Keep shared modules free of Node and React Native runtime code. Paseo rejects imports from `*.server` files into client modules and imports from `*.client` files into server modules. Keep shared modules free of Node and React Native runtime code.
@@ -72,7 +72,7 @@ Paseo rejects imports from `*.server` files into client modules and imports from
`index.ts` wires contributions together and default-exports one contribution function. It must return cleanup, even when it has nothing to clean: `index.ts` wires contributions together and default-exports one contribution function. It must return cleanup, even when it has nothing to clean:
```ts ```ts
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { Main } from "./main.client"; import { Main } from "./main.client";
export default function contribute(plugin: PluginContext) { export default function contribute(plugin: PluginContext) {
@@ -90,7 +90,7 @@ Register a component, then point a sidebar item at its surface ID:
`main.client.tsx`: `main.client.tsx`:
```tsx ```tsx
import type { PluginSurfaceProps } from "@paseo/plugin"; import type { PluginSurfaceProps } from "@getpaseo/plugin";
import { useMemo } from "react"; import { useMemo } from "react";
import { Text, View } from "react-native"; import { Text, View } from "react-native";
@@ -119,7 +119,7 @@ export function Main({ theme, host, layout }: PluginSurfaceProps) {
`index.ts`: `index.ts`:
```ts ```ts
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { Main } from "./main.client"; import { Main } from "./main.client";
export default function contribute(plugin: PluginContext) { export default function contribute(plugin: PluginContext) {
@@ -162,7 +162,7 @@ Do not hardcode `#000`, `#fff`, or React Native's default text color. Primary co
Workspace and agent panels receive the same `theme` and `layout` fields. Workspace and agent panels receive the same `theme` and `layout` fields.
Client code can import `react`, `react-native`, `@tanstack/react-query`, `zod`, `@paseo/plugin`, and `@paseo/plugin/server`. Install them locally for typechecking; Paseo provides the client runtime instances. Client code can import `react`, `react-native`, `@tanstack/react-query`, `zod`, `@getpaseo/plugin`, and `@getpaseo/plugin/server`. Install them locally for typechecking; Paseo provides the client runtime instances.
## Workspace panels ## Workspace panels
@@ -171,7 +171,7 @@ Register one panel for workspace or agent context:
`review.client.tsx`: `review.client.tsx`:
```tsx ```tsx
import { type PluginAgentPanelProps, useAgent, useWorkspace } from "@paseo/plugin"; import { type PluginAgentPanelProps, useAgent, useWorkspace } from "@getpaseo/plugin";
import { useMemo } from "react"; import { useMemo } from "react";
import { Text, View } from "react-native"; import { Text, View } from "react-native";
@@ -202,7 +202,7 @@ export function ReviewPanel({ theme, layout, workspaceId, agentId }: PluginAgent
`index.ts`: `index.ts`:
```ts ```ts
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { ReviewPanel } from "./review.client"; import { ReviewPanel } from "./review.client";
export default function contribute(plugin: PluginContext) { export default function contribute(plugin: PluginContext) {
@@ -281,7 +281,7 @@ Open the Command Center with **⌘K** on macOS or **Ctrl+K** on Windows and Linu
Register an action and open a panel from the callback: Register an action and open a panel from the callback:
```tsx ```tsx
import { defineRpc } from "@paseo/plugin/server"; import { defineRpc } from "@getpaseo/plugin/server";
import { z } from "zod"; import { z } from "zod";
const refreshReview = defineRpc({ const refreshReview = defineRpc({
@@ -336,7 +336,7 @@ An agent callback may open either an agent panel or a workspace panel. A workspa
Use `usePaseo()` for ordinary Paseo operations from a surface. It borrows the selected host's existing connection; do not create another client. Use `usePaseo()` for ordinary Paseo operations from a surface. It borrows the selected host's existing connection; do not create another client.
```tsx ```tsx
import { usePaseo } from "@paseo/plugin"; import { usePaseo } from "@getpaseo/plugin";
import { Pressable, Text } from "react-native"; import { Pressable, Text } from "react-native";
function PullRequestAction() { function PullRequestAction() {
@@ -377,7 +377,7 @@ Define one contract with Zod, handle it in the subprocess, and call it from the
`greeting.shared.ts`: `greeting.shared.ts`:
```ts ```ts
import { defineRpc } from "@paseo/plugin/server"; import { defineRpc } from "@getpaseo/plugin/server";
import { z } from "zod"; import { z } from "zod";
export const greeting = defineRpc({ export const greeting = defineRpc({
@@ -390,7 +390,7 @@ export const greeting = defineRpc({
`greeting.client.tsx`: `greeting.client.tsx`:
```tsx ```tsx
import { useRpc } from "@paseo/plugin"; import { useRpc } from "@getpaseo/plugin";
import { greeting } from "./greeting.shared"; import { greeting } from "./greeting.shared";
export function GreetingButton() { export function GreetingButton() {
@@ -414,7 +414,7 @@ export function createGreeting({ name }: ZodOutput<typeof greeting.input>) {
`index.ts`: `index.ts`:
```ts ```ts
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { GreetingButton } from "./greeting.client"; import { GreetingButton } from "./greeting.client";
import { createGreeting } from "./greeting.server"; import { createGreeting } from "./greeting.server";
import { greeting } from "./greeting.shared"; import { greeting } from "./greeting.shared";
@@ -474,7 +474,7 @@ An attachment source searches external resources and returns a stable text snaps
`issues.shared.ts`: `issues.shared.ts`:
```ts ```ts
import { defineAttachmentSource, defineRpc } from "@paseo/plugin/server"; import { defineAttachmentSource, defineRpc } from "@getpaseo/plugin/server";
import { z } from "zod"; import { z } from "zod";
export const searchIssues = defineRpc({ export const searchIssues = defineRpc({
@@ -519,7 +519,7 @@ export function search({ query }: ZodOutput<typeof searchIssues.input>) {
`index.ts`: `index.ts`:
```ts ```ts
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { search } from "./issues.server"; import { search } from "./issues.server";
import { issues, searchIssues } from "./issues.shared"; import { issues, searchIssues } from "./issues.shared";
+14 -14
View File
@@ -50,7 +50,7 @@ The manifest supplies the default install ID:
Default-export one contribution function. It must return cleanup, even when there is nothing to clean: Default-export one contribution function. It must return cleanup, even when there is nothing to clean:
```tsx ```tsx
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
export default function contribute(plugin: PluginContext) { export default function contribute(plugin: PluginContext) {
// Register contributions here. // Register contributions here.
@@ -67,7 +67,7 @@ mobile, and Paseo has multiple themes. Every `Text` must take its color from `th
Use `layout.compact` for padding and stacking. Unstyled text is black and fails in dark themes. Use `layout.compact` for padding and stacking. Unstyled text is black and fails in dark themes.
```tsx ```tsx
import { type PluginContext, type PluginWorkspacePanelProps, useWorkspace } from "@paseo/plugin"; import { type PluginContext, type PluginWorkspacePanelProps, useWorkspace } from "@getpaseo/plugin";
import { useMemo } from "react"; import { useMemo } from "react";
import { Text, View } from "react-native"; import { Text, View } from "react-native";
@@ -123,7 +123,7 @@ the active workspace or agent. Command callbacks receive the selected host's `pa
Plugin surfaces use React Native primitives and work across desktop, browser, iOS, and Android. Register the surface before its sidebar item. Color text from `theme.colors` and pad from `layout.compact`. Plugin surfaces use React Native primitives and work across desktop, browser, iOS, and Android. Register the surface before its sidebar item. Color text from `theme.colors` and pad from `layout.compact`.
```tsx ```tsx
import type { PluginContext, PluginSurfaceProps } from "@paseo/plugin"; import type { PluginContext, PluginSurfaceProps } from "@getpaseo/plugin";
import React, { useMemo, useState } from "react"; import React, { useMemo, useState } from "react";
import { Pressable, Text, View } from "react-native"; import { Pressable, Text, View } from "react-native";
@@ -172,12 +172,12 @@ export default function contribute(plugin: PluginContext) {
Icons are Lucide icon names. `theme` is a typed `PluginTheme` on every surface and panel. Primary text uses `theme.colors.foreground`; labels use `theme.colors.foregroundMuted`; the root view uses `theme.colors.surface0`. `layout.compact` is true on mobile and narrow windows. Paseo owns the route, header, host picker, close action, error boundary, and per-installation query client. Icons are Lucide icon names. `theme` is a typed `PluginTheme` on every surface and panel. Primary text uses `theme.colors.foreground`; labels use `theme.colors.foregroundMuted`; the root view uses `theme.colors.surface0`. `layout.compact` is true on mobile and narrow windows. Paseo owns the route, header, host picker, close action, error boundary, and per-installation query client.
Client code may import `react`, `react-native`, `@tanstack/react-query`, `zod`, `@paseo/plugin`, and `@paseo/plugin/server`. Install dependencies locally for typechecking; Paseo supplies these runtime modules. Client code may import `react`, `react-native`, `@tanstack/react-query`, `zod`, `@getpaseo/plugin`, and `@getpaseo/plugin/server`. Install dependencies locally for typechecking; Paseo supplies these runtime modules.
| Module | Use it for | | Module | Use it for |
| ---------------------- | ---------------------------------------------------- | | ------------------------- | ---------------------------------------------------- |
| `@paseo/plugin` | hooks and UI types | | `@getpaseo/plugin` | hooks and UI types |
| `@paseo/plugin/server` | `defineRpc`, `defineAttachmentSource`, handler types | | `@getpaseo/plugin/server` | `defineRpc`, `defineAttachmentSource`, handler types |
## Choose the correct API ## Choose the correct API
@@ -188,7 +188,7 @@ Use the existing Paseo SDK for normal Paseo operations. Use plugin RPC only for
`usePaseo()` borrows the selected host's current connection. Never create another client inside a surface. `usePaseo()` borrows the selected host's current connection. Never create another client inside a surface.
```tsx ```tsx
import { usePaseo } from "@paseo/plugin"; import { usePaseo } from "@getpaseo/plugin";
function PullRequestAction() { function PullRequestAction() {
const paseo = usePaseo(); const paseo = usePaseo();
@@ -221,9 +221,9 @@ The API covers workspaces, agents, providers, and daemon config. It omits connec
Define one Zod contract, register its subprocess handler, and call it with `useRpc()`: Define one Zod contract, register its subprocess handler, and call it with `useRpc()`:
```tsx ```tsx
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { useRpc } from "@paseo/plugin"; import { useRpc } from "@getpaseo/plugin";
import { defineRpc } from "@paseo/plugin/server"; import { defineRpc } from "@getpaseo/plugin/server";
import { z } from "zod"; import { z } from "zod";
const greeting = defineRpc({ const greeting = defineRpc({
@@ -275,8 +275,8 @@ daemon log. Never log credentials or other secrets.
Define a search RPC and register a declarative source: Define a search RPC and register a declarative source:
```tsx ```tsx
import type { PluginContext } from "@paseo/plugin"; import type { PluginContext } from "@getpaseo/plugin";
import { defineAttachmentSource, defineRpc } from "@paseo/plugin/server"; import { defineAttachmentSource, defineRpc } from "@getpaseo/plugin/server";
import { z } from "zod"; import { z } from "zod";
const searchIssues = defineRpc({ const searchIssues = defineRpc({