From 0b83ce8977c8a3ca922f42a5aff7707ac85d5bc9 Mon Sep 17 00:00:00 2001 From: Shreyan Dey <90114886+Dey11@users.noreply.github.com> Date: Fri, 28 Aug 2026 06:03:31 +0000 Subject: [PATCH 1/3] Simplify plugins around workspace tabs --- AGENTS.md | 5 +- CONTRIBUTING.md | 2 +- README.md | 20 +- SECURITY.md | 5 +- bun.lock | 15 - docs/installation.md | 23 +- docs/mocks/native-plugin-surfaces.html | 82 +--- docs/mocks/plugin-suite.html | 8 - docs/plans/paseo-plugin-suite.md | 29 +- docs/plans/public-release.md | 9 +- docs/usage.md | 12 +- plugins/linear/README.md | 4 +- plugins/linear/index.ts | 4 +- plugins/linear/main.client.tsx | 4 +- plugins/plugin-contributions.test.ts | 19 +- plugins/prompt-library/README.md | 46 -- plugins/prompt-library/contracts.ts | 55 --- plugins/prompt-library/index.ts | 65 --- plugins/prompt-library/library.test.ts | 59 --- plugins/prompt-library/library.ts | 67 --- plugins/prompt-library/main.client.tsx | 341 ------------- plugins/prompt-library/package.json | 19 - plugins/prompt-library/paseo-plugin.d.ts | 286 ----------- plugins/prompt-library/paseo-plugin.json | 3 - plugins/prompt-library/store.server.ts | 65 --- plugins/prompt-library/tsconfig.json | 15 - plugins/workspace-companion/README.md | 38 +- plugins/workspace-companion/contracts.ts | 88 ---- plugins/workspace-companion/index.ts | 118 +---- plugins/workspace-companion/main.client.tsx | 457 ++---------------- plugins/workspace-companion/package.json | 2 +- .../workspace-companion/qa-config.server.ts | 107 ---- plugins/workspace-companion/qa-config.test.ts | 30 -- plugins/workspace-companion/qa.ts | 37 -- plugins/workspace-companion/review.server.ts | 147 ------ plugins/workspace-companion/review.test.ts | 93 ---- plugins/workspace-companion/review.ts | 141 ------ 37 files changed, 111 insertions(+), 2409 deletions(-) delete mode 100644 plugins/prompt-library/README.md delete mode 100644 plugins/prompt-library/contracts.ts delete mode 100644 plugins/prompt-library/index.ts delete mode 100644 plugins/prompt-library/library.test.ts delete mode 100644 plugins/prompt-library/library.ts delete mode 100644 plugins/prompt-library/main.client.tsx delete mode 100644 plugins/prompt-library/package.json delete mode 100644 plugins/prompt-library/paseo-plugin.d.ts delete mode 100644 plugins/prompt-library/paseo-plugin.json delete mode 100644 plugins/prompt-library/store.server.ts delete mode 100644 plugins/prompt-library/tsconfig.json delete mode 100644 plugins/workspace-companion/qa-config.server.ts delete mode 100644 plugins/workspace-companion/qa-config.test.ts delete mode 100644 plugins/workspace-companion/qa.ts delete mode 100644 plugins/workspace-companion/review.server.ts delete mode 100644 plugins/workspace-companion/review.test.ts delete mode 100644 plugins/workspace-companion/review.ts diff --git a/AGENTS.md b/AGENTS.md index 8403f19..741c4d2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # Paseo Productivity Plugins — AGENTS.md -This repository contains trusted local Paseo plugins for workspace notes and review workflows, reusable prompts, Linear issue work, and development-port management. Each plugin is independently installable on a local or remote Paseo daemon, and the repository is maintained for source distribution to other Paseo users. +This repository contains trusted local Paseo plugins for workspace notes and board workflows, Linear issue work, and development-port management. Each plugin is independently installable on a local or remote Paseo daemon, and the repository is maintained for source distribution to other Paseo users. ## Non-Negotiable Core Principles @@ -19,8 +19,7 @@ User instructions take precedence. Preserve unrelated files and running processe ## Project Glossary -- **Workspace Companion**: Notes, one unified workspace board, and transcript-aware manual QA plans. -- **Prompt Library**: Globally stored reusable prompts exposed in the sidebar and composer attachment picker. +- **Workspace Companion**: Workspace-tab notes and one unified workspace board. - **Linear**: Direct GraphQL integration for reading and explicitly confirmed issue mutations. - **Dev Ports**: Same-user workspace process discovery, safe termination, and Tailscale Serve controls. - **Board state**: `running` and `error` are derived from Paseo activity; `unreviewed`, `recheck`, and `approved` are plugin-owned review markers. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 566befb..73fd5aa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,7 +34,7 @@ For UI changes, test a wide desktop view and a compact view. Use Paseo theme col - Keep Node APIs, credentials, shell commands, Git access, and filesystem access in `*.server.ts` files. - Validate RPC inputs and outputs with Zod. - Use Paseo's SDK for normal workspace and agent operations. -- Never log credentials, transcript contents, or private prompt-library entries. +- Never log credentials, transcript contents, or private workspace notes. Paseo plugin changes require a source reload: diff --git a/README.md b/README.md index e5a2f2b..7dd0146 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,19 @@ # Paseo plugins -Four local plugins for [Paseo](https://paseo.sh): workspace notes and QA planning, reusable prompts, Linear issue work, and development-port controls. +Three local plugins for [Paseo](https://paseo.sh): workspace notes and an agent board, Linear issue work, and development-port controls. > [!WARNING] > Paseo plugins are experimental, trusted code. Server-side plugin code runs without a sandbox on the daemon machine. Read the source before installing it, and expect Paseo API changes to require updates. ## Included plugins -| Plugin | What it adds | Extra requirement | -| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------- | -| [Workspace Companion](plugins/workspace-companion) | Markdown notes, a draggable agent board with workspace archiving, and transcript-aware manual QA plans | A configured Paseo coding-agent provider for QA generation | -| [Prompt Library](plugins/prompt-library) | A reusable prompt library in the sidebar and composer attachment picker | None | -| [Linear](plugins/linear) | Issue search, comments, status changes, and priority changes | A Linear personal API key | -| [Dev Ports](plugins/dev-ports) | Workspace port discovery, safe process stopping, browser links, and private Tailscale Serve controls | Linux daemon; Tailscale is optional | +| Plugin | What it adds | Extra requirement | +| -------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------- | +| [Workspace Companion](plugins/workspace-companion) | Workspace-tab Markdown notes and a draggable agent board with workspace archiving | None | +| [Linear](plugins/linear) | Workspace-tab issue search, comments, status changes, and priority changes | A Linear personal API key | +| [Dev Ports](plugins/dev-ports) | Workspace port discovery, safe process stopping, browser links, and private Tailscale Serve controls | Linux daemon; Tailscale is optional | -Each plugin is independently installable. You do not need to enable all four. +Each plugin is independently installable. You do not need to enable all three. ## Quick start @@ -38,7 +37,6 @@ In Paseo, open **Settings → Plugins** and enable plugins. Then install only th ```bash paseo plugin install "$PWD/plugins/workspace-companion" -paseo plugin install "$PWD/plugins/prompt-library" paseo plugin install "$PWD/plugins/linear" paseo plugin install "$PWD/plugins/dev-ports" paseo plugin ls @@ -58,7 +56,6 @@ bun install --frozen-lockfile bun run test bun run typecheck paseo plugin reload workspace-companion -paseo plugin reload prompt-library paseo plugin reload linear paseo plugin reload dev-ports ``` @@ -72,7 +69,6 @@ Plugin state is stored under the daemon's Paseo home, normally `~/.paseo/plugin- - Linear mutations require an explicit confirmation in the UI. - Dev Ports only shows same-user listeners inside registered Paseo workspaces. It sends `SIGTERM` and never force-kills a process. - Dev Ports creates private Tailscale Serve mappings. It never enables Tailscale Funnel. -- Workspace Companion sends the focused agent transcript and current workspace changes to the provider configured for QA planning. Read [SECURITY.md](SECURITY.md) before installing the plugins on a shared daemon. @@ -89,7 +85,7 @@ The suite uses Bun workspaces. Each plugin keeps its own Paseo manifest, strict ## Paseo compatibility -Paseo does not currently provide a stable plugin distribution format. This repository distributes source directories that the daemon compiles locally. Use a recent Paseo release and consult the official [plugin quickstart](https://paseo.sh/docs/plugins) and [plugin reference](https://paseo.sh/docs/plugins/reference) when the API changes. +Paseo's plugin API is experimental. This repository distributes source directories that the daemon compiles locally. Use a recent Paseo release and consult the official [plugin quickstart](https://paseo.sh/docs/plugins) and [plugin reference](https://paseo.sh/docs/plugins/reference) when the API changes. ## License diff --git a/SECURITY.md b/SECURITY.md index 1f4e666..e9d52ff 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -8,8 +8,7 @@ Review the plugin directory before installing it. On shared daemons, treat plugi ## Plugin permissions -- `workspace-companion` reads workspace Git metadata and the focused agent's projected transcript when you manually generate a QA plan. It stores notes, board state, and QA plans under Paseo's plugin-data directory. -- `prompt-library` reads and writes its own prompt store under Paseo's plugin-data directory. Attached prompts become part of the message sent to the selected agent. +- `workspace-companion` stores notes and board state under Paseo's plugin-data directory. Refining a note sends its current contents to the selected workspace agent. - `linear` sends requests to Linear with the configured personal API key. Writes require an explicit confirmation in the panel. - `dev-ports` reads Linux socket and `/proc` metadata, can send `SIGTERM` to a verified same-user workspace process, and can create or remove Tailscale Serve mappings that it owns. @@ -17,7 +16,7 @@ None of the plugins should log credentials or stored content. ## Credentials -Never commit a Linear key or a QA-provider secret. Keep credentials in the daemon environment or the documented user-only configuration files. Restrict credential files to the daemon user: +Never commit a Linear key. Keep it in the daemon environment or the documented user-only configuration file. Restrict credential files to the daemon user: ```bash chmod 600 ~/.config/paseo-plugins/*.env diff --git a/bun.lock b/bun.lock index 998224c..eeb463b 100644 --- a/bun.lock +++ b/bun.lock @@ -39,19 +39,6 @@ "zod": "^4.4.3", }, }, - "plugins/prompt-library": { - "name": "prompt-library", - "version": "0.0.0", - "devDependencies": { - "@getpaseo/client": "^0.4.0", - "@tanstack/react-query": "^5.90.11", - "@types/react": "~19.2.0", - "react": "19.1.0", - "react-native": "0.81.5", - "typescript": "^5.9.3", - "zod": "^4.4.3", - }, - }, "plugins/workspace-companion": { "name": "workspace-companion", "version": "0.0.0", @@ -541,8 +528,6 @@ "promise": ["promise@8.3.0", "", { "dependencies": { "asap": "~2.0.6" } }, "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg=="], - "prompt-library": ["prompt-library@workspace:plugins/prompt-library"], - "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], "react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="], diff --git a/docs/installation.md b/docs/installation.md index 37a288e..581d1c5 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -31,14 +31,14 @@ bun run typecheck Install a plugin with an absolute directory path: ```bash -paseo plugin install "$PWD/plugins/prompt-library" +paseo plugin install "$PWD/plugins/workspace-companion" paseo plugin ls ``` The plugin should report `running`. If it does not, inspect its retained log: ```bash -paseo plugin logs prompt-library +paseo plugin logs workspace-companion ``` ## Install on a remote host @@ -70,24 +70,6 @@ paseo plugin reload linear The plugin reads the key when it handles a request. It does not return or log the key. -## Configure Workspace Companion QA - -QA generation starts a temporary Paseo agent. By default it uses `codex/gpt-5.6-sol`, `auto-review`, and high thinking. If that provider or model is not available on your daemon, create: - -```text -~/.config/paseo-plugins/workspace-companion.env -``` - -Set the provider and optional mode values: - -```bash -PASEO_QA_PROVIDER=codex/gpt-5.5 -PASEO_QA_MODE=auto-review -PASEO_QA_THINKING=high -``` - -Use provider, mode, and thinking IDs reported by your Paseo installation. Reload Workspace Companion after changing the file. - ## Configure Dev Ports Dev Ports requires a Linux daemon with `ss` and `/proc`. Port discovery and safe process stopping work without Tailscale. @@ -130,7 +112,6 @@ Removing a plugin removes Paseo's installation record. It does not delete the cl | Plugin failed to load | Run `bun run typecheck`, then inspect `paseo plugin logs `. | | Edited code is stale | Run `paseo plugin reload `. | | Linear says it is not configured | Put the key in the daemon environment or the documented credential file, then reload. | -| QA generation fails immediately | Configure a provider, model, mode, and thinking option that exist on the daemon. | | Dev Ports shows no listeners | Confirm the daemon is Linux, `ss` is installed, and the process directory belongs to a registered workspace. | | Tailscale access is denied | Set the daemon user as the Tailscale operator once. | diff --git a/docs/mocks/native-plugin-surfaces.html b/docs/mocks/native-plugin-surfaces.html index 5dad81a..3da982d 100644 --- a/docs/mocks/native-plugin-surfaces.html +++ b/docs/mocks/native-plugin-surfaces.html @@ -658,7 +658,7 @@

