@hachej/boring-workspace 0.1.17 → 0.1.18

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.
Files changed (37) hide show
  1. package/README.md +36 -34
  2. package/dist/{FileTree-Dvaud3jU.js → FileTree-DHVB9rpk.js} +15 -15
  3. package/dist/{MarkdownEditor-sLkqTXDj.js → MarkdownEditor-L1KDH0bM.js} +1 -1
  4. package/dist/{WorkspaceLoadingState-zLzh1tGc.js → WorkspaceLoadingState-DYDxUYnx.js} +114 -110
  5. package/dist/WorkspaceProvider-CDPaAO5u.js +5971 -0
  6. package/dist/app-front.d.ts +94 -107
  7. package/dist/app-front.js +243 -233
  8. package/dist/app-server.d.ts +130 -15
  9. package/dist/app-server.js +1569 -304
  10. package/dist/{bootstrapServer-BreQ9QBc.d.ts → createInMemoryBridge-BDxDzihm.d.ts} +11 -26
  11. package/dist/manifest-CyNNdfYz.d.ts +58 -0
  12. package/dist/plugin.d.ts +199 -0
  13. package/dist/plugin.js +300 -0
  14. package/dist/server.d.ts +239 -4
  15. package/dist/server.js +901 -78
  16. package/dist/shared.d.ts +4 -112
  17. package/dist/surface-COYagY2m.d.ts +111 -0
  18. package/dist/testing.d.ts +19 -1
  19. package/dist/testing.js +2 -2
  20. package/dist/{agent-tool-DEtfQPVB.d.ts → ui-bridge-Gfh1MMgl.d.ts} +30 -30
  21. package/dist/workspace.css +36 -0
  22. package/dist/workspace.d.ts +165 -120
  23. package/dist/workspace.js +330 -377
  24. package/docs/INTERFACES.md +9 -9
  25. package/docs/PLUGIN_STRUCTURE.md +39 -145
  26. package/docs/PLUGIN_SYSTEM.md +355 -0
  27. package/docs/README.md +6 -1
  28. package/docs/plans/README.md +1 -0
  29. package/docs/plans/archive/HOT_RELOADABLE_AGENT_PLUGINS_PLAN.md +218 -0
  30. package/docs/plans/archive/RELOAD_PLUGGABILITY_PLAN.md +174 -0
  31. package/docs/plans/archive/UNIFIED_PLUGIN_SYSTEM_PLAN.md +769 -0
  32. package/package.json +11 -5
  33. package/dist/CommandPalette-CJHuTJlD.js +0 -5716
  34. package/docs/bridge.md +0 -135
  35. package/docs/panels.md +0 -102
  36. package/docs/plugins.md +0 -158
  37. /package/docs/plans/{MACRO_PLUGIN_GENERIC_HELPERS_AUDIT.md → archive/MACRO_PLUGIN_GENERIC_HELPERS_AUDIT.md} +0 -0
