@hachej/boring-workspace 0.1.41 → 0.1.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/app-front.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { jsx as f, jsxs as ye, Fragment as ce } from "react/jsx-runtime";
2
2
  import { useEffect as A, useSyncExternalStore as vr, useMemo as W, useState as O, useCallback as w, useRef as j, useLayoutEffect as Sr } from "react";
3
3
  import { PiChatPanel as br, usePiSessions as yr } from "@hachej/boring-agent/front";
4
- import { aj as Pr, at as ze, au as bn, av as yn, aw as Pn, ax as An, ay as Ve, az as ht, aA as vt, aB as En, aC as Ar, aD as qe, aE as Er, U as un, aF as wr, q as Tr, aG as Nr, u as wn, aH as Rr, ag as Dr, aI as _r } from "./WorkspaceProvider-B6P8ANTL.js";
5
- import { T as Lr, C as Or, r as dn, w as xr, W as fn } from "./WorkspaceLoadingState-BdtTzpsu.js";
4
+ import { aj as Pr, at as ze, au as bn, av as yn, aw as Pn, ax as An, ay as Ve, az as ht, aA as vt, aB as En, aC as Ar, aD as qe, aE as Er, U as un, aF as wr, q as Tr, aG as Nr, u as wn, aH as Rr, ag as Dr, aI as _r } from "./WorkspaceProvider-DkZAxsYo.js";
5
+ import { T as Lr, C as Or, r as dn, w as xr, W as fn } from "./WorkspaceLoadingState-yp4vNmrT.js";
6
6
  import { Sun as Mr, Moon as Cr } from "lucide-react";
7
7
  import { IconButton as Wr, ErrorState as Fr } from "@hachej/boring-ui-kit";