Confirm Linear change

Notes

-

Workspace context shared with this agent

+

Private Markdown context for this workspace

@@ -670,7 +670,7 @@

Notes

## Decisions - Keep the board limited to five states -- QA the drag interaction on desktop +- Test the drag interaction on desktop ## Follow-ups @@ -685,84 +685,6 @@

Notes

-
-
-
-

QA review

-

Manual checks inferred from the work and its conversation

-
- -
-
- 18 transcript messages - 7 changed files - +184 −96 - Generated 4:32 AM -
-
-
What changed
-
-

- The workspace companion panels now use Paseo's quieter grouped - layout. -

-

- Review planning now turns the agent conversation and current - diff into manual QA flows. -

-
-
-
-
Test these flows
-
-
-
-

Generate a QA plan from an agent

- High -
-

- The review action now reads transcript context and - working-tree changes. -

-
    -
  1. Focus an agent with completed workspace changes.
  2. -
  3. Open QA review and choose Regenerate.
  4. -
  5. - Confirm the plan names the changed screens and gives - executable checks. -
  6. -
-
-
-
-

Edit and preview a workspace note

- Normal -
-

- The note editor, preview, dirty state, and save controls were - redesigned. -

-
    -
  1. Edit Markdown and verify Unsaved changes appears.
  2. -
  3. Switch between Write and Preview without losing text.
  4. -
  5. - Save, reopen the panel, and confirm the note persists. -
  6. -
