From 929d2b717e3560ccdd1f02b56ce63a9fce5e937c Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Wed, 19 Aug 2026 14:44:29 +0200 Subject: [PATCH] fix(plugins): publish the plugin SDK under the @getpaseo scope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- docker/base/Dockerfile | 2 +- docs/plugins.md | 18 ++-- docs/release.md | 2 +- package-lock.json | 94 +++++++------------ package.json | 14 +-- .../browser/plugin-workspace-panels.spec.ts | 2 +- packages/app/package.json | 2 +- packages/app/src/plugins/attachments/model.ts | 2 +- .../app/src/plugins/attachments/picker.tsx | 4 +- .../app/src/plugins/client-state/snapshots.ts | 2 +- .../app/src/plugins/client-state/source.ts | 2 +- .../command-center/contributions.test.ts | 2 +- .../plugins/command-center/contributions.ts | 6 +- packages/app/src/plugins/evaluate.test.ts | 4 +- packages/app/src/plugins/evaluate.ts | 8 +- packages/app/src/plugins/runtime-boundary.tsx | 2 +- .../app/src/plugins/surface-runtime.test.tsx | 4 +- packages/app/src/plugins/surface-screen.tsx | 2 +- packages/app/src/plugins/theme.ts | 2 +- packages/app/src/plugins/types.ts | 2 +- .../src/plugins/workspace-panels/panel.tsx | 4 +- .../plugins/workspace-panels/resolution.ts | 2 +- .../cli/src/commands/plugin/scaffold.test.ts | 8 +- packages/cli/src/commands/plugin/scaffold.ts | 12 +-- packages/plugin/package.json | 11 ++- packages/plugin/src/server.test.ts | 2 +- packages/server/package.json | 2 +- .../src/server/plugins/compiler.test.ts | 35 ++++--- .../server/src/server/plugins/compiler.ts | 6 +- .../plugins/plugin-paseo-api.e2e.test.ts | 2 +- .../src/server/plugins/plugin-process.ts | 5 +- .../server/plugins/plugin-sdk-specifiers.ts | 17 ++++ .../src/server/plugins/runtime.posix.test.ts | 42 +++++++-- plugin-examples/linear/index.ts | 2 +- plugin-examples/linear/issues.server.ts | 2 +- plugin-examples/linear/issues.shared.ts | 2 +- .../local-plugin/increment.shared.ts | 2 +- plugin-examples/local-plugin/index.ts | 2 +- plugin-examples/local-plugin/main.client.tsx | 2 +- public-docs/plugins/index.md | 4 +- public-docs/plugins/reference.md | 36 +++---- skills/paseo-plugin/SKILL.md | 28 +++--- 42 files changed, 216 insertions(+), 188 deletions(-) create mode 100644 packages/server/src/server/plugins/plugin-sdk-specifiers.ts diff --git a/docker/base/Dockerfile b/docker/base/Dockerfile index cd2591ed49..378ec7118a 100644 --- a/docker/base/Dockerfile +++ b/docker/base/Dockerfile @@ -23,7 +23,7 @@ RUN set -eux; \ npm pack --workspace=@getpaseo/relay --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=@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/cli --pack-destination /tmp/paseo-packs diff --git a/docs/plugins.md b/docs/plugins.md index 6350baddad..a4743c0f29 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -53,7 +53,7 @@ my-plugin/ ``` 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 contract changes. @@ -96,15 +96,15 @@ code lives behind filename boundaries: | `*.server.ts` | Node APIs, filesystem and process access, credentials, and handlers. | | `*.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 -`@paseo/plugin`. Plugin UI runs on desktop and mobile across multiple themes: color every +Shared files import contracts from `@getpaseo/plugin/server`. Client files import hooks from +`@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 `layout.compact`. See `public-docs/plugins/reference.md`. -| Module | Use it for | -| ---------------------- | -------------------------------------------------------- | -| `@paseo/plugin` | hooks and UI types | -| `@paseo/plugin/server` | `defineRpc`, `defineAttachmentSource`, and handler types | +| Module | Use it for | +| ------------------------- | -------------------------------------------------------- | +| `@getpaseo/plugin` | hooks and UI types | +| `@getpaseo/plugin/server` | `defineRpc`, `defineAttachmentSource`, and handler types | 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 @@ -113,7 +113,7 @@ such as `StyleSheet.create` belong in `*.client.tsx`; placing them in `index.ts` server bundle. ```ts -import type { PluginContext } from "@paseo/plugin"; +import type { PluginContext } from "@getpaseo/plugin"; import { Greeting } from "./greeting.client"; import { createGreeting } from "./greeting.server"; 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. ```ts -import type { PluginContext } from "@paseo/plugin"; +import type { PluginContext } from "@getpaseo/plugin"; import { search } from "./issues.server"; import { issues, searchIssues } from "./issues.shared"; diff --git a/docs/release.md b/docs/release.md index 1556de9493..eef4fdbcf4 100644 --- a/docs/release.md +++ b/docs/release.md @@ -120,7 +120,7 @@ republish the packages: ```bash 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 done ``` diff --git a/package-lock.json b/package-lock.json index 15f7bd2dff..6b51b32aa5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6247,6 +6247,10 @@ "resolved": "packages/highlight", "link": true }, + "node_modules/@getpaseo/plugin": { + "resolved": "packages/plugin", + "link": true + }, "node_modules/@getpaseo/protocol": { "resolved": "packages/protocol", "link": true @@ -9556,10 +9560,6 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@paseo/plugin": { - "resolved": "packages/plugin", - "link": true - }, "node_modules/@pinojs/redact": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", @@ -11181,8 +11181,7 @@ "optional": true, "os": [ "android" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-android-arm64": { "version": "4.59.0", @@ -11195,8 +11194,7 @@ "optional": true, "os": [ "android" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.59.0", @@ -11209,8 +11207,7 @@ "optional": true, "os": [ "darwin" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-darwin-x64": { "version": "4.59.0", @@ -11223,8 +11220,7 @@ "optional": true, "os": [ "darwin" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-freebsd-arm64": { "version": "4.59.0", @@ -11237,8 +11233,7 @@ "optional": true, "os": [ "freebsd" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-freebsd-x64": { "version": "4.59.0", @@ -11251,8 +11246,7 @@ "optional": true, "os": [ "freebsd" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { "version": "4.59.0", @@ -11265,8 +11259,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { "version": "4.59.0", @@ -11279,8 +11272,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { "version": "4.59.0", @@ -11293,8 +11285,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { "version": "4.59.0", @@ -11307,8 +11298,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { "version": "4.59.0", @@ -11321,8 +11311,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { "version": "4.59.0", @@ -11335,8 +11324,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { "version": "4.59.0", @@ -11349,8 +11337,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { "version": "4.59.0", @@ -11363,8 +11350,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { "version": "4.59.0", @@ -11377,8 +11363,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { "version": "4.59.0", @@ -11391,8 +11376,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { "version": "4.59.0", @@ -11405,8 +11389,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.59.0", @@ -11419,8 +11402,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-linux-x64-musl": { "version": "4.59.0", @@ -11433,8 +11415,7 @@ "optional": true, "os": [ "linux" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-openbsd-x64": { "version": "4.59.0", @@ -11447,8 +11428,7 @@ "optional": true, "os": [ "openbsd" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-openharmony-arm64": { "version": "4.59.0", @@ -11461,8 +11441,7 @@ "optional": true, "os": [ "openharmony" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { "version": "4.59.0", @@ -11475,8 +11454,7 @@ "optional": true, "os": [ "win32" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { "version": "4.59.0", @@ -11489,8 +11467,7 @@ "optional": true, "os": [ "win32" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { "version": "4.59.0", @@ -11503,8 +11480,7 @@ "optional": true, "os": [ "win32" - ], - "peer": true + ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { "version": "4.59.0", @@ -11517,8 +11493,7 @@ "optional": true, "os": [ "win32" - ], - "peer": true + ] }, "node_modules/@rtsao/scc": { "version": "1.1.0", @@ -19112,7 +19087,6 @@ "dev": true, "license": "BSD-3-Clause", "optional": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -36154,12 +36128,12 @@ "@getpaseo/client": "*", "@getpaseo/expo-two-way-audio": "*", "@getpaseo/highlight": "*", + "@getpaseo/plugin": "*", "@getpaseo/protocol": "*", "@gorhom/bottom-sheet": "^5.2.14", "@gorhom/portal": "^1.0.14", "@marijn/find-cluster-break": "^1.0.2", "@mattermost/react-native-paste-input": "2.0.1", - "@paseo/plugin": "*", "@react-native-async-storage/async-storage": "2.2.0", "@react-native-masked-view/masked-view": "^0.3.2", "@react-native/normalize-colors": "^0.81.5", @@ -38625,13 +38599,13 @@ } }, "packages/plugin": { - "name": "@paseo/plugin", + "name": "@getpaseo/plugin", "version": "0.5.0-beta.1", "dependencies": { "use-sync-external-store": "^1.6.0" }, "devDependencies": { - "@getpaseo/client": "*", + "@getpaseo/client": "0.5.0-beta.1", "@types/node": "^20.9.0", "@types/react": "~19.2.0", "react": "19.1.0", @@ -38640,7 +38614,7 @@ "zod": "^4.4.3" }, "peerDependencies": { - "@getpaseo/client": "*", + "@getpaseo/client": "0.5.0-beta.1", "react": "19.1.0", "zod": "^4.4.3" } @@ -38886,12 +38860,12 @@ "@babel/parser": "^7.29.8", "@getpaseo/client": "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/relay": "0.5.0-beta.1", "@isaacs/ttlcache": "^2.1.4", "@modelcontextprotocol/sdk": "^1.20.1", "@opencode-ai/sdk": "1.14.46", - "@paseo/plugin": "*", "@xterm/headless": "^6.0.0", "ai": "5.0.78", "ajv": "^8.20.0", diff --git a/package.json b/package.json index 606be52492..08d8a0936a 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,8 @@ "build": "npm run build --workspaces --if-present", "build:highlight": "npm run build --workspace=@getpaseo/highlight", "build:highlight:clean": "npm run build:clean --workspace=@getpaseo/highlight", - "build:plugin": "npm run build --workspace=@paseo/plugin", - "build:plugin:clean": "npm run build:clean --workspace=@paseo/plugin", + "build:plugin": "npm run build --workspace=@getpaseo/plugin", + "build:plugin:clean": "npm run build:clean --workspace=@getpaseo/plugin", "build:relay": "npm run build --workspace=@getpaseo/relay", "build:relay:clean": "npm run build:clean --workspace=@getpaseo/relay", "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:next": "node scripts/set-release-version.mjs --mode beta-next", "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: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: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": "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: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: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/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/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/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/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: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", diff --git a/packages/app/e2e/browser/plugin-workspace-panels.spec.ts b/packages/app/e2e/browser/plugin-workspace-panels.spec.ts index 708076d222..b320e7e5bf 100644 --- a/packages/app/e2e/browser/plugin-workspace-panels.spec.ts +++ b/packages/app/e2e/browser/plugin-workspace-panels.spec.ts @@ -31,7 +31,7 @@ function isSettledWorkspaceUrl(url: URL): boolean { function pluginSource(): string { return `import React, { useRef } from "react"; import { Text, View } from "react-native"; -import { useAgent, useWorkspace } from "@paseo/plugin"; +import { useAgent, useWorkspace } from "@getpaseo/plugin"; function WorkspacePanel({ workspaceId, host, layout }) { const workspace = useWorkspace(workspaceId, (value) => ({ id: value.id })); diff --git a/packages/app/package.json b/packages/app/package.json index def691ad3c..e50a4815f1 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -49,12 +49,12 @@ "@getpaseo/client": "*", "@getpaseo/expo-two-way-audio": "*", "@getpaseo/highlight": "*", + "@getpaseo/plugin": "*", "@getpaseo/protocol": "*", "@gorhom/bottom-sheet": "^5.2.14", "@gorhom/portal": "^1.0.14", "@marijn/find-cluster-break": "^1.0.2", "@mattermost/react-native-paste-input": "2.0.1", - "@paseo/plugin": "*", "@react-native-async-storage/async-storage": "2.2.0", "@react-native-masked-view/masked-view": "^0.3.2", "@react-native/normalize-colors": "^0.81.5", diff --git a/packages/app/src/plugins/attachments/model.ts b/packages/app/src/plugins/attachments/model.ts index c9b2a34d48..29798b2d31 100644 --- a/packages/app/src/plugins/attachments/model.ts +++ b/packages/app/src/plugins/attachments/model.ts @@ -1,6 +1,6 @@ import { z } from "zod"; 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"; export const PluginResourceComposerAttachmentSchema = z.object({ diff --git a/packages/app/src/plugins/attachments/picker.tsx b/packages/app/src/plugins/attachments/picker.tsx index 7ccbb79da3..f25d5c4d20 100644 --- a/packages/app/src/plugins/attachments/picker.tsx +++ b/packages/app/src/plugins/attachments/picker.tsx @@ -2,8 +2,8 @@ import { useCallback, useMemo, useState, type ReactElement, type RefObject } fro import { View } from "react-native"; import { withUnistyles } from "react-native-unistyles"; import type { DaemonClient } from "@getpaseo/client/internal/daemon-client"; -import type { PluginAttachmentItem, PluginAttachmentSourceContribution } from "@paseo/plugin"; -import { searchPluginAttachments } from "@paseo/plugin/host"; +import type { PluginAttachmentItem, PluginAttachmentSourceContribution } from "@getpaseo/plugin"; +import { searchPluginAttachments } from "@getpaseo/plugin/host"; import type { LucideIcon } from "lucide-react-native"; import type { UserComposerAttachment } from "@/attachments/types"; import type { AttachmentMenuItem } from "@/composer/input/input"; diff --git a/packages/app/src/plugins/client-state/snapshots.ts b/packages/app/src/plugins/client-state/snapshots.ts index 30d0767fda..67a08830cd 100644 --- a/packages/app/src/plugins/client-state/snapshots.ts +++ b/packages/app/src/plugins/client-state/snapshots.ts @@ -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"; const workspaceSnapshots = new WeakMap(); diff --git a/packages/app/src/plugins/client-state/source.ts b/packages/app/src/plugins/client-state/source.ts index 652ae90d44..d7aaee597e 100644 --- a/packages/app/src/plugins/client-state/source.ts +++ b/packages/app/src/plugins/client-state/source.ts @@ -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 { selectWorkspace } from "@/stores/session-store-hooks/selectors"; import { normalizeWorkspaceOpaqueId } from "@/utils/workspace-identity"; diff --git a/packages/app/src/plugins/command-center/contributions.test.ts b/packages/app/src/plugins/command-center/contributions.test.ts index 488144e7ab..44ba334947 100644 --- a/packages/app/src/plugins/command-center/contributions.test.ts +++ b/packages/app/src/plugins/command-center/contributions.test.ts @@ -6,7 +6,7 @@ import { type PluginAgentSnapshot, type PluginCommandCenterItemContribution, type PluginWorkspaceSnapshot, -} from "@paseo/plugin"; +} from "@getpaseo/plugin"; import { describe, expect, it } from "vitest"; import { z } from "zod"; import type { InstalledPlugin } from "../types"; diff --git a/packages/app/src/plugins/command-center/contributions.ts b/packages/app/src/plugins/command-center/contributions.ts index 0a3d72465d..7852164681 100644 --- a/packages/app/src/plugins/command-center/contributions.ts +++ b/packages/app/src/plugins/command-center/contributions.ts @@ -1,6 +1,6 @@ -import { callPluginRpc } from "@paseo/plugin/host"; -import type { PluginCommandCapabilities } from "@paseo/plugin"; -import type { PluginClientStateSource } from "@paseo/plugin/host"; +import { callPluginRpc } from "@getpaseo/plugin/host"; +import type { PluginCommandCapabilities } from "@getpaseo/plugin"; +import type { PluginClientStateSource } from "@getpaseo/plugin/host"; import type { CommandCenterContribution } from "@/command-center/contributions"; import { getCommandCenterIcon } from "@/command-center/icon"; import { resolvePluginIcon } from "../icons"; diff --git a/packages/app/src/plugins/evaluate.test.ts b/packages/app/src/plugins/evaluate.test.ts index 27288508b8..0fb47d98f7 100644 --- a/packages/app/src/plugins/evaluate.test.ts +++ b/packages/app/src/plugins/evaluate.test.ts @@ -162,11 +162,11 @@ describe("evaluatePluginClientBundle", () => { ).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( "example", `(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 module = { exports: {} }; module.exports.default = function(plugin) { diff --git a/packages/app/src/plugins/evaluate.ts b/packages/app/src/plugins/evaluate.ts index 73ac933839..675614c31b 100644 --- a/packages/app/src/plugins/evaluate.ts +++ b/packages/app/src/plugins/evaluate.ts @@ -17,8 +17,8 @@ import { useAgent, useWorkspace, useRpc, -} from "@paseo/plugin"; -import { createPluginContext, type PluginRegistrationCollector } from "@paseo/plugin/host"; +} from "@getpaseo/plugin"; +import { createPluginContext, type PluginRegistrationCollector } from "@getpaseo/plugin/host"; import type { EvaluatedPlugin } from "./types"; import type { ComponentType } from "react"; import { resolvePluginIcon } from "./icons"; @@ -149,7 +149,7 @@ export function evaluatePluginClientBundle(id: string, bundle: string): Evaluate if (name === "react") return React; if (name === "react/jsx-runtime") return ReactJsxRuntime; if (name === "react-native") return ReactNative; - if (name === "@paseo/plugin") { + if (name === "@getpaseo/plugin") { return { defineAttachmentSource, defineRpc, @@ -159,7 +159,7 @@ export function evaluatePluginClientBundle(id: string, bundle: string): Evaluate useRpc, }; } - if (name === "@paseo/plugin/server") { + if (name === "@getpaseo/plugin/server") { return { defineAttachmentSource, defineRpc }; } if (name === "@tanstack/react-query") return ReactQuery; diff --git a/packages/app/src/plugins/runtime-boundary.tsx b/packages/app/src/plugins/runtime-boundary.tsx index 9d7e0a7821..7f2d62c054 100644 --- a/packages/app/src/plugins/runtime-boundary.tsx +++ b/packages/app/src/plugins/runtime-boundary.tsx @@ -1,5 +1,5 @@ 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 { InstalledPlugin } from "./types"; import type { PluginSurfaceRuntime } from "./surface-runtime"; diff --git a/packages/app/src/plugins/surface-runtime.test.tsx b/packages/app/src/plugins/surface-runtime.test.tsx index 83ee59a251..ec3ad2d4d1 100644 --- a/packages/app/src/plugins/surface-runtime.test.tsx +++ b/packages/app/src/plugins/surface-runtime.test.tsx @@ -1,7 +1,7 @@ import type { DaemonClient } from "@getpaseo/client/internal/daemon-client"; import type { PaseoApi } from "@getpaseo/client"; -import { PaseoApiProvider } from "@paseo/plugin/host"; -import { usePaseo } from "@paseo/plugin"; +import { PaseoApiProvider } from "@getpaseo/plugin/host"; +import { usePaseo } from "@getpaseo/plugin"; import React from "react"; import { renderToStaticMarkup } from "react-dom/server"; import { describe, expect, it, vi } from "vitest"; diff --git a/packages/app/src/plugins/surface-screen.tsx b/packages/app/src/plugins/surface-screen.tsx index 0ea1597a0d..9c235e544e 100644 --- a/packages/app/src/plugins/surface-screen.tsx +++ b/packages/app/src/plugins/surface-screen.tsx @@ -1,5 +1,5 @@ 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 { useCallback, useMemo, useRef, useState, type ComponentType } from "react"; import { Platform, Pressable, Text, View } from "react-native"; diff --git a/packages/app/src/plugins/theme.ts b/packages/app/src/plugins/theme.ts index c006b85c9a..5f456700f1 100644 --- a/packages/app/src/plugins/theme.ts +++ b/packages/app/src/plugins/theme.ts @@ -1,4 +1,4 @@ -import type { PluginTheme } from "@paseo/plugin"; +import type { PluginTheme } from "@getpaseo/plugin"; import type { Theme } from "@/styles/theme"; export function toPluginTheme(theme: Theme): PluginTheme { diff --git a/packages/app/src/plugins/types.ts b/packages/app/src/plugins/types.ts index 773a8d3a9f..f28145aafb 100644 --- a/packages/app/src/plugins/types.ts +++ b/packages/app/src/plugins/types.ts @@ -5,7 +5,7 @@ import type { PluginSidebarContribution, PluginSurfaceContribution, PluginWorkspacePanelContribution, -} from "@paseo/plugin"; +} from "@getpaseo/plugin"; export interface EvaluatedPlugin { id: string; diff --git a/packages/app/src/plugins/workspace-panels/panel.tsx b/packages/app/src/plugins/workspace-panels/panel.tsx index 830bd0feef..067cfb6063 100644 --- a/packages/app/src/plugins/workspace-panels/panel.tsx +++ b/packages/app/src/plugins/workspace-panels/panel.tsx @@ -3,8 +3,8 @@ import type { PluginHostProps, PluginTheme, PluginWorkspacePanelProps, -} from "@paseo/plugin"; -import { PluginClientStateProvider } from "@paseo/plugin/host"; +} from "@getpaseo/plugin"; +import { PluginClientStateProvider } from "@getpaseo/plugin/host"; import { CircleAlert } from "lucide-react-native"; import { useMemo } from "react"; import { Platform, Text, View } from "react-native"; diff --git a/packages/app/src/plugins/workspace-panels/resolution.ts b/packages/app/src/plugins/workspace-panels/resolution.ts index 8e7119e02a..b2436c6c52 100644 --- a/packages/app/src/plugins/workspace-panels/resolution.ts +++ b/packages/app/src/plugins/workspace-panels/resolution.ts @@ -1,4 +1,4 @@ -import type { PluginWorkspacePanelContribution } from "@paseo/plugin"; +import type { PluginWorkspacePanelContribution } from "@getpaseo/plugin"; import type { InstalledPlugin } from "../types"; import type { PluginWorkspaceTabTarget } from "@/workspace-tabs/model"; diff --git a/packages/cli/src/commands/plugin/scaffold.test.ts b/packages/cli/src/commands/plugin/scaffold.test.ts index 838defbfb3..8655a1ca01 100644 --- a/packages/cli/src/commands/plugin/scaffold.test.ts +++ b/packages/cli/src/commands/plugin/scaffold.test.ts @@ -50,7 +50,7 @@ describe("plugin scaffold", () => { await Promise.all([ writeFile( path.join(directory, "inspect.shared.ts"), - `import { defineRpc } from "@paseo/plugin/server"; + `import { defineRpc } from "@getpaseo/plugin/server"; import { z } from "zod"; export const inspect = defineRpc({ @@ -62,7 +62,7 @@ export const inspect = defineRpc({ ), writeFile( 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 { inspect } from "./inspect.shared"; @@ -83,7 +83,7 @@ import { useAgent, usePaseo, useWorkspace, -} from "@paseo/plugin"; +} from "@getpaseo/plugin"; export function Surface() { const paseo = usePaseo(); @@ -111,7 +111,7 @@ export function AgentPanel({ workspaceId, agentId }: PluginAgentPanelProps) { ), writeFile( path.join(directory, "index.ts"), - `import type { PluginContext } from "@paseo/plugin"; + `import type { PluginContext } from "@getpaseo/plugin"; import { AgentPanel, Surface } from "./main.client"; import { inspectConfig } from "./inspect.server"; import { inspect } from "./inspect.shared"; diff --git a/packages/cli/src/commands/plugin/scaffold.ts b/packages/cli/src/commands/plugin/scaffold.ts index b7151bb926..ba5ea91360 100644 --- a/packages/cli/src/commands/plugin/scaffold.ts +++ b/packages/cli/src/commands/plugin/scaffold.ts @@ -2,7 +2,7 @@ import { mkdir, readdir, writeFile } from "node:fs/promises"; import path from "node:path"; 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 { 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; } -declare module "@paseo/plugin" { +declare module "@getpaseo/plugin" { import type { ComponentType } from "react"; import type { PaseoApi } from "@getpaseo/client"; import type { ZodType, input as ZodInput, output as ZodOutput } from "zod"; @@ -64,7 +64,7 @@ declare module "@paseo/plugin" { PluginAttachmentSourceContribution, PluginHandlerContext, PluginRpcContract, - } from "@paseo/plugin/server"; + } from "@getpaseo/plugin/server"; export { PluginAttachmentItemSchema, @@ -76,7 +76,7 @@ declare module "@paseo/plugin" { type PluginAttachmentSourceContribution, type PluginHandlerContext, type PluginRpcContract, - } from "@paseo/plugin/server"; + } from "@getpaseo/plugin/server"; export interface PluginTheme { readonly colors: { @@ -242,7 +242,7 @@ const TSCONFIG = { include: ["**/*.ts", "**/*.tsx"], }; -const ENTRY = `import type { PluginContext } from "@paseo/plugin"; +const ENTRY = `import type { PluginContext } from "@getpaseo/plugin"; import { MainSurface } from "./main.client"; 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 { Text, View } from "react-native"; diff --git a/packages/plugin/package.json b/packages/plugin/package.json index ee26d73fb4..a621022cc0 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { - "name": "@paseo/plugin", + "name": "@getpaseo/plugin", "version": "0.5.0-beta.1", - "private": true, + "description": "Paseo plugin SDK package", "files": [ "dist", "!dist/**/*.map" @@ -24,6 +24,9 @@ "default": "./dist/host.js" } }, + "publishConfig": { + "access": "public" + }, "scripts": { "clean": "node ../../scripts/clean-package-dist.mjs", "build": "tsc -p tsconfig.json --incremental false", @@ -36,7 +39,7 @@ "use-sync-external-store": "^1.6.0" }, "devDependencies": { - "@getpaseo/client": "*", + "@getpaseo/client": "0.5.0-beta.1", "@types/node": "^20.9.0", "@types/react": "~19.2.0", "react": "19.1.0", @@ -45,7 +48,7 @@ "zod": "^4.4.3" }, "peerDependencies": { - "@getpaseo/client": "*", + "@getpaseo/client": "0.5.0-beta.1", "react": "19.1.0", "zod": "^4.4.3" } diff --git a/packages/plugin/src/server.test.ts b/packages/plugin/src/server.test.ts index c0eb35576f..5117249ae8 100644 --- a/packages/plugin/src/server.test.ts +++ b/packages/plugin/src/server.test.ts @@ -49,7 +49,7 @@ function collectBareSpecifiers(entry: string): string[] { return bare; } -describe("@paseo/plugin/server", () => { +describe("@getpaseo/plugin/server", () => { it("does not load react or the client hook graph", () => { const specifiers = collectBareSpecifiers(path.join(srcDir, "server.ts")); expect(specifiers.filter((specifier) => forbiddenSpecifiers.has(specifier))).toEqual([]); diff --git a/packages/server/package.json b/packages/server/package.json index 1e211b6026..5c17578600 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -74,12 +74,12 @@ "@babel/parser": "^7.29.8", "@getpaseo/client": "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/relay": "0.5.0-beta.1", "@isaacs/ttlcache": "^2.1.4", "@modelcontextprotocol/sdk": "^1.20.1", "@opencode-ai/sdk": "1.14.46", - "@paseo/plugin": "*", "@xterm/headless": "^6.0.0", "ai": "5.0.78", "ajv": "^8.20.0", diff --git a/packages/server/src/server/plugins/compiler.test.ts b/packages/server/src/server/plugins/compiler.test.ts index 545f29c50d..59eef6e458 100644 --- a/packages/server/src/server/plugins/compiler.test.ts +++ b/packages/server/src/server/plugins/compiler.test.ts @@ -73,14 +73,18 @@ afterEach(async () => { }); describe("plugin author module externals", () => { - it("leaves @paseo/plugin/server external in both bundles", async () => { - const directory = await mkdtemp(path.join(tmpdir(), "paseo-plugin-compiler-")); - temporaryDirectories.push(directory); - const entryPath = path.join(directory, "index.ts"); - await writeFile( - entryPath, - `import type { PluginContext } from "@paseo/plugin"; -import { defineRpc } from "@paseo/plugin/server"; + // COMPAT(plugin-sdk-scope): plugins written against the unpublished @paseo/plugin name must + // keep compiling. Drop that case with the specifiers in plugin-sdk-specifiers.ts. + it.each(["@getpaseo/plugin", "@paseo/plugin"])( + "leaves %s/server external in both bundles", + async (sdk) => { + const directory = await mkdtemp(path.join(tmpdir(), "paseo-plugin-compiler-")); + temporaryDirectories.push(directory); + const entryPath = path.join(directory, "index.ts"); + await writeFile( + entryPath, + `import type { PluginContext } from "${sdk}"; +import { defineRpc } from "${sdk}/server"; import { z } from "zod"; const ping = defineRpc({ @@ -94,12 +98,13 @@ export default function contribute(plugin: PluginContext) { return () => undefined; } `, - ); + ); - const { clientBundle, serverBundle } = await compilePlugin(entryPath); - expect(clientBundle).toContain("@paseo/plugin/server"); - expect(serverBundle).toContain("@paseo/plugin/server"); - expect(clientBundle).not.toContain("Invalid plugin RPC method"); - expect(serverBundle).not.toContain("Invalid plugin RPC method"); - }); + const { clientBundle, serverBundle } = await compilePlugin(entryPath); + expect(clientBundle).toContain(`${sdk}/server`); + expect(serverBundle).toContain(`${sdk}/server`); + expect(clientBundle).not.toContain("Invalid plugin RPC method"); + expect(serverBundle).not.toContain("Invalid plugin RPC method"); + }, + ); }); diff --git a/packages/server/src/server/plugins/compiler.ts b/packages/server/src/server/plugins/compiler.ts index e383d605d8..4713d1f332 100644 --- a/packages/server/src/server/plugins/compiler.ts +++ b/packages/server/src/server/plugins/compiler.ts @@ -4,6 +4,7 @@ import { createRequire } from "node:module"; import path from "node:path"; import { parse } from "@babel/parser"; import type { Plugin } from "esbuild"; +import { PLUGIN_SDK_SPECIFIERS } from "./plugin-sdk-specifiers.js"; const nodeRequire = createRequire(import.meta.url); const ESBUILD_BINARY_PATH = "ESBUILD_BINARY_PATH"; @@ -307,15 +308,14 @@ async function compileTarget(entryPath: string, target: PluginBuildTarget): Prom external: target === "client" ? [ - "@paseo/plugin", - "@paseo/plugin/server", + ...PLUGIN_SDK_SPECIFIERS, "@tanstack/react-query", "react", "react/jsx-runtime", "react-native", "zod", ] - : ["@paseo/plugin", "@paseo/plugin/server", "zod"], + : [...PLUGIN_SDK_SPECIFIERS, "zod"], plugins: [createRuntimeBoundaryPlugin(target), createUnusedPlatformModulePlugin(target)], logLevel: "silent", treeShaking: true, diff --git a/packages/server/src/server/plugins/plugin-paseo-api.e2e.test.ts b/packages/server/src/server/plugins/plugin-paseo-api.e2e.test.ts index e1cd938df4..a9e3fe3560 100644 --- a/packages/server/src/server/plugins/plugin-paseo-api.e2e.test.ts +++ b/packages/server/src/server/plugins/plugin-paseo-api.e2e.test.ts @@ -21,7 +21,7 @@ test("plugin handlers create workspaces and agents through their Paseo API", asy ); await writeFile( path.join(pluginDirectory, "index.tsx"), - `import { defineRpc, type PluginContext } from "@paseo/plugin"; + `import { defineRpc, type PluginContext } from "@getpaseo/plugin"; import { z } from "zod"; const create = defineRpc({ diff --git a/packages/server/src/server/plugins/plugin-process.ts b/packages/server/src/server/plugins/plugin-process.ts index 65a62540c5..7fe29aef26 100644 --- a/packages/server/src/server/plugins/plugin-process.ts +++ b/packages/server/src/server/plugins/plugin-process.ts @@ -5,10 +5,11 @@ import { defineRpc, type PluginHandlerContext, type PluginRpcContract, -} from "@paseo/plugin/server"; +} from "@getpaseo/plugin/server"; import { createPaseoApi, type PaseoApi } from "@getpaseo/client"; import { DaemonClient } from "@getpaseo/client/internal/daemon-client"; import { createPluginDaemonTransportFactory } from "./daemon-transport.js"; +import { isPluginSdkSpecifier } from "./plugin-sdk-specifiers.js"; type RpcHandler = (input: unknown, context: PluginHandlerContext) => unknown | Promise; @@ -64,7 +65,7 @@ function register(contract: PluginRpcContract, handler: RpcHandler): void { const pluginAuthorRuntime = { defineAttachmentSource, defineRpc }; function runtimeRequire(name: string): unknown { - if (name === "@paseo/plugin" || name === "@paseo/plugin/server") return pluginAuthorRuntime; + if (isPluginSdkSpecifier(name)) return pluginAuthorRuntime; return nodeRequire(name); } diff --git a/packages/server/src/server/plugins/plugin-sdk-specifiers.ts b/packages/server/src/server/plugins/plugin-sdk-specifiers.ts new file mode 100644 index 0000000000..66ff688ce4 --- /dev/null +++ b/packages/server/src/server/plugins/plugin-sdk-specifiers.ts @@ -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); +} diff --git a/packages/server/src/server/plugins/runtime.posix.test.ts b/packages/server/src/server/plugins/runtime.posix.test.ts index 850cca304d..4b881d009a 100644 --- a/packages/server/src/server/plugins/runtime.posix.test.ts +++ b/packages/server/src/server/plugins/runtime.posix.test.ts @@ -501,7 +501,7 @@ export default function contribute(plugin: unknown) { import { platform } from "node:os"; import { Text } from "react-native"; import { z } from "zod"; -import { defineAttachmentSource, defineRpc } from "@paseo/plugin"; +import { defineAttachmentSource, defineRpc } from "@getpaseo/plugin"; const greetRpc = defineRpc({ name: "greet", @@ -560,6 +560,34 @@ export default function contribute(plugin: any) { 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 () => { const directory = await mkdtemp(path.join(tmpdir(), "paseo-plugin-")); temporaryDirectories.push(directory); @@ -571,7 +599,7 @@ export default function contribute(plugin: any) { ), writeFile( path.join(directory, "index.ts"), - `import type { PluginContext } from "@paseo/plugin"; + `import type { PluginContext } from "@getpaseo/plugin"; import { Surface } from "./surface.client"; import { inspectRpc } from "./inspect.shared"; import { inspectHost } from "./inspect.server"; @@ -597,7 +625,7 @@ export function Surface() { ), writeFile( path.join(directory, "inspect.shared.ts"), - `import { defineRpc } from "@paseo/plugin/server"; + `import { defineRpc } from "@getpaseo/plugin/server"; import { z } from "zod"; export const inspectRpc = defineRpc({ @@ -643,7 +671,7 @@ export function inspectHost(_input: z.input) { ), writeFile( path.join(directory, "index.ts"), - `import type { PluginContext } from "@paseo/plugin"; + `import type { PluginContext } from "@getpaseo/plugin"; import { Surface } from "./surface.client"; export default function contribute(plugin: PluginContext) { @@ -683,7 +711,7 @@ export function Surface() { return readSecret(); }`, ), writeFile( path.join(directory, "index.ts"), - `import type { PluginContext } from "@paseo/plugin"; + `import type { PluginContext } from "@getpaseo/plugin"; import { inspect } from "./inspect.server"; import { inspectRpc } from "./inspect.shared"; @@ -695,7 +723,7 @@ export default function contribute(plugin: PluginContext) { ), writeFile( path.join(directory, "inspect.shared.ts"), - `import { defineRpc } from "@paseo/plugin"; + `import { defineRpc } from "@getpaseo/plugin"; import { z } from "zod"; export const inspectRpc = defineRpc({ name: "inspect", @@ -728,7 +756,7 @@ export function inspect() { void Surface; return {}; }`, const directory = await createPlugin( "invalid-output", `import { z } from "zod"; -import { defineRpc } from "@paseo/plugin"; +import { defineRpc } from "@getpaseo/plugin"; const brokenRpc = defineRpc({ name: "broken", input: z.object({}), diff --git a/plugin-examples/linear/index.ts b/plugin-examples/linear/index.ts index f1c57bff88..84b93af5b4 100644 --- a/plugin-examples/linear/index.ts +++ b/plugin-examples/linear/index.ts @@ -1,4 +1,4 @@ -import type { PluginContext } from "@paseo/plugin"; +import type { PluginContext } from "@getpaseo/plugin"; import { searchIssues } from "./issues.server"; import { issueAttachments, searchIssuesRpc } from "./issues.shared"; diff --git a/plugin-examples/linear/issues.server.ts b/plugin-examples/linear/issues.server.ts index d2f7ed273f..d353d53adc 100644 --- a/plugin-examples/linear/issues.server.ts +++ b/plugin-examples/linear/issues.server.ts @@ -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 { searchIssuesRpc } from "./issues.shared"; import { createLinearIssueSearch } from "./linear"; diff --git a/plugin-examples/linear/issues.shared.ts b/plugin-examples/linear/issues.shared.ts index f46ee50b19..fb16c388dd 100644 --- a/plugin-examples/linear/issues.shared.ts +++ b/plugin-examples/linear/issues.shared.ts @@ -1,4 +1,4 @@ -import { defineAttachmentSource, defineRpc } from "@paseo/plugin/server"; +import { defineAttachmentSource, defineRpc } from "@getpaseo/plugin/server"; import { z } from "zod"; const SearchPayloadSchema = z.object({ diff --git a/plugin-examples/local-plugin/increment.shared.ts b/plugin-examples/local-plugin/increment.shared.ts index 4f7116eeeb..633d39104e 100644 --- a/plugin-examples/local-plugin/increment.shared.ts +++ b/plugin-examples/local-plugin/increment.shared.ts @@ -1,4 +1,4 @@ -import { defineRpc } from "@paseo/plugin/server"; +import { defineRpc } from "@getpaseo/plugin/server"; import { z } from "zod"; export const incrementRpc = defineRpc({ diff --git a/plugin-examples/local-plugin/index.ts b/plugin-examples/local-plugin/index.ts index dc19d89595..38118fcb06 100644 --- a/plugin-examples/local-plugin/index.ts +++ b/plugin-examples/local-plugin/index.ts @@ -1,4 +1,4 @@ -import type { PluginContext } from "@paseo/plugin"; +import type { PluginContext } from "@getpaseo/plugin"; import { ExamplePanel } from "./main.client"; import { increment } from "./increment.server"; import { incrementRpc } from "./increment.shared"; diff --git a/plugin-examples/local-plugin/main.client.tsx b/plugin-examples/local-plugin/main.client.tsx index bfaf6bba7f..16d9b0f46d 100644 --- a/plugin-examples/local-plugin/main.client.tsx +++ b/plugin-examples/local-plugin/main.client.tsx @@ -1,5 +1,5 @@ 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 { Pressable, Text, View } from "react-native"; import { incrementRpc } from "./increment.shared"; diff --git a/public-docs/plugins/index.md b/public-docs/plugins/index.md index 1aff8ff422..b3e8806391 100644 --- a/public-docs/plugins/index.md +++ b/public-docs/plugins/index.md @@ -46,7 +46,7 @@ Plugins run on desktop, browser, iOS, and Android. Paseo ships several themes. C Replace `main.client.tsx` with: ```tsx -import { type PluginWorkspacePanelProps, useWorkspace } from "@paseo/plugin"; +import { type PluginWorkspacePanelProps, useWorkspace } from "@getpaseo/plugin"; import { useMemo } from "react"; import { Text, View } from "react-native"; @@ -83,7 +83,7 @@ export function WorkspaceOverview({ theme, layout, workspaceId }: PluginWorkspac Replace `index.ts` with: ```ts -import type { PluginContext } from "@paseo/plugin"; +import type { PluginContext } from "@getpaseo/plugin"; import { WorkspaceOverview } from "./main.client"; export default function contribute(plugin: PluginContext) { diff --git a/public-docs/plugins/reference.md b/public-docs/plugins/reference.md index 43fa6c9248..cb88207985 100644 --- a/public-docs/plugins/reference.md +++ b/public-docs/plugins/reference.md @@ -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. -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: @@ -60,10 +60,10 @@ my-plugin/ ## SDK modules -| Module | Use it for | -| ---------------------- | -------------------------------------------------------- | -| `@paseo/plugin` | hooks and UI types | -| `@paseo/plugin/server` | `defineRpc`, `defineAttachmentSource`, and handler types | +| Module | Use it for | +| ------------------------- | -------------------------------------------------------- | +| `@getpaseo/plugin` | hooks and UI 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. @@ -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: ```ts -import type { PluginContext } from "@paseo/plugin"; +import type { PluginContext } from "@getpaseo/plugin"; import { Main } from "./main.client"; 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`: ```tsx -import type { PluginSurfaceProps } from "@paseo/plugin"; +import type { PluginSurfaceProps } from "@getpaseo/plugin"; import { useMemo } from "react"; import { Text, View } from "react-native"; @@ -119,7 +119,7 @@ export function Main({ theme, host, layout }: PluginSurfaceProps) { `index.ts`: ```ts -import type { PluginContext } from "@paseo/plugin"; +import type { PluginContext } from "@getpaseo/plugin"; import { Main } from "./main.client"; 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. -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 @@ -171,7 +171,7 @@ Register one panel for workspace or agent context: `review.client.tsx`: ```tsx -import { type PluginAgentPanelProps, useAgent, useWorkspace } from "@paseo/plugin"; +import { type PluginAgentPanelProps, useAgent, useWorkspace } from "@getpaseo/plugin"; import { useMemo } from "react"; import { Text, View } from "react-native"; @@ -202,7 +202,7 @@ export function ReviewPanel({ theme, layout, workspaceId, agentId }: PluginAgent `index.ts`: ```ts -import type { PluginContext } from "@paseo/plugin"; +import type { PluginContext } from "@getpaseo/plugin"; import { ReviewPanel } from "./review.client"; 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: ```tsx -import { defineRpc } from "@paseo/plugin/server"; +import { defineRpc } from "@getpaseo/plugin/server"; import { z } from "zod"; 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. ```tsx -import { usePaseo } from "@paseo/plugin"; +import { usePaseo } from "@getpaseo/plugin"; import { Pressable, Text } from "react-native"; function PullRequestAction() { @@ -377,7 +377,7 @@ Define one contract with Zod, handle it in the subprocess, and call it from the `greeting.shared.ts`: ```ts -import { defineRpc } from "@paseo/plugin/server"; +import { defineRpc } from "@getpaseo/plugin/server"; import { z } from "zod"; export const greeting = defineRpc({ @@ -390,7 +390,7 @@ export const greeting = defineRpc({ `greeting.client.tsx`: ```tsx -import { useRpc } from "@paseo/plugin"; +import { useRpc } from "@getpaseo/plugin"; import { greeting } from "./greeting.shared"; export function GreetingButton() { @@ -414,7 +414,7 @@ export function createGreeting({ name }: ZodOutput) { `index.ts`: ```ts -import type { PluginContext } from "@paseo/plugin"; +import type { PluginContext } from "@getpaseo/plugin"; import { GreetingButton } from "./greeting.client"; import { createGreeting } from "./greeting.server"; import { greeting } from "./greeting.shared"; @@ -474,7 +474,7 @@ An attachment source searches external resources and returns a stable text snaps `issues.shared.ts`: ```ts -import { defineAttachmentSource, defineRpc } from "@paseo/plugin/server"; +import { defineAttachmentSource, defineRpc } from "@getpaseo/plugin/server"; import { z } from "zod"; export const searchIssues = defineRpc({ @@ -519,7 +519,7 @@ export function search({ query }: ZodOutput) { `index.ts`: ```ts -import type { PluginContext } from "@paseo/plugin"; +import type { PluginContext } from "@getpaseo/plugin"; import { search } from "./issues.server"; import { issues, searchIssues } from "./issues.shared"; diff --git a/skills/paseo-plugin/SKILL.md b/skills/paseo-plugin/SKILL.md index c70cc329db..14a81875ec 100644 --- a/skills/paseo-plugin/SKILL.md +++ b/skills/paseo-plugin/SKILL.md @@ -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: ```tsx -import type { PluginContext } from "@paseo/plugin"; +import type { PluginContext } from "@getpaseo/plugin"; export default function contribute(plugin: PluginContext) { // 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. ```tsx -import { type PluginContext, type PluginWorkspacePanelProps, useWorkspace } from "@paseo/plugin"; +import { type PluginContext, type PluginWorkspacePanelProps, useWorkspace } from "@getpaseo/plugin"; import { useMemo } from "react"; 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`. ```tsx -import type { PluginContext, PluginSurfaceProps } from "@paseo/plugin"; +import type { PluginContext, PluginSurfaceProps } from "@getpaseo/plugin"; import React, { useMemo, useState } from "react"; 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. -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 | -| ---------------------- | ---------------------------------------------------- | -| `@paseo/plugin` | hooks and UI types | -| `@paseo/plugin/server` | `defineRpc`, `defineAttachmentSource`, handler types | +| Module | Use it for | +| ------------------------- | ---------------------------------------------------- | +| `@getpaseo/plugin` | hooks and UI types | +| `@getpaseo/plugin/server` | `defineRpc`, `defineAttachmentSource`, handler types | ## 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. ```tsx -import { usePaseo } from "@paseo/plugin"; +import { usePaseo } from "@getpaseo/plugin"; function PullRequestAction() { 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()`: ```tsx -import type { PluginContext } from "@paseo/plugin"; -import { useRpc } from "@paseo/plugin"; -import { defineRpc } from "@paseo/plugin/server"; +import type { PluginContext } from "@getpaseo/plugin"; +import { useRpc } from "@getpaseo/plugin"; +import { defineRpc } from "@getpaseo/plugin/server"; import { z } from "zod"; const greeting = defineRpc({ @@ -275,8 +275,8 @@ daemon log. Never log credentials or other secrets. Define a search RPC and register a declarative source: ```tsx -import type { PluginContext } from "@paseo/plugin"; -import { defineAttachmentSource, defineRpc } from "@paseo/plugin/server"; +import type { PluginContext } from "@getpaseo/plugin"; +import { defineAttachmentSource, defineRpc } from "@getpaseo/plugin/server"; import { z } from "zod"; const searchIssues = defineRpc({