8
8
  function Gr() {
package/dist/testing.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { jsx as Ba } from "react/jsx-runtime";
2
2
  import * as Pa from "react";
3
3
  import { createElement as is, useMemo as wn, useLayoutEffect as us, isValidElement as ss, cloneElement as ds, useSyncExternalStore as Gi } from "react";
4
- import { h as cs, q as fs, o as ps } from "./WorkspaceProvider-B6P8ANTL.js";
4
+ import { h as cs, q as fs, o as ps } from "./WorkspaceProvider-DkZAxsYo.js";
5
5
  import { d as ms } from "./panel-DnvDNQac.js";
6
6
  import * as bs from "react-dom/test-utils";
7
7
  import ka from "react-dom";
package/dist/workspace.js CHANGED
@@ -1,17 +1,17 @@
1
1
  var V = Object.defineProperty;
2
2
  var X = (e, t, r) => t in e ? V(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
3
3
  var T = (e, t, r) => X(e, typeof t != "symbol" ? t + "" : t, r);
4
- import { u as K, p as Q, a as Y, b as Z, D as ee } from "./WorkspaceProvider-B6P8ANTL.js";
5
- import { A as Je, C as Ge, c as Ve, d as Xe, e as Qe, F as Ye, f as Ze, M as et, g as tt, P as rt, h as at, i as nt, j as st, k as ot, R as it, S as lt, l as ct, m as dt, T as ut, U as pt, W as ft, n as mt, o as ht, q as gt, r as bt, s as yt, t as vt, v as xt, w as kt, x as wt, y as Pt, z as St, B as Ct, E as Nt, G as Et, H as Rt, I as Tt, J as It, K as Ot, L as Ft, N as Lt, O as Mt, Q as Bt, V as Wt, X as Dt, Y as Kt, Z as $t, _ as jt, $ as zt, a0 as Ht, a1 as Ut, a2 as _t, a3 as qt, a4 as At, a5 as Jt, a6 as Gt, a7 as Vt, a8 as Xt, a9 as Qt, aa as Yt, ab as Zt, ac as er, ad as tr, ae as rr, af as ar, ag as nr, ah as sr, ai as or, aj as ir, ak as lr, al as cr, am as dr, an as ur, ao as pr, ap as fr, aq as mr, ar as hr, as as gr } from "./WorkspaceProvider-B6P8ANTL.js";
4
+ import { u as K, p as Q, a as Y, b as Z, D as ee } from "./WorkspaceProvider-DkZAxsYo.js";
5
+ import { A as Je, C as Ge, c as Ve, d as Xe, e as Qe, F as Ye, f as Ze, M as et, g as tt, P as rt, h as at, i as nt, j as st, k as ot, R as it, S as lt, l as ct, m as dt, T as ut, U as pt, W as ft, n as mt, o as ht, q as gt, r as bt, s as yt, t as vt, v as xt, w as kt, x as wt, y as Pt, z as St, B as Ct, E as Nt, G as Et, H as Rt, I as Tt, J as It, K as Ot, L as Ft, N as Lt, O as Mt, Q as Bt, V as Wt, X as Dt, Y as Kt, Z as $t, _ as jt, $ as zt, a0 as Ht, a1 as Ut, a2 as _t, a3 as qt, a4 as At, a5 as Jt, a6 as Gt, a7 as Vt, a8 as Xt, a9 as Qt, aa as Yt, ab as Zt, ac as er, ad as tr, ae as rr, af as ar, ag as nr, ah as sr, ai as or, aj as ir, ak as lr, al as cr, am as dr, an as ur, ao as pr, ap as fr, aq as mr, ar as hr, as as gr } from "./WorkspaceProvider-DkZAxsYo.js";
6
6
  import { c as C } from "./utils-B6yFEsav.js";
7
- import { C as yr, T as vr, W as xr, b as kr } from "./WorkspaceLoadingState-BdtTzpsu.js";
7
+ import { C as yr, T as vr, W as xr, b as kr } from "./WorkspaceLoadingState-yp4vNmrT.js";
8
8
  import { jsx as a, jsxs as g, Fragment as te } from "react/jsx-runtime";
9
9
  import { Button as P, Sheet as re, SheetContent as ae, SheetHeader as ne, SheetTitle as se, SheetDescription as oe, EmptyState as ie, Kbd as I, ErrorState as le, IconButton as O } from "@hachej/boring-ui-kit";
10
10
  import { Toaster as Pr, dismissToast as Sr, toast as Cr } from "@hachej/boring-ui-kit";
11
11
  import { useSyncExternalStore as $, useState as N, useEffect as k, useRef as S, useCallback as b, useMemo as w, Suspense as ce, Component as de } from "react";
12
12
  import { C as Er, c as Rr } from "./CodeEditor-DQqOn4xz.js";
13
- import { FileTree as Ir } from "./FileTree-CdvCFi6P.js";
14
- import { MarkdownEditor as Fr } from "./MarkdownEditor-D6W7J3qC.js";
13
+ import { FileTree as Ir } from "./FileTree-CVsvICGP.js";
14
+ import { MarkdownEditor as Fr } from "./MarkdownEditor-BvaGmzWP.js";
15
15
  import { MenuIcon as ue, PanelLeftOpenIcon as pe, PanelLeftCloseIcon as fe, PinIcon as me, CheckIcon as he, CopyIcon as ge } from "lucide-react";
16
16
  import { d as Mr } from "./panel-DnvDNQac.js";
17
17
  function We() {
@@ -1,6 +1,6 @@
1
1
  # Workspace Interfaces
2
2
 
3
- Last updated: 2026-05-02
3
+ Last updated: 2026-06-12
4
4
 
5
5
  `@hachej/boring-workspace` is a workspace UI and bridge package. The app shell owns
6
6
  auth, routing, application persistence, and the concrete chat component.
@@ -1,9 +1,9 @@
1
1
  # Plugin Structure
2
2
 
3
3
  Canonical quick reference for boring-ui plugin layouts. For the full current
4
- contract, see [`PLUGIN_SYSTEM.md`](./PLUGIN_SYSTEM.md). For future hosted/runtime
5
- architecture, see the repo-level
6
- [`docs/runtime-plugin-v2-hot-reload-plan.md`](../../../docs/runtime-plugin-v2-hot-reload-plan.md).
4
+ contract, see [`PLUGIN_SYSTEM.md`](./PLUGIN_SYSTEM.md). For the historical
5
+ hosted/runtime architecture exploration, see the archived repo-level
6
+ [`docs/plans/archive/runtime-plugin-v2-hot-reload-plan.md`](../../../docs/plans/archive/runtime-plugin-v2-hot-reload-plan.md).
7
7
 
8
8
  ## Generated/runtime plugin
9
9
 
@@ -6,8 +6,9 @@ example `PLUGIN_SYSTEM.md §4.5`), so keep headings stable when editing.
6
6
 
7
7
  This document describes the implementation as it exists now. Historical
8
8
  implementation plans live under `packages/workspace/docs/plans/archive/`.
9
- For future generated/hosted runtime-plugin architecture, see the repo-level
10
- `docs/runtime-plugin-v2-hot-reload-plan.md`.
9
+ For the historical generated/hosted runtime-plugin architecture exploration,
10
+ see the archived repo-level
11
+ `docs/plans/archive/runtime-plugin-v2-hot-reload-plan.md`.
11
12
 
12
13
  ## Contents
13
14
 
@@ -27,7 +28,7 @@ For future generated/hosted runtime-plugin architecture, see the repo-level
27
28
  | Term | Definition |
28
29
  | --- | --- |
29
30
  | **App/internal plugin** | Trusted package composed by the app at boot. May export `boring.server`, Fastify routes, agent tools, providers, catalogs, and domain APIs. Server changes require restart/redeploy. |
30
- | **Runtime/generated plugin** | Workspace-local plugin under `.pi/extensions/<id>/`, usually produced by `boring-ui-plugin scaffold`. It is hot-loaded for front/Pi resources, but must not rely on dynamic backend routes. |
31
+ | **Runtime/generated plugin** | Workspace-local plugin under `.pi/extensions/<id>/`, usually produced by `boring-ui-plugin scaffold`. Also called an **external** plugin in trust-model terms. It is hot-loaded for front/Pi resources, but must not rely on dynamic backend routes. |
31
32
  | **Boring plugin package** | Node package with `package.json#boring` and/or `package.json#pi`. App-default packages are declared in `package.json#boring.defaultPluginPackages` or passed to `createWorkspaceAgentServer`. |
32
33
  | **Boring front factory** | Default export of `boring.front`: `(api: BoringFrontAPI) => void | Promise<void>`. Usually created with `definePlugin({ ... })`. |
33
34
  | **Workspace server plugin** | Trusted boot-time server contribution returned by `defineServerPlugin({ ... })` or a compatible object. May include routes, tools, system prompt, Pi resources, and provisioning. |
@@ -35,6 +36,25 @@ For future generated/hosted runtime-plugin architecture, see the repo-level
35
36
  | **Revision** | Per-plugin monotonic integer. It bumps on signature changes and is appended to browser front imports for cache busting. |
36
37
  | **Surface resolver** | Front contribution that maps a typed request such as `open-path` to a panel id/title/params. File opens should route through this path. |
37
38
 
39
+ ### 1.1 Trust model (internal vs external)
40
+
41
+ The two tiers differ by **provenance and trust**, not just lifecycle:
42
+
43
+ | | App/internal plugin | Runtime/generated ("external") plugin |
44
+ | --- | --- | --- |
45
+ | Provenance | App-owned package, composed at boot | Workspace-local `.pi/extensions/`, often agent-generated |
46
+ | Trust | Trusted app module | Trusted **only** as local developer/workspace code |
47
+ | Front | Native React in the host tree | Native React (local trusted context) |
48
+ | Server/routes/tools | Full power: Fastify routes, static `agentTools`, providers, domain APIs | Route-free; no `boring.server`; backend work goes through Pi tools |
49
+ | Reload | Restart/redeploy | `/reload` hot-swaps front + Pi resources |
50
+
51
+ Plugin tools' `execute()` run in the **host Node process and bypass the
52
+ sandbox by design**; plugin loading is local-mode-only (skipped under
53
+ `vercel-sandbox`). Hosted/marketplace plugins — untrusted external code that
54
+ would need iframe fronts and sandbox-proxied tools — are **not implemented**;
55
+ that provenance/permission model is a future phase (see §7 and the archived
56
+ repo-level `docs/plans/archive/runtime-plugin-trust-modes-plan.md`).
57
+
38
58
  ---
39
59
 
40
60
  ## 2. End-to-end behaviour
@@ -241,6 +261,27 @@ boring-ui-plugin verify <name>
241
261
  Do not teach agents to copy `packages/plugin-cli/templates/plugin` for generated runtime
242
262
  plugins. That template is an app/internal publishable package example.
243
263
 
264
+ ### 4.7 Chat slash commands
265
+
266
+ Plugins can contribute **chat `/slash` commands** — a separate surface from the
267
+ command-palette `commands` output. There is no `!` bang-command; the composer
268
+ parses `/name args` only.
269
+
270
+ - **Front registry** (`packages/agent/src/front/slashCommands/registry.ts`):
271
+ `SlashCommand { name, description, kind?, source?, sourcePlugin?, handler }`.
272
+ `kind: 'local'` runs in the browser; `kind: 'skill'` is forwarded to the Pi
273
+ agent as `skill: <name>\n\n<args>`. The chat composer (`PiChatPanel`)
274
+ intercepts `/` input before it reaches the harness.
275
+ - **Server commands** are listed from the harness via
276
+ `GET /api/v1/agent/commands` (consumed by `useServerCommands`) and executed
277
+ via `POST /api/v1/agent/commands/execute` — this route **bypasses the
278
+ harness chat loop**; Pi executes the command natively. `source`
279
+ (`extension`/`prompt`/`skill`) and `sourcePlugin` tag where a command came
280
+ from in the picker.
281
+ - **How a plugin contributes one**: ship a Pi extension/prompt/skill in its
282
+ `package.json#pi` block — Pi-sourced commands appear automatically. No
283
+ harness changes required.
284
+
244
285
  ---
245
286
 
246
287
  ## 5. Key algorithms
@@ -327,7 +368,8 @@ while capturing the front factory.
327
368
  plugin RPC for purity.
328
369
  - Dynamic provider/binding trees for runtime hot-loaded plugins in this PR.
329
370
  - Marketplace signing/provenance/permissions. Those belong to the next runtime
330
- plugin architecture phase.
371
+ plugin architecture phase. Promotion (external → internal) is designed as an
372
+ explicit admin action with pinned provenance + restart — not implemented yet.
331
373
 
332
374
  ---
333
375
 
package/docs/README.md CHANGED
@@ -1,24 +1,87 @@
1
1
  # Workspace Docs
2
2
 
3
- Current package docs live here. Active ownership plans stay in `docs/plans/`.
4
- Older implementation plans live in `docs/plans/archive/`.
5
-
6
- ## Current References
7
-
8
- - `PLUGIN_SYSTEM.md` - current normative spec for the plugin / agent layer:
9
- package manifest fields, public API for front + server authoring,
10
- hot-reload coverage table, prompt-location guidance, and key algorithms.
11
- Code cites it as `Per PLUGIN_SYSTEM.md §X`.
12
- - `PLUGIN_STRUCTURE.md` - quick layout guide for generated/runtime plugins vs
13
- app/internal publishable package plugins.
14
- - `INTERFACES.md` - package boundaries and public abstractions.
15
- - `plans/PLUGIN_OUTPUTS_ISOLATION_PLAN.md` - latest plugin ownership plan.
16
- - `plans/UI_BRIDGE_OWNERSHIP_REFACTOR.md` - UI bridge ownership decision.
17
- - `plans/archive/` - superseded implementation plans.
18
-
19
- ## Rules
20
-
21
- - Keep root package markdown to `README.md` and `CHANGELOG.md`.
22
- - Prefer short current-reference docs over long status reports.
23
- - Move old plans into `plans/archive/` instead of keeping them beside active
24
- ownership plans.
3
+ `@hachej/boring-workspace` is the workspace UI, layout, plugin, and bridge layer
4
+ for boring-ui apps. It composes chat, files, catalogs, editors, and app-specific
5
+ panes into an IDE-style workbench. The app shell owns auth, routing, persistence,
6
+ and the concrete chat component; the workspace owns the layout runtime, the
7
+ plugin registries, and the typed agent-to-browser bridge.
8
+
9
+ This folder holds the current normative docs. Read this index first, then jump to
10
+ the doc that matches your task.
11
+
12
+ ## Architecture at a glance
13
+
14
+ - **Layout runtime** Dockview-based panes (`IdeLayout`, `ChatLayout`,
15
+ `ResponsiveDockviewShell`) mounted by `WorkspaceProvider`. Panels open in the
16
+ center/right/bottom; left-tabs stay docked in the sidebar.
17
+ - **Plugin host** — `WorkspaceProvider` runs `bootstrap(plugins)` to populate the
18
+ panel, command, catalog, and surface-resolver registries. Lazy panel factories
19
+ are auto-wrapped in `React.lazy + Suspense + ErrorBoundary`.
20
+ - **UI bridge** — Agents/servers post `UiCommand` values (`src/shared/ui-bridge.ts`);
21
+ the front-end dispatches them against the workspace runtime over SSE with an
22
+ HTTP poll fallback.
23
+ - **Surface resolvers** Decouple agent "open X" requests from concrete panel
24
+ ids. A `SurfaceOpenRequest { kind, target, meta }` is resolved by plugin
25
+ surface resolvers into panel openings (`src/shared/types/surface.ts`).
26
+ - **Two plugin tiers** — App/internal package plugins (trusted, boot-time, may add
27
+ routes/agent tools/Pi resources) and runtime/generated `.pi/extensions` plugins
28
+ (a.k.a. *external* plugins: hot-reloaded for front/Pi, route-free, and loaded
29
+ only in local/direct-style host runtime contexts — not `vercel-sandbox`). See
30
+ `PLUGIN_SYSTEM.md` §1.1 for the trust model.
31
+
32
+ ## Key abstractions
33
+
34
+ | Abstraction | Where | What it is |
35
+ | --- | --- | --- |
36
+ | `WorkspaceProvider` | `src/front/provider` | Root provider; boots plugins, layout, bridge. |
37
+ | `definePlugin()` | `@hachej/boring-workspace/plugin` | Declarative front plugin: panels, leftTabs, commands, catalogs, bindings, providers, surfaceResolvers. |
38
+ | `defineServerPlugin()` | `@hachej/boring-workspace/server` | Trusted boot-time server plugin: routes, agent tools, system prompt, Pi packages, provisioning. |
39
+ | `PaneProps<T>` | `src/shared/types/panel.ts` | Props every panel/left-tab component receives (`params`, `api`, `containerApi`). |
40
+ | `UiCommand` / `UiBridge` | `src/shared/ui-bridge.ts` | Typed agent→browser command contract. |
41
+ | `SurfaceOpenRequest` | `src/shared/types/surface.ts` | Domain open request resolved to a panel. |
42
+ | `BoringPluginAssetManager` | `src/server/agentPlugins` | Scans plugin dirs, hashes signatures, emits load/unload/error events, backs `/api/v1/agent-plugins`. |
43
+
44
+ ## Architectural decisions
45
+
46
+ - **App shell owns auth/routing/persistence/chat; workspace owns chrome.** Keeps
47
+ the workspace package reusable and the chat component injected, not hardcoded.
48
+ - **Front/shared workspace code does not value-import `@hachej/boring-agent`.** The
49
+ dependency is inverted via the injected `chatPanel`, so the workbench builds and
50
+ ships without the agent package. Only `src/app/*` composition may import
51
+ documented agent server APIs.
52
+ - **Agents open domain targets through `openSurface`, not `openPanel`.** Surface
53
+ resolvers map requests to panels so workspace chrome never hardcodes plugin
54
+ panel ids or domain rules. Use `openPanel` only when the caller intentionally
55
+ names a concrete panel.
56
+ - **Plugin data APIs live under the owning plugin.** There is no shared
57
+ `front/data` compatibility layer; e.g. the filesystem client/hooks/events are
58
+ plugin-owned (`src/plugins/filesystemPlugin/front/data`).
59
+ - **Generated runtime plugins stay route-free; server changes are boot-time only.**
60
+ `/reload` refreshes front/Pi resources and tolerates per-plugin failures, but
61
+ does not hot-wire Fastify routes or agent tools. Server-file drift surfaces a
62
+ `requiresRestart` warning.
63
+ - **Chat-first boot.** `WorkspaceAgentFront` mounts immediately while readiness
64
+ warms in the background; workbench surfaces are locally gated by warmup state.
65
+ - **Style isolation.** Workspace owns public `--boring-*` tokens and Tailwind base
66
+ reset; agent consumes them under `[data-boring-agent]`. See
67
+ [`docs/TAILWIND-V4-STYLE-ISOLATION.md`](../../../docs/TAILWIND-V4-STYLE-ISOLATION.md).
68
+
69
+ ## Docs
70
+
71
+ Authoring:
72
+ - [`PLUGIN_STRUCTURE.md`](./PLUGIN_STRUCTURE.md) — quick layout guide for
73
+ generated/runtime plugins vs app/internal publishable package plugins.
74
+ - [`PLUGIN_SYSTEM.md`](./PLUGIN_SYSTEM.md) — normative spec for the plugin/agent
75
+ layer: manifest fields, front + server authoring API, hot-reload coverage,
76
+ and key algorithms. Code and tests cite it as `Per PLUGIN_SYSTEM.md §X`, so its
77
+ section numbering is stable.
78
+
79
+ Boundaries / contracts:
80
+ - [`INTERFACES.md`](./INTERFACES.md) — package boundaries, core contracts, and
81
+ ownership rules across `src/front`, `src/server`, `src/shared`, `src/plugins`,
82
+ and `src/app`.
83
+
84
+ History:
85
+ - [`plans/archive/`](./plans/archive/) — superseded implementation plans and specs
86
+ kept for historical context. Not normative; current behavior is described in the
87
+ docs above and verified against source.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hachej/boring-workspace",
3
- "version": "0.1.41",
3
+ "version": "0.1.42",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Workspace UI, plugin, and bridge package for composing chat, files, catalogs, editors, and app-specific panes.",
@@ -135,9 +135,9 @@
135
135
  "tailwind-merge": "^2.0.0",
136
136
  "zod": "^3.23.0",
137
137
  "zustand": "^5.0.0",
138
- "@hachej/boring-agent": "0.1.41",
139
- "@hachej/boring-ui-plugin-cli": "0.1.41",
140
- "@hachej/boring-ui-kit": "0.1.41"
138
+ "@hachej/boring-agent": "0.1.42",
139
+ "@hachej/boring-ui-kit": "0.1.42",
140
+ "@hachej/boring-ui-plugin-cli": "0.1.42"
141
141
  },
142
142
  "devDependencies": {
143
143
  "@tailwindcss/postcss": "^4.0.0",
File without changes