-
-
-
-
-
Watch for
-
    -
  • - Plans that describe implementation details instead of - user-visible checks -
  • -
  • Missing empty and error states on compact clients
  • -
-
-
diff --git a/docs/mocks/plugin-suite.html b/docs/mocks/plugin-suite.html index 22f4f9f..45c15c7 100644 --- a/docs/mocks/plugin-suite.html +++ b/docs/mocks/plugin-suite.html @@ -232,7 +232,6 @@

Paseo

Workspaces
Schedules
Agent board
-
Prompt library
Dev ports
@@ -297,13 +296,6 @@

Notes

-
- QA plan ready -

- Test the updated authentication and migration flows in the app. -

-
-
diff --git a/docs/plans/paseo-plugin-suite.md b/docs/plans/paseo-plugin-suite.md index 2ebba0a..ce2f853 100644 --- a/docs/plans/paseo-plugin-suite.md +++ b/docs/plans/paseo-plugin-suite.md @@ -2,7 +2,7 @@ ## Goal -Add four trusted local Paseo plugins: workspace notes and review workflows, a reusable prompt library, direct Linear issue tools, and safe development-port controls. +Maintain three trusted local Paseo plugins: workspace notes and board workflows, direct Linear issue tools, and safe development-port controls. ## Context @@ -12,15 +12,14 @@ Paseo 0.5 exposes global surfaces, sidebar items, workspace/agent panels, comman 1. Workspace-scoped Markdown notes with write and preview modes; the current agent can refine a replacement note that the user reviews before saving. 2. One workspace board with exactly five columns, ordered `Running`, `Unreviewed`, `Recheck`, `Error`, and `Approved`. `Running` and `Error` are live states; the other three are plugin-owned review states. A separate header drop target archives the actual Paseo workspace without introducing a sixth status. -3. A global prompt library exposed through both a sidebar surface and composer attachment picker. -4. A direct Linear GraphQL panel for search, issue detail, comments, status, and priority updates. Every write requires a second explicit confirmation. -5. A manual QA plan generated from the focused agent's transcript and an overview of current workspace changes. It identifies user-facing screens and flows to test rather than reviewing code. -6. Workspace-scoped listening-port discovery, safe `SIGTERM`, private Tailscale Serve controls, and forwarded links opened by the operating system browser. +3. A workspace-context Linear GraphQL panel for search, issue detail, comments, status, and priority updates. Every write requires a second explicit confirmation. +4. Workspace-scoped listening-port discovery, safe `SIGTERM`, private Tailscale Serve controls, and forwarded links opened by the operating system browser. ## Non-goals - Replacing Paseo's native workspace lifecycle or maintaining a separate plugin-only archive. -- Automatic review popovers, automatic QA-plan generation, or persistent reviewer agents. +- QA-plan generation or code-review automation. +- Reusable prompt storage or composer prompt attachments. - Killing processes outside registered workspaces or escalating to `SIGKILL`. - Public exposure through Tailscale Funnel. - Linear project administration, bulk edits, or automation. @@ -43,8 +42,6 @@ The workspace companion renders one card per workspace. A real agent or workspac Archive remains an action outside the workflow state machine. Desktop/web users drag a card to a header target, while touch and keyboard users use a two-step card action. The client calls `paseo.workspaces.archive`, removes the workspace and its agents from the query cache immediately, and restores the previous cache if the daemon reports an error or does not confirm `archivedAt`. -QA-plan generation is asynchronous because plugin RPC requests have a shorter timeout than a high-reasoning analyst run. The command records a generating state immediately, the panel polls that state, and a temporary auto-archived Sol agent analyzes the focused agent's public projected timeline together with the current Git overview. The analyst receives a constrained JSON schema and explicit product-QA instructions: no edits, no code-quality findings, and no transcript instructions treated as commands. - Global plugin surfaces do not receive Paseo's internal router or external-link helper. Workspace cards therefore use Paseo's canonical host/workspace URL on web and its `paseo://` deep link on native. Dev Ports calls the desktop preload's allowlisted `opener.openUrl` bridge when present, then falls back to a normal browser tab or native Linking. ## Alternatives considered @@ -58,17 +55,15 @@ Global plugin surfaces do not receive Paseo's internal router or external-link h ## Implementation phases -1. Scaffold the repository and four plugin packages; establish contracts and pure domain tests. -2. Build Workspace Companion notes, board, review states, and on-demand transcript-aware QA plans. -3. Build Prompt Library storage, management surface, and attachment search. -4. Build Linear GraphQL adapter and confirmed mutations. -5. Build Dev Ports discovery, safety classifier, process controls, and Tailscale adapter. -6. Typecheck, test, install, reload, inspect daemon health/logs, and review the complete diff. +1. Maintain Workspace Companion notes, board, review states, and workspace archiving. +2. Maintain the Linear GraphQL adapter and confirmed mutations. +3. Maintain Dev Ports discovery, safety classification, process controls, and Tailscale adapter. +4. Typecheck, test, install, reload, inspect daemon health/logs, and review the complete diff. ## Validation -- Focused Bun tests for concurrent persistence, board-state precedence, review workflow transitions and legacy-state migration, workspace routes, QA evidence parsing and plan construction, Linear credential/confirmation/error behavior, external browser selection, port parsing/safety, Tailscale command construction, and mapping ownership. No test mutates a live Linear account or Tailscale configuration. -- Strict TypeScript checks in all four packages. +- Focused Bun tests for concurrent persistence, board-state precedence, review workflow transitions and legacy-state migration, workspace routes, Linear credential/confirmation/error behavior, external browser selection, port parsing/safety, Tailscale command construction, and mapping ownership. No test mutates a live Linear account or Tailscale configuration. +- Strict TypeScript checks in all three packages. - Paseo plugin installation/reload without daemon restart. - Daemon status and plugin list/log inspection after installation. @@ -81,4 +76,4 @@ Global plugin surfaces do not receive Paseo's internal router or external-link h ## Status -Implemented and locally installed on 2026-08-21. The Agent Board and Dev Ports native-quality pass was completed on 2026-08-22 against Paseo's current public plugin contract and repository design guidance. On 2026-08-22, Agent Board ordering was made persistent and movement optimistic, the Linear panel was rebuilt around Paseo's grouped rows and restrained hierarchy, and Workspace Companion's Notes and QA review panels received the same native-quality pass. QA review now generates on demand from the focused agent's transcript and current changes. The Agent Board now archives real Paseo workspaces through a header drop target with optimistic rollback and an accessible two-step fallback. Public installation guides and portable Linear and QA configuration were added before distribution. All 42 focused tests, all four strict typechecks, and formatting pass. Workspace Companion and Linear reload as `running`, and both retained logs end in `Plugin ready` without errors. +Implemented and locally installed on 2026-08-21. The Agent Board and Dev Ports native-quality pass was completed on 2026-08-22. Agent Board ordering is persistent and optimistic, and archiving uses a header drop target with rollback plus an accessible two-step fallback. On 2026-08-28, Prompt Library and QA Review were removed, while Workspace Notes and Linear moved to workspace-context panels so Paseo lists them in its native workspace tab menu. The maintained suite passes 34 focused tests, all three strict typechecks, and formatting; Workspace Companion and Linear reload as `running` with clean `Plugin ready` logs. diff --git a/docs/plans/public-release.md b/docs/plans/public-release.md index 997b955..5646656 100644 --- a/docs/plans/public-release.md +++ b/docs/plans/public-release.md @@ -2,7 +2,7 @@ ## Goal -Publish the existing four-plugin suite to `Dey11/paseo-plugins` with enough setup, security, and troubleshooting information for another Paseo user to install one plugin without maintainer help. +Publish the plugin suite to `Dey11/paseo-plugins` with enough setup, security, and troubleshooting information for another Paseo user to install one plugin without maintainer help. ## Context @@ -12,7 +12,7 @@ Paseo's plugin API is experimental and currently distributes local source direct - Root installation, update, removal, security, and contribution guides - One README per plugin -- Portable configuration files for Linear and Workspace Companion QA +- Portable configuration for Linear - CI for formatting, tests, and strict TypeScript checks - MIT license and repository metadata @@ -20,7 +20,7 @@ Paseo's plugin API is experimental and currently distributes local source direct - npm publication or a plugin marketplace package - Automatic installation scripts that enable trusted code without review -- Changing the product behavior of the four plugins +- Changing plugin product behavior beyond the release requirements - Making the GitHub repository public; the owner will do that later ## Chosen approach @@ -38,8 +38,7 @@ Use the existing Bun workspace as the repository root. Paseo installs each `plug - Paseo API changes may break source compatibility. The guides link to current official plugin documentation and describe the API as experimental. - Tailscale and Linear operate outside Paseo. Their guides state exact permissions and avoid live mutation tests. -- QA generation requires provider-specific IDs. The plugin exposes those IDs through daemon environment variables or a user-only configuration file. ## Status -Completed on 2026-08-22. The committed tree passes formatting, 39 focused tests, and all four strict TypeScript checks from a fresh clone. The release is published to the private `Dey11/paseo-plugins` repository with a clean `main` history; the owner will make it public later. +Completed on 2026-08-22. The initial four-plugin release was published with a clean `main` history. Prompt Library and QA Review were removed from the maintained suite on 2026-08-28; the root README and current installation guide define the supported set. diff --git a/docs/usage.md b/docs/usage.md index af3a4d9..d755d27 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -4,20 +4,14 @@ The plugins are independently installable against a Paseo daemon. If a client wa ## Workspace Companion -- Open **Notes** from an agent's right panel or the command center. Edit Markdown in **Write**, inspect it in **Preview**, and save it to the daemon. -- **Refine with agent** sends the current note to the agent whose panel is open. The returned Markdown stays as an unsaved draft until you review and save it. +- Open **Workspace notes** from the workspace **+** menu or the Command Center. Edit Markdown in **Write**, inspect it in **Preview**, and save it to the daemon. +- **Refine with agent** sends the current note to the most recently updated agent in that workspace. The returned Markdown stays as an unsaved draft until you review and save it. - Open **Agent board** from the sidebar. There is one workspace board with **Running**, **Unreviewed**, **Recheck**, **Error**, and **Approved** columns. Drag cards to reorder any column on desktop/web; the order persists across reloads. Finished workspaces can also move among the three review columns, while Running and Error stay tied to live Paseo activity. Placements appear immediately while the daemon saves them. Use **Move to** for a non-drag review-state change, and select the card body to open its workspace. - To archive a workspace on desktop/web, drag its card onto **Archive** in the board header. The board removes it immediately and restores it if Paseo rejects the request. Touch and keyboard users can press **Archive**, then **Confirm archive**, on the card. This archives the actual Paseo workspace and closes its runtime; Archive is not another board status. -- Open **QA review** from an agent panel. **Generate QA plan** reads that agent's conversation and the current workspace changes, then starts a temporary Sol analyst to identify the screens and flows worth manually testing. The panel reports product behavior to exercise, concrete steps, and things to watch for; it does not perform a code review. The temporary analyst archives itself when finished. - -## Prompt Library - -- Open **Prompt library** from the sidebar to create, edit, tag, search, or delete prompts. -- In any composer, open the attachment picker and choose **Prompt library**. Selecting an item attaches a snapshot of its prompt text to that message. ## Linear -- Open **Linear** from an agent's right panel or command center. Search by issue text, page through all matching issues, open an issue, review comments, and open the canonical Linear URL. +- Open **Linear** from the workspace **+** menu or Command Center. Search by issue text, page through all matching issues, open an issue, review comments, and open the canonical Linear URL. - Choosing a status, priority, or comment creates a confirmation card. Nothing is written to Linear until **Confirm update** is pressed. ## Dev Ports diff --git a/plugins/linear/README.md b/plugins/linear/README.md index 6a645d4..1af995c 100644 --- a/plugins/linear/README.md +++ b/plugins/linear/README.md @@ -1,6 +1,6 @@ # Linear -The Linear plugin adds an agent-context panel for: +The Linear plugin adds a workspace panel for: - Searching issues by text - Reading issue descriptions and comments @@ -21,7 +21,7 @@ paseo plugin install "$PWD/plugins/linear" paseo plugin ls ``` -Open **Linear** from an agent tab or the Command Center. +Open **Linear** from the workspace **+** menu or the Command Center. ## Configure the API key diff --git a/plugins/linear/index.ts b/plugins/linear/index.ts index 188c08e..1a9b2f5 100644 --- a/plugins/linear/index.ts +++ b/plugins/linear/index.ts @@ -24,14 +24,14 @@ export default function contribute(plugin: PluginContext) { id: "linear", title: "Linear", icon: "CircleDot", - context: "agent", + context: "workspace", Component: LinearPanel, }); plugin.addCommandCenterItem({ id: "open-linear", title: "Open Linear", icon: "CircleDot", - context: "agent", + context: "workspace", onSelect: ({ openPanel }) => openPanel("linear"), }); return () => {}; diff --git a/plugins/linear/main.client.tsx b/plugins/linear/main.client.tsx index 8a9ff1f..54ee322 100644 --- a/plugins/linear/main.client.tsx +++ b/plugins/linear/main.client.tsx @@ -1,4 +1,4 @@ -import type { PluginAgentPanelProps, PluginTheme } from "@getpaseo/plugin"; +import type { PluginTheme, PluginWorkspacePanelProps } from "@getpaseo/plugin"; import { useRpc } from "@getpaseo/plugin"; import { useInfiniteQuery, useQuery } from "@tanstack/react-query"; import React, { useEffect, useMemo, useState } from "react"; @@ -30,7 +30,7 @@ type Notice = { text: string; }; -export function LinearPanel({ theme, layout }: PluginAgentPanelProps) { +export function LinearPanel({ theme, layout }: PluginWorkspacePanelProps) { const statusRpc = useRpc(LinearStatusRpc); const searchRpc = useRpc(SearchLinearIssuesRpc); const getIssue = useRpc(GetLinearIssueRpc); diff --git a/plugins/plugin-contributions.test.ts b/plugins/plugin-contributions.test.ts index 25d0a98..de8d88d 100644 --- a/plugins/plugin-contributions.test.ts +++ b/plugins/plugin-contributions.test.ts @@ -2,8 +2,6 @@ import { describe, expect, test } from "bun:test"; const contributionFiles = [ "plugins/workspace-companion/index.ts", - "plugins/prompt-library/index.ts", - "plugins/prompt-library/contracts.ts", "plugins/linear/index.ts", "plugins/dev-ports/index.ts", ]; @@ -12,7 +10,6 @@ const documentedLucideIcons = new Set([ "CircleDot", "ListPlus", "PanelsTopLeft", - "Scan", ]); describe("Paseo client contributions", () => { @@ -48,6 +45,22 @@ describe("Paseo client contributions", () => { for (const limit of limits) expect(limit).toBeLessThanOrEqual(200); }); + test("exposes notes and Linear in the workspace tab launcher", async () => { + const expectations = [ + ["plugins/workspace-companion/index.ts", "notes"], + ["plugins/linear/index.ts", "linear"], + ] as const; + + for (const [file, panelId] of expectations) { + const source = await Bun.file(file).text(); + expect(source).toMatch( + new RegExp( + `addWorkspacePanel\\(\\{[\\s\\S]*?id: "${panelId}"[\\s\\S]*?context: "workspace"[\\s\\S]*?\\}\\)`, + ), + ); + } + }); + test("does not execute server-only imports while loading a client entry", async () => { for (const file of contributionFiles.filter((path) => path.endsWith("/index.ts"), diff --git a/plugins/prompt-library/README.md b/plugins/prompt-library/README.md deleted file mode 100644 index e463611..0000000 --- a/plugins/prompt-library/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# Prompt Library - -Prompt Library stores reusable prompts in Paseo and exposes them in two places: - -- A sidebar page for creating, editing, tagging, searching, and deleting prompts. -- The composer attachment picker, where a saved prompt can be attached to any message on the selected host. - -## Install - -From the repository root: - -```bash -bun install --frozen-lockfile -bun run --filter prompt-library typecheck -paseo plugin install "$PWD/plugins/prompt-library" -paseo plugin ls -``` - -Open **Prompt library** in the sidebar or Command Center. In a composer, open the attachment picker and choose **Prompt library**. - -## How attachments work - -Selecting a saved prompt attaches a text snapshot to the current message. Editing the library entry later does not change an attachment already added to a draft or sent to an agent. - -Search matches prompt titles, tags, and content. The attachment picker returns at most 50 matching prompts. - -## Stored data - -Prompts live at: - -```text -$PASEO_HOME/plugin-data/prompt-library/prompts.json -``` - -`PASEO_HOME` defaults to `~/.paseo`. The plugin creates owner-only directories and files and replaces the store atomically. - -The library is local to one daemon. It does not sync prompts between separate daemons. - -## Verify and debug - -```bash -bun test plugins/prompt-library -bun run --filter prompt-library typecheck -paseo plugin reload prompt-library -paseo plugin logs prompt-library -``` diff --git a/plugins/prompt-library/contracts.ts b/plugins/prompt-library/contracts.ts deleted file mode 100644 index 16ab349..0000000 --- a/plugins/prompt-library/contracts.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { - PluginAttachmentSearchPayloadSchema, - defineAttachmentSource, - defineRpc, -} from "@getpaseo/plugin/server"; -import { z } from "zod"; - -export const PromptSchema = z.object({ - id: z.string().min(1), - title: z.string().min(1).max(120), - content: z.string().min(1).max(100_000), - tags: z.array(z.string().min(1).max(40)).max(20), - createdAt: z.string(), - updatedAt: z.string(), -}); -export type SavedPrompt = z.infer; -export const PromptListSchema = z.array(PromptSchema); - -export const ListPromptsRpc = defineRpc({ - name: "prompt-library.list", - input: z.object({ query: z.string().max(200).default("") }), - output: PromptListSchema, -}); - -export const SavePromptRpc = defineRpc({ - name: "prompt-library.save", - input: z.object({ - id: z.string().optional(), - title: z.string().min(1).max(120), - content: z.string().min(1).max(100_000), - tags: z.array(z.string().min(1).max(40)).max(20), - }), - output: PromptSchema, -}); - -export const DeletePromptRpc = defineRpc({ - name: "prompt-library.delete", - input: z.object({ id: z.string().min(1) }), - output: z.object({ deleted: z.boolean() }), -}); - -export const SearchPromptAttachmentsRpc = defineRpc({ - name: "prompt-library.attachments.search", - input: z.object({ query: z.string().max(200).default("") }), - output: PluginAttachmentSearchPayloadSchema, -}); - -export const PromptAttachmentSource = defineAttachmentSource({ - id: "saved-prompts", - title: "Prompt library", - icon: "Blocks", - pickerTitle: "Attach a saved prompt", - searchPlaceholder: "Search titles, tags, and prompt text…", - search: SearchPromptAttachmentsRpc, -}); diff --git a/plugins/prompt-library/index.ts b/plugins/prompt-library/index.ts deleted file mode 100644 index d386482..0000000 --- a/plugins/prompt-library/index.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { PluginContext } from "@getpaseo/plugin"; -import { - DeletePromptRpc, - ListPromptsRpc, - PromptAttachmentSource, - SavePromptRpc, - SearchPromptAttachmentsRpc, -} from "./contracts"; -import { - asAttachment, - deletePrompt, - searchPrompts, - upsertPrompt, -} from "./library"; -import { PromptLibrarySurface } from "./main.client"; -import { mutatePrompts, newPromptId, readPrompts } from "./store.server"; - -export default function contribute(plugin: PluginContext) { - plugin.handle(ListPromptsRpc, async ({ query }) => - searchPrompts(await readPrompts(), query), - ); - plugin.handle(SavePromptRpc, async (input) => { - return mutatePrompts((prompts) => { - const update = upsertPrompt( - prompts, - input, - new Date().toISOString(), - newPromptId, - ); - return { prompts: update.prompts, result: update.prompt }; - }); - }); - plugin.handle(DeletePromptRpc, async ({ id }) => - mutatePrompts((prompts) => { - const update = deletePrompt(prompts, id); - return { - prompts: update.prompts, - result: { deleted: update.deleted }, - shouldWrite: update.deleted, - }; - }), - ); - plugin.handle(SearchPromptAttachmentsRpc, async ({ query }) => ({ - items: searchPrompts(await readPrompts(), query) - .slice(0, 50) - .map(asAttachment), - })); - - plugin.addSurface("prompt-library", PromptLibrarySurface); - plugin.addSidebarItem({ - id: "prompt-library", - title: "Prompt library", - icon: "Blocks", - surface: "prompt-library", - }); - plugin.addAttachmentSource(PromptAttachmentSource); - plugin.addCommandCenterItem({ - id: "open-prompt-library", - title: "Open prompt library", - icon: "Blocks", - context: "global", - onSelect: ({ openSurface }) => openSurface("prompt-library"), - }); - return () => {}; -} diff --git a/plugins/prompt-library/library.test.ts b/plugins/prompt-library/library.test.ts deleted file mode 100644 index cfc71d9..0000000 --- a/plugins/prompt-library/library.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { describe, expect, test } from "bun:test"; -import { - asAttachment, - deletePrompt, - searchPrompts, - upsertPrompt, -} from "./library"; -import type { SavedPrompt } from "./contracts"; - -const prompts: SavedPrompt[] = [ - { - id: "one", - title: "Review API", - content: "Review this API diff", - tags: ["review", "backend"], - createdAt: "2026-01-01", - updatedAt: "2026-01-02", - }, - { - id: "two", - title: "Write release note", - content: "Summarize user-visible changes", - tags: ["writing"], - createdAt: "2026-01-01", - updatedAt: "2026-01-03", - }, -]; - -describe("prompt library", () => { - test("search requires every term across title, tags, and content", () => { - expect( - searchPrompts(prompts, "api backend").map((prompt) => prompt.id), - ).toEqual(["one"]); - expect( - searchPrompts(prompts, "user changes").map((prompt) => prompt.id), - ).toEqual(["two"]); - }); - - test("upsert normalizes tags and preserves creation time", () => { - const result = upsertPrompt( - prompts, - { - id: "one", - title: " Review API ", - content: " Updated ", - tags: ["Review", "review", " API "], - }, - "2026-02-01", - () => "new", - ); - expect(result.prompt.tags).toEqual(["review", "api"]); - expect(result.prompt.createdAt).toBe("2026-01-01"); - }); - - test("deletion and attachment snapshots are deterministic", () => { - expect(deletePrompt(prompts, "one").prompts).toHaveLength(1); - expect(asAttachment(prompts[0]).text).toBe("Review this API diff"); - }); -}); diff --git a/plugins/prompt-library/library.ts b/plugins/prompt-library/library.ts deleted file mode 100644 index 8d45470..0000000 --- a/plugins/prompt-library/library.ts +++ /dev/null @@ -1,67 +0,0 @@ -import type { SavedPrompt } from "./contracts"; - -export function searchPrompts( - prompts: readonly SavedPrompt[], - query: string, -): SavedPrompt[] { - const terms = query.toLocaleLowerCase().trim().split(/\s+/).filter(Boolean); - return [...prompts] - .filter((prompt) => { - const haystack = - `${prompt.title}\n${prompt.tags.join(" ")}\n${prompt.content}`.toLocaleLowerCase(); - return terms.every((term) => haystack.includes(term)); - }) - .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)); -} - -export function upsertPrompt( - prompts: readonly SavedPrompt[], - input: { id?: string; title: string; content: string; tags: string[] }, - now: string, - createId: () => string, -): { prompt: SavedPrompt; prompts: SavedPrompt[] } { - const existing = input.id - ? prompts.find((prompt) => prompt.id === input.id) - : undefined; - if (input.id && !existing) - throw new Error("The saved prompt no longer exists."); - const prompt: SavedPrompt = { - id: existing?.id ?? createId(), - title: input.title.trim(), - content: input.content.trim(), - tags: [ - ...new Set( - input.tags.map((tag) => tag.trim().toLocaleLowerCase()).filter(Boolean), - ), - ], - createdAt: existing?.createdAt ?? now, - updatedAt: now, - }; - return { - prompt, - prompts: [ - prompt, - ...prompts.filter((candidate) => candidate.id !== prompt.id), - ], - }; -} - -export function deletePrompt( - prompts: readonly SavedPrompt[], - id: string, -): { deleted: boolean; prompts: SavedPrompt[] } { - const next = prompts.filter((prompt) => prompt.id !== id); - return { deleted: next.length !== prompts.length, prompts: next }; -} - -export function asAttachment(prompt: SavedPrompt) { - return { - id: prompt.id, - identifier: prompt.title, - title: prompt.title, - subtitle: prompt.tags.length ? prompt.tags.join(" · ") : "Saved prompt", - url: `paseo://prompt-library/${encodeURIComponent(prompt.id)}`, - text: prompt.content, - resourceType: "saved-prompt", - }; -} diff --git a/plugins/prompt-library/main.client.tsx b/plugins/prompt-library/main.client.tsx deleted file mode 100644 index f6b193f..0000000 --- a/plugins/prompt-library/main.client.tsx +++ /dev/null @@ -1,341 +0,0 @@ -import type { PluginSurfaceProps, PluginTheme } from "@getpaseo/plugin"; -import { useRpc } from "@getpaseo/plugin"; -import { useQuery } from "@tanstack/react-query"; -import React, { useEffect, useMemo, useState } from "react"; -import { - Pressable, - ScrollView, - StyleSheet, - Text, - TextInput, - View, -} from "react-native"; -import { - DeletePromptRpc, - ListPromptsRpc, - SavePromptRpc, - type SavedPrompt, -} from "./contracts"; - -export function PromptLibrarySurface({ theme, layout }: PluginSurfaceProps) { - const listPrompts = useRpc(ListPromptsRpc); - const savePrompt = useRpc(SavePromptRpc); - const deletePrompt = useRpc(DeletePromptRpc); - const styles = useStyles(theme, layout.compact); - const [query, setQuery] = useState(""); - const [editingId, setEditingId] = useState(); - const [title, setTitle] = useState(""); - const [content, setContent] = useState(""); - const [tags, setTags] = useState(""); - const [confirmDelete, setConfirmDelete] = useState(null); - const [notice, setNotice] = useState(""); - const [busy, setBusy] = useState(false); - const prompts = useQuery({ - queryKey: ["prompt-library", query], - queryFn: () => listPrompts({ query }), - }); - useEffect(() => { - const timer = setTimeout(() => prompts.refetch(), 180); - return () => clearTimeout(timer); - }, [query]); - - function edit(prompt: SavedPrompt) { - setEditingId(prompt.id); - setTitle(prompt.title); - setContent(prompt.content); - setTags(prompt.tags.join(", ")); - setNotice(""); - } - function clear() { - setEditingId(undefined); - setTitle(""); - setContent(""); - setTags(""); - setConfirmDelete(null); - } - async function save() { - setBusy(true); - setNotice(""); - try { - await savePrompt({ - id: editingId, - title, - content, - tags: tags - .split(",") - .map((tag) => tag.trim()) - .filter(Boolean), - }); - clear(); - await prompts.refetch(); - setNotice( - "Prompt saved. It is now available in the composer attachment picker.", - ); - } catch (error) { - setNotice(message(error)); - } finally { - setBusy(false); - } - } - async function remove(id: string) { - if (confirmDelete !== id) { - setConfirmDelete(id); - return; - } - setBusy(true); - try { - await deletePrompt({ id }); - clear(); - await prompts.refetch(); - setNotice("Prompt deleted."); - } catch (error) { - setNotice(message(error)); - } finally { - setBusy(false); - } - } - - return ( - - - - Prompt library - - Save once, then attach a prompt from any workspace composer. - - - + Page 1 + +
- +
SYS-218 @@ -634,6 +663,15 @@

Make plugin panels match Paseo

+
+ + +
+ + + +
+
+
+

Decisions

+
+ + Keep the board limited to five states +
+
+ + Test the drag interaction on desktop +
+

Follow-ups

+
+ + Verify compact layout on iPhone +