@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.
- package/README.md +36 -34
- package/dist/{FileTree-Dvaud3jU.js → FileTree-DHVB9rpk.js} +15 -15
- package/dist/{MarkdownEditor-sLkqTXDj.js → MarkdownEditor-L1KDH0bM.js} +1 -1
- package/dist/{WorkspaceLoadingState-zLzh1tGc.js → WorkspaceLoadingState-DYDxUYnx.js} +114 -110
- package/dist/WorkspaceProvider-CDPaAO5u.js +5971 -0
- package/dist/app-front.d.ts +94 -107
- package/dist/app-front.js +243 -233
- package/dist/app-server.d.ts +130 -15
- package/dist/app-server.js +1569 -304
- package/dist/{bootstrapServer-BreQ9QBc.d.ts → createInMemoryBridge-BDxDzihm.d.ts} +11 -26
- package/dist/manifest-CyNNdfYz.d.ts +58 -0
- package/dist/plugin.d.ts +199 -0
- package/dist/plugin.js +300 -0
- package/dist/server.d.ts +239 -4
- package/dist/server.js +901 -78
- package/dist/shared.d.ts +4 -112
- package/dist/surface-COYagY2m.d.ts +111 -0
- package/dist/testing.d.ts +19 -1
- package/dist/testing.js +2 -2
- package/dist/{agent-tool-DEtfQPVB.d.ts → ui-bridge-Gfh1MMgl.d.ts} +30 -30
- package/dist/workspace.css +36 -0
- package/dist/workspace.d.ts +165 -120
- package/dist/workspace.js +330 -377
- package/docs/INTERFACES.md +9 -9
- package/docs/PLUGIN_STRUCTURE.md +39 -145
- package/docs/PLUGIN_SYSTEM.md +355 -0
- package/docs/README.md +6 -1
- package/docs/plans/README.md +1 -0
- package/docs/plans/archive/HOT_RELOADABLE_AGENT_PLUGINS_PLAN.md +218 -0
- package/docs/plans/archive/RELOAD_PLUGGABILITY_PLAN.md +174 -0
- package/docs/plans/archive/UNIFIED_PLUGIN_SYSTEM_PLAN.md +769 -0
- package/package.json +11 -5
- package/dist/CommandPalette-CJHuTJlD.js +0 -5716
- package/docs/bridge.md +0 -135
- package/docs/panels.md +0 -102
- package/docs/plugins.md +0 -158
- /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.
|
|
File without changes
|