@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/README.md
CHANGED
|
@@ -54,20 +54,17 @@ function App() {
|
|
|
54
54
|
Add a panel in 8 lines:
|
|
55
55
|
|
|
56
56
|
```ts
|
|
57
|
-
import {
|
|
57
|
+
import { definePlugin } from "@hachej/boring-workspace/plugin"
|
|
58
58
|
|
|
59
|
-
export const myPanelPlugin =
|
|
59
|
+
export const myPanelPlugin = definePlugin({
|
|
60
60
|
id: "my-panel",
|
|
61
61
|
label: "My Panel",
|
|
62
|
-
|
|
62
|
+
panels: [
|
|
63
63
|
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
placement: "center",
|
|
69
|
-
component: () => import("./WidgetPane").then(m => ({ default: m.WidgetPane })),
|
|
70
|
-
}),
|
|
64
|
+
id: "my-widget",
|
|
65
|
+
label: "Widget",
|
|
66
|
+
placement: "center",
|
|
67
|
+
component: () => import("./WidgetPane").then(m => ({ default: m.WidgetPane })),
|
|
71
68
|
},
|
|
72
69
|
],
|
|
73
70
|
})
|
|
@@ -153,14 +150,15 @@ UiBridgeClient receives → dispatches to FileTree plugin → expands node + foc
|
|
|
153
150
|
|
|
154
151
|
| Import | Environment | What You Get |
|
|
155
152
|
|--------|-------------|--------------|
|
|
156
|
-
| `@hachej/boring-workspace` | Browser | `WorkspaceProvider`, `IdeLayout`,
|
|
153
|
+
| `@hachej/boring-workspace` | Browser | `WorkspaceProvider`, `IdeLayout`, built-in layout primitives |
|
|
154
|
+
| `@hachej/boring-workspace/plugin` | Browser | `definePlugin()` and browser-safe plugin authoring types |
|
|
157
155
|
| `@hachej/boring-workspace/server` | Node | `defineServerPlugin()`, server routes, UI tools, Pi package helpers |
|
|
158
156
|
| `@hachej/boring-workspace/shared` | Any | `PaneProps`, `SurfaceOpenRequest`, `UiCommand`, plugin types |
|
|
159
157
|
| `@hachej/boring-workspace/events` | Any | Typed event bus for bridge communication |
|
|
160
158
|
| `@hachej/boring-workspace/charts` | Browser | Recharts wrappers for data visualization |
|
|
161
159
|
| `@hachej/boring-workspace/testing` | Browser | Test utilities and mock providers |
|
|
162
160
|
| `@hachej/boring-workspace/app/front` | Browser | App composition: `WorkspaceAgentFront` |
|
|
163
|
-
| `@hachej/boring-workspace/app/server` | Node | App composition: `
|
|
161
|
+
| `@hachej/boring-workspace/app/server` | Node | App composition: `createWorkspaceAgentServer` |
|
|
164
162
|
| `@hachej/boring-workspace/globals.css` | Browser | Global CSS for the workspace chrome |
|
|
165
163
|
|
|
166
164
|
---
|
|
@@ -176,35 +174,31 @@ UiBridgeClient receives → dispatches to FileTree plugin → expands node + foc
|
|
|
176
174
|
| `surface-resolver` | Maps `exec_ui` → panel | `openFile` → editor panel with path |
|
|
177
175
|
| `binding` | React context in provider tree | Theme, auth, workspace-scoped state |
|
|
178
176
|
| `provider` | Binding + `apiBaseUrl` injection | Server-side plugin config passed to front |
|
|
179
|
-
| `agent-tool` |
|
|
177
|
+
| `agent-tool` | Static agent tool via server plugin | `deploy`, `test`, `lint` commands |
|
|
180
178
|
|
|
181
179
|
### Writing a Plugin
|
|
182
180
|
|
|
183
181
|
```ts
|
|
184
|
-
import {
|
|
182
|
+
import { definePlugin } from "@hachej/boring-workspace/plugin"
|
|
185
183
|
import type { PaneProps } from "@hachej/boring-workspace"
|
|
186
184
|
|
|
187
|
-
export const statusPlugin =
|
|
185
|
+
export const statusPlugin = definePlugin({
|
|
188
186
|
id: "build-status",
|
|
189
187
|
label: "Build Status",
|
|
190
|
-
|
|
188
|
+
leftTabs: [
|
|
191
189
|
{
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
placement: "left",
|
|
197
|
-
component: () => import("./StatusTab").then(m => ({ default: m.StatusTab })),
|
|
198
|
-
}),
|
|
190
|
+
id: "build-status-tab",
|
|
191
|
+
title: "Build",
|
|
192
|
+
panelId: "build-status-tab",
|
|
193
|
+
component: () => import("./StatusTab").then(m => ({ default: m.StatusTab })),
|
|
199
194
|
},
|
|
195
|
+
],
|
|
196
|
+
panels: [
|
|
200
197
|
{
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
placement: "bottom",
|
|
206
|
-
component: () => import("./BuildDetails").then(m => ({ default: m.BuildDetails })),
|
|
207
|
-
}),
|
|
198
|
+
id: "build-details",
|
|
199
|
+
label: "Build Details",
|
|
200
|
+
placement: "bottom",
|
|
201
|
+
component: () => import("./BuildDetails").then(m => ({ default: m.BuildDetails })),
|
|
208
202
|
},
|
|
209
203
|
],
|
|
210
204
|
})
|
|
@@ -219,14 +213,22 @@ function StatusTab({ params, api, containerApi }: PaneProps<{}>) {
|
|
|
219
213
|
|
|
220
214
|
### Server Plugins
|
|
221
215
|
|
|
216
|
+
Server plugins are boot-time/static composition. Hot-reloadable `.pi/extensions` agent tools should use Pi extensions instead.
|
|
217
|
+
|
|
222
218
|
```ts
|
|
223
219
|
import { defineServerPlugin } from "@hachej/boring-workspace/server"
|
|
224
220
|
|
|
225
221
|
export const statusServerPlugin = defineServerPlugin({
|
|
226
222
|
id: "build-status",
|
|
227
|
-
|
|
228
|
-
routes:
|
|
229
|
-
|
|
223
|
+
agentTools: [buildTool], // Agent tools
|
|
224
|
+
routes: async (app) => { // Fastify plugin function
|
|
225
|
+
app.register(statusRoutes, { prefix: "/build-status" })
|
|
226
|
+
},
|
|
227
|
+
provisioning: {
|
|
228
|
+
templateDirs: [
|
|
229
|
+
{ id: "build-status-seed", path: seedBuildDir, target: "." },
|
|
230
|
+
],
|
|
231
|
+
},
|
|
230
232
|
})
|
|
231
233
|
```
|
|
232
234
|
|
|
@@ -279,7 +281,7 @@ export const statusServerPlugin = defineServerPlugin({
|
|
|
279
281
|
| Blank panel / white screen | Lazy component threw | Check `PluginErrorBoundary` — inspect console |
|
|
280
282
|
| `UiBridge not connected` | Backend not running | Verify `apiBaseUrl` and backend endpoint |
|
|
281
283
|
| Commands not arriving | SSE blocked by proxy | Use `?poll=true` on `/api/v1/ui/commands/next` |
|
|
282
|
-
| Plugin not loading | Missing `
|
|
284
|
+
| Plugin not loading | Missing `definePlugin` wrapper or `boring.front` manifest entry | Package front plugins must default-export `definePlugin({ ... })` and declare `boring.front` |
|
|
283
285
|
| Duplicate panel IDs | Two plugins register same ID | Rename one panel's `id` field |
|
|
284
286
|
|
|
285
287
|
---
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as i, jsxs as C } from "react/jsx-runtime";
|
|
2
|
-
import { useRef as w, useEffect as
|
|
2
|
+
import { useRef as w, useEffect as I, useMemo as P, useCallback as x, createContext as H, useContext as L } from "react";
|
|
3
3
|
import { Tree as q } from "react-arborist";
|
|
4
|
-
import { FolderOpenIcon as z, FolderIcon as B, ChevronRightIcon as E, Loader2Icon as
|
|
5
|
-
import {
|
|
6
|
-
import { Input as
|
|
4
|
+
import { FolderOpenIcon as z, FolderIcon as B, ChevronRightIcon as E, Loader2Icon as K } from "lucide-react";
|
|
5
|
+
import { I as Y } from "./WorkspaceProvider-CDPaAO5u.js";
|
|
6
|
+
import { Input as G } from "@hachej/boring-ui-kit";
|
|
7
7
|
import { c as v } from "./utils-B6yFEsav.js";
|
|
8
8
|
const T = /* @__PURE__ */ new Set(), A = H({
|
|
9
9
|
onContextMenu: void 0,
|
|
@@ -12,14 +12,14 @@ const T = /* @__PURE__ */ new Set(), A = H({
|
|
|
12
12
|
onSubmitEdit: void 0,
|
|
13
13
|
onCancelEdit: void 0
|
|
14
14
|
});
|
|
15
|
-
function
|
|
15
|
+
function J({
|
|
16
16
|
initialValue: n,
|
|
17
17
|
onSubmit: p,
|
|
18
18
|
onCancel: h,
|
|
19
19
|
isDraft: c
|
|
20
20
|
}) {
|
|
21
21
|
const t = w(null), u = w(!1);
|
|
22
|
-
|
|
22
|
+
I(() => {
|
|
23
23
|
const e = t.current;
|
|
24
24
|
if (e)
|
|
25
25
|
if (e.focus(), !c && n.includes(".")) {
|
|
@@ -36,7 +36,7 @@ function G({
|
|
|
36
36
|
!e || e === n ? h() : p(e);
|
|
37
37
|
};
|
|
38
38
|
return /* @__PURE__ */ i(
|
|
39
|
-
|
|
39
|
+
G,
|
|
40
40
|
{
|
|
41
41
|
ref: t,
|
|
42
42
|
type: "text",
|
|
@@ -54,7 +54,7 @@ function G({
|
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
function Q({ node: n, style: p, dragHandle: h }) {
|
|
57
|
-
const { onContextMenu: c, editing: t, pendingPaths: u, onSubmitEdit: l, onCancelEdit: e } = L(A), o = n.data, f = o.kind === "dir", d = (t == null ? void 0 : t.path) === o.path, N = u.has(o.path), b = f ? n.isOpen ? z : B :
|
|
57
|
+
const { onContextMenu: c, editing: t, pendingPaths: u, onSubmitEdit: l, onCancelEdit: e } = L(A), o = n.data, f = o.kind === "dir", d = (t == null ? void 0 : t.path) === o.path, N = u.has(o.path), b = f ? n.isOpen ? z : B : Y(o.name || "untitled");
|
|
58
58
|
return /* @__PURE__ */ C(
|
|
59
59
|
"div",
|
|
60
60
|
{
|
|
@@ -95,7 +95,7 @@ function Q({ node: n, style: p, dragHandle: h }) {
|
|
|
95
95
|
}
|
|
96
96
|
),
|
|
97
97
|
d ? /* @__PURE__ */ i(
|
|
98
|
-
|
|
98
|
+
J,
|
|
99
99
|
{
|
|
100
100
|
initialValue: (t == null ? void 0 : t.initialValue) ?? o.name ?? "",
|
|
101
101
|
isDraft: !!(t != null && t.isDraft),
|
|
@@ -113,7 +113,7 @@ function Q({ node: n, style: p, dragHandle: h }) {
|
|
|
113
113
|
}
|
|
114
114
|
),
|
|
115
115
|
N && !d && /* @__PURE__ */ i(
|
|
116
|
-
|
|
116
|
+
K,
|
|
117
117
|
{
|
|
118
118
|
"data-testid": "file-tree-pending-spinner",
|
|
119
119
|
"aria-label": "Pending",
|
|
@@ -140,17 +140,17 @@ function te({
|
|
|
140
140
|
onSubmitEdit: N,
|
|
141
141
|
onCancelEdit: b,
|
|
142
142
|
onDragDrop: s,
|
|
143
|
-
className:
|
|
143
|
+
className: R
|
|
144
144
|
}) {
|
|
145
145
|
const k = w(null);
|
|
146
|
-
|
|
146
|
+
I(() => {
|
|
147
147
|
if (!(t != null && t.isDraft)) return;
|
|
148
148
|
const r = requestAnimationFrame(() => {
|
|
149
149
|
var a;
|
|
150
150
|
(a = k.current) == null || a.scrollTo(t.path);
|
|
151
151
|
});
|
|
152
152
|
return () => cancelAnimationFrame(r);
|
|
153
|
-
}, [t == null ? void 0 : t.isDraft, t == null ? void 0 : t.path]),
|
|
153
|
+
}, [t == null ? void 0 : t.isDraft, t == null ? void 0 : t.path]), I(() => {
|
|
154
154
|
if (!u) return;
|
|
155
155
|
const r = requestAnimationFrame(() => {
|
|
156
156
|
var a;
|
|
@@ -212,11 +212,11 @@ function te({
|
|
|
212
212
|
{
|
|
213
213
|
className: v(
|
|
214
214
|
"flex h-full items-center justify-center text-sm text-muted-foreground",
|
|
215
|
-
|
|
215
|
+
R
|
|
216
216
|
),
|
|
217
217
|
children: "No files"
|
|
218
218
|
}
|
|
219
|
-
) : /* @__PURE__ */ i(A.Provider, { value: _, children: /* @__PURE__ */ i("div", { "data-boring-workspace-part": "file-tree", className: v("file-tree",
|
|
219
|
+
) : /* @__PURE__ */ i(A.Provider, { value: _, children: /* @__PURE__ */ i("div", { "data-boring-workspace-part": "file-tree", className: v("file-tree", R), children: /* @__PURE__ */ i(
|
|
220
220
|
q,
|
|
221
221
|
{
|
|
222
222
|
ref: k,
|
|
@@ -15,7 +15,7 @@ import { TableHeader as ut } from "@tiptap/extension-table-header";
|
|
|
15
15
|
import { TableCell as gt } from "@tiptap/extension-table-cell";
|
|
16
16
|
import dt from "@tiptap/extension-image";
|
|
17
17
|
import { c as U } from "./utils-B6yFEsav.js";
|
|
18
|
-
import { ao as q, ap as _ } from "./
|
|
18
|
+
import { ao as q, ap as _ } from "./WorkspaceProvider-CDPaAO5u.js";
|
|
19
19
|
import { uploadFile as ft } from "@hachej/boring-agent/front";
|
|
20
20
|
import mt from "@tiptap/extension-code-block-lowlight";
|
|
21
21
|
import { createLowlight as pt, common as ht } from "lowlight";
|