package/docs/bridge.md DELETED
@@ -1,135 +0,0 @@
1
- > boring-ui agents use exec_ui to open panels and interact with the workspace. Ask boring-ui to wire up a new surface.
2
-
3
- # UI Bridge
4
-
5
- The UI bridge is the typed pubsub channel between the agent backend and the workspace frontend. The agent calls `exec_ui` (a tool) to post commands; the frontend dispatches them against the live workspace runtime.
6
-
7
- ## Table of Contents
8
-
9
- - [Opening a panel from the agent](#opening-a-panel-from-the-agent)
10
- - [openSurface vs openPanel](#opensurface-vs-openpanel)
11
- - [Reading current UI state](#reading-current-ui-state)
12
- - [Surface resolvers](#surface-resolvers)
13
- - [Posting from server code](#posting-from-server-code)
14
- - [Frontend event bus](#frontend-event-bus)
15
-
16
- ---
17
-
18
- ## Opening a panel from the agent
19
-
20
- Use `exec_ui` with `kind: "openSurface"`:
21
-
22
- ```json
23
- {
24
- "kind": "openSurface",
25
- "params": {
26
- "kind": "my-plugin.open",
27
- "target": "item-123",
28
- "meta": { "title": "My Item" }
29
- }
30
- }
31
- ```
32
-
33
- The workspace routes this to the plugin's `surface-resolver` output, which maps the `kind` to a concrete panel open call.
34
-
35
- ---
36
-
37
- ## openSurface vs openPanel
38
-
39
- | method | use when |
40
- |---|---|
41
- | `openSurface` | you want plugin resolver selection — preferred for domain targets |
42
- | `openPanel` | you intentionally name the concrete panel id |
43
-
44
- **Prefer `openSurface`.** It keeps the agent decoupled from panel ids and lets the plugin control routing.
45
-
46
- Open a file in the editor (built-in surface):
47
-
48
- ```json
49
- {
50
- "kind": "openSurface",
51
- "params": {
52
- "kind": "workspace.open.path",
53
- "target": "src/index.ts"
54
- }
55
- }
56
- ```
57
-
58
- ---
59
-
60
- ## Reading current UI state
61
-
62
- Use `get_ui_state` before `openPanel` to discover which panel components are registered, or to check what the user is currently viewing:
63
-
64
- ```json
65
- // tool call: get_ui_state (no params)
66
- // returns:
67
- {
68
- "workbenchOpen": true,
69
- "drawerOpen": false,
70
- "openTabs": [{ "id": "...", "title": "...", "params": {} }],
71
- "activeTab": "tab-id-or-null",
72
- "activeFile": "src/index.ts-or-null",
73
- "availablePanels": ["code-editor", "chart-canvas", "..."]
74
- }
75
- ```
76
-
77
- `availablePanels` lists every component id registered by the host — use these with `exec_ui openPanel`.
78
-
79
- ---
80
-
81
- ## Surface resolvers
82
-
83
- Register a surface resolver in your plugin to map `SurfaceOpenRequest` kinds to panel opens:
84
-
85
- ```ts
86
- import { defineFrontPlugin, type SurfacePanelResolution } from '@boring/workspace'
87
-
88
- defineFrontPlugin({
89
- outputs: [
90
- {
91
- type: 'surface-resolver',
92
- resolve(req): SurfacePanelResolution | null {
93
- if (req.kind === 'my-plugin.open') {
94
- return {
95
- panelId: 'my-panel',
96
- params: { id: req.target },
97
- }
98
- }
99
- return null
100
- },
101
- },
102
- ],
103
- })
104
- ```
105
-
106
- ---
107
-
108
- ## Posting from server code
109
-
110
- From a Fastify route or server plugin:
111
-
112
- ```ts
113
- import { postUiCommand } from '@boring/workspace/server'
114
-
115
- await postUiCommand(workspaceId, {
116
- kind: 'openSurface',
117
- params: { kind: 'my-plugin.open', target: 'item-123' },
118
- })
119
- ```
120
-
121
- ---
122
-
123
- ## Frontend event bus
124
-
125
- Subscribe to workspace events on the frontend:
126
-
127
- ```ts
128
- import { events, workspaceEvents } from '@boring/workspace'
129
-
130
- events.on(workspaceEvents.panelOpened, (panel) => {
131
- console.log('panel opened', panel.id)
132
- })
133
- ```
134
-
135
- See [plugins.md](./plugins.md) to register a surface resolver in your plugin.
package/docs/panels.md DELETED
@@ -1,102 +0,0 @@
1
- > boring-ui can create panel components. Ask it to build one for your domain.
2
-
3
- # Panels
4
-
5
- Panels are React components rendered inside the workspace dockview layout. They receive `PaneProps<T>` and can be opened programmatically by the agent or user.
6
-
7
- ## Table of Contents
8
-
9
- - [Defining a panel](#defining-a-panel)
10
- - [Panel component API](#panel-component-api)
11
- - [Placement](#placement)
12
- - [Auto-lazy loading](#auto-lazy-loading)
13
- - [Opening panels](#opening-panels)
14
-
15
- ---
16
-
17
- ## Defining a panel
18
-
19
- ```ts
20
- import { definePanel } from '@boring/workspace'
21
-
22
- export const myPanel = definePanel({
23
- id: 'my-panel',
24
- title: 'My Panel',
25
- placement: 'center',
26
- // Zero-arg factory → auto-detected as lazy (code-split)
27
- component: () => import('./MyPane').then(m => ({ default: m.MyPane })),
28
- })
29
- ```
30
-
31
- ---
32
-
33
- ## Panel component API
34
-
35
- Panel components receive `PaneProps<T>`:
36
-
37
- ```ts
38
- import type { PaneProps } from '@boring/workspace'
39
-
40
- interface Params { id?: string; query?: string }
41
-
42
- export function MyPane({ params, api, containerApi }: PaneProps<Params>) {
43
- // params — data passed when the panel is opened
44
- // api — DockviewPanelApi (close, setTitle, onDidParametersChange, …)
45
- // containerApi — DockviewApi (addPanel, fromJSON, …)
46
- }
47
- ```
48
-
49
- React to parameter changes (agent re-opens with new params):
50
-
51
- ```ts
52
- useEffect(() => {
53
- const disposable = api.onDidParametersChange(() => {
54
- // params updated
55
- })
56
- return () => disposable.dispose()
57
- }, [api])
58
- ```
59
-
60
- ---
61
-
62
- ## Placement
63
-
64
- | value | where |
65
- |---|---|
66
- | `center` | main editor area |
67
- | `right` | right sidebar |
68
- | `bottom` | bottom panel |
69
-
70
- ---
71
-
72
- ## Auto-lazy loading
73
-
74
- **Do not set `lazy: true`.** The registry auto-detects it:
75
-
76
- - Zero-arg function `() => import(...)` → lazy (code-split, loaded on first open)
77
- - Component `(props) => JSX` → eager (loaded at startup)
78
-
79
- ---
80
-
81
- ## Opening panels
82
-
83
- From the agent via exec_ui (see [bridge.md](./bridge.md)):
84
-
85
- ```json
86
- {
87
- "kind": "openSurface",
88
- "params": { "kind": "my-plugin.open", "target": "item-123" }
89
- }
90
- ```
91
-
92
- From React code directly:
93
-
94
- ```ts
95
- containerApi.addPanel({
96
- id: 'my-panel',
97
- component: 'my-panel',
98
- params: { id: 'item-123' },
99
- })
100
- ```
101
-
102
- See [plugins.md](./plugins.md) for the full plugin API.
package/docs/plugins.md DELETED
@@ -1,158 +0,0 @@
1
- > boring-ui can create plugins. Ask it to build one for your use case.
2
-
3
- # Plugins
4
-
5
- Plugins are the primary extension point. A plugin contributes panels, commands, catalogs, left-tabs, and surface resolvers to the workspace shell.
6
-
7
- **Key capabilities:**
8
- - **Panels** — center/right/bottom panes opened programmatically by the agent or user
9
- - **Commands** — entries in the command palette (`cmd+k`)
10
- - **Left tabs** — persistent tabs in the left sidebar
11
- - **Catalogs** — data explorer tabs with search + row selection
12
- - **Surface resolvers** — map agent-emitted `openSurface` requests to concrete panel opens
13
- - **Bindings / providers** — React components mounted in the provider tree
14
-
15
- ## Table of Contents
16
-
17
- - [Minimal plugin](#minimal-plugin)
18
- - [Output types](#output-types)
19
- - [System prompt](#system-prompt)
20
- - [Composing plugins](#composing-plugins)
21
- - [Server plugins](#server-plugins)
22
- - [Registering with the shell](#registering-with-the-shell)
23
- - [Plugin folder layout](#plugin-folder-layout)
24
- - [Invariants](#invariants)
25
-
26
- ---
27
-
28
- ## Minimal plugin
29
-
30
- ```ts
31
- import { defineFrontPlugin, definePanel } from '@boring/workspace'
32
-
33
- export const myPlugin = defineFrontPlugin({
34
- id: 'my-plugin',
35
- label: 'My Plugin',
36
- systemPrompt: "You can open the widget panel with the 'open-panel' tool.",
37
- outputs: [
38
- {
39
- type: 'panel',
40
- panel: definePanel({
41
- id: 'my-widget',
42
- title: 'Widget',
43
- placement: 'center',
44
- component: () => import('./WidgetPane').then(m => ({ default: m.WidgetPane })),
45
- }),
46
- },
47
- ],
48
- })
49
- ```
50
-
51
- ---
52
-
53
- ## Output types
54
-
55
- | type | contributes |
56
- |---|---|
57
- | `panel` | a center/right/bottom pane opened programmatically |
58
- | `left-tab` | a persistent tab in the left sidebar |
59
- | `command` | an entry in the command palette |
60
- | `catalog` | a data explorer tab with search + row selection |
61
- | `surface-resolver` | maps a `SurfaceOpenRequest` kind → panel id |
62
- | `binding` | a React component mounted in the provider tree |
63
- | `provider` | same as binding but receives `apiBaseUrl`, `authHeaders`, etc. |
64
-
65
- ---
66
-
67
- ## System prompt
68
-
69
- The `systemPrompt` field on a plugin is injected into the agent's context. Use it to teach the agent what panels exist and when to open them.
70
-
71
- ```ts
72
- defineFrontPlugin({
73
- id: 'contract-review',
74
- systemPrompt: `
75
- You can open the contract review panel when the user asks to review a contract.
76
- Use exec_ui with kind "openSurface" and kind "contract-review.open".
77
- `,
78
- ...
79
- })
80
- ```
81
-
82
- All plugin `systemPrompt` strings are concatenated and passed as `systemPromptAppend` to the agent harness.
83
-
84
- ---
85
-
86
- ## Composing plugins
87
-
88
- ```ts
89
- import { composePlugins } from '@boring/workspace'
90
-
91
- export const myPlugin = composePlugins({
92
- id: 'my-plugin',
93
- plugins: [panelsPlugin, catalogPlugin, surfacePlugin],
94
- })
95
- ```
96
-
97
- `composePlugins` flattens child panels, commands, catalogs, bindings, and outputs into one `WorkspaceFrontPlugin`. Child ownership adopts to the parent plugin id by default.
98
-
99
- ---
100
-
101
- ## Server plugins
102
-
103
- Server plugins contribute agent tools, routes, and pi package declarations:
104
-
105
- ```ts
106
- import { defineServerPlugin } from '@boring/workspace/server'
107
-
108
- export const myServerPlugin = defineServerPlugin({
109
- id: 'my-plugin',
110
- tools: [myAgentTool],
111
- promptText: 'You have access to the my_tool tool.',
112
- })
113
- ```
114
-
115
- Compose server plugins with `composeServerPlugins()`.
116
-
117
- ---
118
-
119
- ## Registering with the shell
120
-
121
- ```tsx
122
- import { WorkspaceAgentFront } from '@boring/workspace'
123
-
124
- <WorkspaceAgentFront plugins={[myPlugin]} />
125
- ```
126
-
127
- ---
128
-
129
- ## Plugin folder layout
130
-
131
- ```
132
- src/plugins/myPlugin/
133
- front/
134
- index.tsx ← defineFrontPlugin(), public front exports
135
- panels.tsx ← panel definitions
136
- surfaceResolver.ts ← openSurface kind → panel resolution
137
- server/
138
- index.ts ← defineServerPlugin(), public server exports
139
- tools.ts ← agent tools
140
- shared/
141
- constants.ts ← plugin id, surface kinds
142
- types.ts ← platform-neutral shared types
143
- ```
144
-
145
- Use only the files the plugin needs.
146
-
147
- ---
148
-
149
- ## Invariants
150
-
151
- ```bash
152
- pnpm --filter @boring/workspace run lint:plugin-invariants
153
- ```
154
-
155
- Rejects cross-layer imports, legacy file names, and plugin-domain imports from workspace chrome.
156
-
157
- See [panels.md](./panels.md) for panel component API.
158
- See [bridge.md](./bridge.md) for how to open panels from the agent.