@hachej/boring-workspace 0.1.53 → 0.1.55
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/{FileTree-CfJoRiTm.js → FileTree-DGonRKiT.js} +17 -17
- package/dist/{MarkdownEditor-DrPDGy9F.js → MarkdownEditor-CwglOF-8.js} +1 -1
- package/dist/{WorkspaceLoadingState-Bqsn2JEc.js → WorkspaceLoadingState-B2Ctp-b2.js} +249 -225
- package/dist/{WorkspaceProvider-CrOT4ab7.js → WorkspaceProvider-DF90RUdU.js} +3275 -3159
- package/dist/app-front.d.ts +20 -0
- package/dist/app-front.js +539 -527
- package/dist/app-server.d.ts +39 -8
- package/dist/app-server.js +1248 -22
- package/dist/bridge-client.d.ts +68 -0
- package/dist/bridge-client.js +370 -0
- package/dist/plugin.d.ts +3 -1
- package/dist/runtimeEnv-XVFZ1OkV.d.ts +353 -0
- package/dist/server.d.ts +236 -8
- package/dist/server.js +1349 -25
- package/dist/shared.d.ts +2 -1
- package/dist/shared.js +30 -0
- package/dist/testing.js +1 -1
- package/dist/{ui-bridge-LeBuZqfA.d.ts → ui-bridge-BbuUZ5iC.d.ts} +6 -1
- package/dist/workspace-bridge-rpc-A98RA5o6.d.ts +124 -0
- package/dist/workspace.css +35 -0
- package/dist/workspace.d.ts +68 -2
- package/dist/workspace.js +196 -185
- package/docs/PLUGIN_SYSTEM.md +57 -0
- package/package.json +8 -4
- package/dist/createInMemoryBridge-siFWq_R_.d.ts +0 -198
package/docs/PLUGIN_SYSTEM.md
CHANGED
|
@@ -282,6 +282,63 @@ parses `/name args` only.
|
|
|
282
282
|
`package.json#pi` block — Pi-sourced commands appear automatically. No
|
|
283
283
|
harness changes required.
|
|
284
284
|
|
|
285
|
+
### 4.8 Generic session attention badges
|
|
286
|
+
|
|
287
|
+
`WorkspaceAttention` is the generic way for plugins to say “this chat session
|
|
288
|
+
needs attention”. The workspace owns only the display and routing mechanics;
|
|
289
|
+
plugins own the domain semantics, surface UI, and bridge/API operations.
|
|
290
|
+
|
|
291
|
+
A plugin should use its own `reason` namespace and may attach a `sessionBadge`
|
|
292
|
+
for the session list:
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
const { addBlocker, removeBlocker } = useWorkspaceAttention()
|
|
296
|
+
|
|
297
|
+
addBlocker({
|
|
298
|
+
id: `pr-review:${sessionId}:123`,
|
|
299
|
+
reason: "pr-review.review",
|
|
300
|
+
sessionId,
|
|
301
|
+
surfaceKind: "pr-review",
|
|
302
|
+
target: "review-123",
|
|
303
|
+
label: "Review PR #123 to continue",
|
|
304
|
+
sessionBadge: {
|
|
305
|
+
kind: "review",
|
|
306
|
+
label: "review",
|
|
307
|
+
tone: "warning",
|
|
308
|
+
priority: 20,
|
|
309
|
+
},
|
|
310
|
+
actions: [{ id: "open", label: "Open review" }],
|
|
311
|
+
})
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
`sessionBadge.kind` is stable metadata for tests/styling
|
|
315
|
+
(`data-boring-badge="review"`). `label` is the short text rendered in the row.
|
|
316
|
+
`tone` is visual only; plugin code should not infer behavior from it. If several
|
|
317
|
+
plugins mark one session, the highest `priority` badge wins.
|
|
318
|
+
|
|
319
|
+
Composer blocker actions are plugin-defined. Workspace provides a convenience
|
|
320
|
+
for `id: "open"` when `surfaceKind` is present, and emits
|
|
321
|
+
`WORKSPACE_ATTENTION_ACTION_EVENT` for every action with `{ blockerId, actionId,
|
|
322
|
+
sessionId, blocker }`. The owning plugin should listen for its domain-specific
|
|
323
|
+
actions such as `approve`, `request-changes`, or `cancel`; workspace does not
|
|
324
|
+
assign semantics to those action ids.
|
|
325
|
+
|
|
326
|
+
Ask-user consumes this as an ask-user-specific attention type:
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
reason: "ask-user.question"
|
|
330
|
+
sessionBadge: { kind: "question", label: "question", tone: "attention" }
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Other plugins should not reuse ask-user’s reason or badge kind unless they are
|
|
334
|
+
actually delegating to ask-user. For example, a PR review plugin should use
|
|
335
|
+
`reason: "pr-review.review"` and `kind: "review"` even if both are ultimately
|
|
336
|
+
“human input”.
|
|
337
|
+
|
|
338
|
+
Compatibility: old blockers with `reason: "waiting_for_user_input"` still render
|
|
339
|
+
a legacy `needs input` badge, but new plugins should provide `sessionBadge`
|
|
340
|
+
explicitly.
|
|
341
|
+
|
|
285
342
|
---
|
|
286
343
|
|
|
287
344
|
## 5. Key algorithms
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hachej/boring-workspace",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.55",
|
|
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.",
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
"types": "./dist/shared.d.ts",
|
|
35
35
|
"import": "./dist/shared.js"
|
|
36
36
|
},
|
|
37
|
+
"./bridge-client": {
|
|
38
|
+
"types": "./dist/bridge-client.d.ts",
|
|
39
|
+
"import": "./dist/bridge-client.js"
|
|
40
|
+
},
|
|
37
41
|
"./app/front": {
|
|
38
42
|
"types": "./dist/app-front.d.ts",
|
|
39
43
|
"import": "./dist/app-front.js",
|
|
@@ -135,9 +139,9 @@
|
|
|
135
139
|
"tailwind-merge": "^2.0.0",
|
|
136
140
|
"zod": "^3.23.0",
|
|
137
141
|
"zustand": "^5.0.0",
|
|
138
|
-
"@hachej/boring-
|
|
139
|
-
"@hachej/boring-ui-
|
|
140
|
-
"@hachej/boring-
|
|
142
|
+
"@hachej/boring-agent": "0.1.55",
|
|
143
|
+
"@hachej/boring-ui-kit": "0.1.55",
|
|
144
|
+
"@hachej/boring-ui-plugin-cli": "0.1.55"
|
|
141
145
|
},
|
|
142
146
|
"devDependencies": {
|
|
143
147
|
"@tailwindcss/postcss": "^4.0.0",
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import { B as BoringPackageBoringField, a as BoringPackagePiField } from './manifest-C2vVgH_e.js';
|
|
2
|
-
import { PiPackageSource, PluginSkillSource, ProvisionWorkspaceRuntimeOptions } from '@hachej/boring-agent/server';
|
|
3
|
-
import { FastifyPluginAsync } from 'fastify';
|
|
4
|
-
import { A as AgentTool } from './agent-tool-CB0RQyx9.js';
|
|
5
|
-
import { U as UiBridge } from './ui-bridge-LeBuZqfA.js';
|
|
6
|
-
|
|
7
|
-
type BoringPluginNativeFrontTargetTrust$1 = "local-trusted-native";
|
|
8
|
-
/**
|
|
9
|
-
* Host-owned runtime import target for a plugin front entry.
|
|
10
|
-
*
|
|
11
|
-
* Only the trusted native/browser-module case exists today. Future
|
|
12
|
-
* target kinds (iframe/artifact/...) can extend the union without
|
|
13
|
-
* rewriting list/event payload shapes.
|
|
14
|
-
*/
|
|
15
|
-
interface BoringPluginNativeFrontTarget$1 {
|
|
16
|
-
kind: "native";
|
|
17
|
-
entryUrl: string;
|
|
18
|
-
revision: number;
|
|
19
|
-
trust: BoringPluginNativeFrontTargetTrust$1;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Plugin front served as a plain browser module URL — the Vite-dev transport
|
|
23
|
-
* (`/@fs/...`). Hosts running a Vite dev server let Vite transform the entry;
|
|
24
|
-
* the CLI's runtime host mints `native` targets instead.
|
|
25
|
-
*/
|
|
26
|
-
interface BoringPluginModuleUrlFrontTarget {
|
|
27
|
-
kind: "module-url";
|
|
28
|
-
entryUrl: string;
|
|
29
|
-
revision: number;
|
|
30
|
-
}
|
|
31
|
-
type BoringPluginFrontTarget$1 = BoringPluginNativeFrontTarget$1 | BoringPluginModuleUrlFrontTarget;
|
|
32
|
-
type BoringPluginEvent$1 = {
|
|
33
|
-
type: "boring.plugin.load";
|
|
34
|
-
id: string;
|
|
35
|
-
boring: BoringPackageBoringField;
|
|
36
|
-
version: string;
|
|
37
|
-
revision: number;
|
|
38
|
-
frontTarget?: BoringPluginFrontTarget$1;
|
|
39
|
-
} | {
|
|
40
|
-
type: "boring.plugin.unload";
|
|
41
|
-
id: string;
|
|
42
|
-
revision: number;
|
|
43
|
-
} | {
|
|
44
|
-
type: "boring.plugin.error";
|
|
45
|
-
id: string;
|
|
46
|
-
revision: number;
|
|
47
|
-
message: string;
|
|
48
|
-
};
|
|
49
|
-
interface BoringPluginListEntry$1 {
|
|
50
|
-
id: string;
|
|
51
|
-
boring: BoringPackageBoringField;
|
|
52
|
-
pi?: BoringPackagePiField;
|
|
53
|
-
version: string;
|
|
54
|
-
revision: number;
|
|
55
|
-
frontTarget?: BoringPluginFrontTarget$1;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
type BoringPluginSourceKind = "internal" | "external";
|
|
59
|
-
interface BoringPluginSource {
|
|
60
|
-
rootDir: string;
|
|
61
|
-
kind: BoringPluginSourceKind;
|
|
62
|
-
workspaceId?: string;
|
|
63
|
-
/**
|
|
64
|
-
* True when the user explicitly registered this directory as a plugin
|
|
65
|
-
* source (e.g. a `packages` entry in Pi settings.json). Registered
|
|
66
|
-
* sources that are missing, lack a package.json, or carry no plugin
|
|
67
|
-
* metadata surface as preflight errors instead of being silently
|
|
68
|
-
* skipped the way speculative scan roots are.
|
|
69
|
-
*/
|
|
70
|
-
registered?: boolean;
|
|
71
|
-
}
|
|
72
|
-
type BoringPluginSourceInput = string | BoringPluginSource;
|
|
73
|
-
interface BoringServerPluginManifest {
|
|
74
|
-
id: string;
|
|
75
|
-
rootDir: string;
|
|
76
|
-
version: string;
|
|
77
|
-
boring: BoringPackageBoringField;
|
|
78
|
-
/** True when package.json explicitly declares a boring manifest. Pi-only packages remain valid Pi resources but are not listed as Boring plugins. */
|
|
79
|
-
hasBoring: boolean;
|
|
80
|
-
pi?: BoringPackagePiField;
|
|
81
|
-
frontPath?: string;
|
|
82
|
-
/** Legacy Vite-dev browser import fallback (`/@fs/...`). */
|
|
83
|
-
frontUrl?: string;
|
|
84
|
-
serverPath?: string;
|
|
85
|
-
extensionPaths?: string[];
|
|
86
|
-
skillPaths?: string[];
|
|
87
|
-
source: BoringPluginSource;
|
|
88
|
-
}
|
|
89
|
-
type BoringPluginNativeFrontTargetTrust = BoringPluginNativeFrontTargetTrust$1;
|
|
90
|
-
type BoringPluginNativeFrontTarget = BoringPluginNativeFrontTarget$1;
|
|
91
|
-
type BoringPluginFrontTarget = BoringPluginFrontTarget$1;
|
|
92
|
-
type BoringPluginListEntry = BoringPluginListEntry$1;
|
|
93
|
-
interface BoringPluginFrontTargetResolverContext {
|
|
94
|
-
revision: number;
|
|
95
|
-
/** Plugin-root-relative front entry path normalized for URL-like consumers. */
|
|
96
|
-
frontEntrySubpath: string;
|
|
97
|
-
}
|
|
98
|
-
type BoringPluginFrontTargetResolver = (plugin: BoringServerPluginManifest, context: BoringPluginFrontTargetResolverContext) => BoringPluginFrontTarget | undefined;
|
|
99
|
-
/**
|
|
100
|
-
* Surfaces whose changes the hot-reload pipeline can't re-load mid-
|
|
101
|
-
* session — set when a plugin's load DID succeed but a sub-surface
|
|
102
|
-
* (the agent-tools registry, Fastify routes) carries stale code from
|
|
103
|
-
* the previous revision. The /reload caller (chat UI, verify-plugin,
|
|
104
|
-
* etc.) should surface a "restart needed for X" warning.
|
|
105
|
-
*
|
|
106
|
-
* - `'routes'`: a `WorkspaceServerPlugin.routes` function changed. The
|
|
107
|
-
* workspace's Fastify instance can't unregister + re-register routes
|
|
108
|
-
* mid-flight; the previous routes stay live until next boot.
|
|
109
|
-
* - `'agentTools'`: a `WorkspaceServerPlugin.agentTools` array changed.
|
|
110
|
-
* The current Pi session still has the old tool list; new sessions
|
|
111
|
-
* get the new list.
|
|
112
|
-
* - Multiple surfaces: order is deterministic (`routes` before
|
|
113
|
-
* `agentTools`) so subscribers can format consistently.
|
|
114
|
-
*/
|
|
115
|
-
type PluginRestartSurface = "routes" | "agentTools";
|
|
116
|
-
type BoringPluginEvent = (Extract<BoringPluginEvent$1, {
|
|
117
|
-
type: "boring.plugin.load";
|
|
118
|
-
}> & {
|
|
119
|
-
/**
|
|
120
|
-
* Non-empty when the plugin loaded but one or more server-side
|
|
121
|
-
* surfaces still hold pre-load code. UI consumers should render
|
|
122
|
-
* a "restart needed: <surfaces>" hint. Empty/omitted = fully
|
|
123
|
-
* live.
|
|
124
|
-
*/
|
|
125
|
-
requiresRestart?: PluginRestartSurface[];
|
|
126
|
-
}) | Extract<BoringPluginEvent$1, {
|
|
127
|
-
type: "boring.plugin.unload";
|
|
128
|
-
}> | Extract<BoringPluginEvent$1, {
|
|
129
|
-
type: "boring.plugin.error";
|
|
130
|
-
}>;
|
|
131
|
-
|
|
132
|
-
type WorkspaceRuntimeProvisioning = NonNullable<ProvisionWorkspaceRuntimeOptions["plugins"][number]["provisioning"]>;
|
|
133
|
-
interface WorkspaceServerPluginAsset {
|
|
134
|
-
/** Stable asset name within this plugin, e.g. "sdk" or "workspace-template". */
|
|
135
|
-
name: string;
|
|
136
|
-
/** Source directory or file owned by the plugin. Relative strings are resolved by the app integration. */
|
|
137
|
-
source: string | URL;
|
|
138
|
-
/** Optional runtime target path within this plugin's asset namespace. Defaults to name. */
|
|
139
|
-
target?: string;
|
|
140
|
-
}
|
|
141
|
-
interface WorkspaceServerPlugin {
|
|
142
|
-
id: string;
|
|
143
|
-
label?: string;
|
|
144
|
-
/**
|
|
145
|
-
* Native Pi package sources required by this workspace integration.
|
|
146
|
-
* Workspace declares them; @hachej/boring-agent applies them through Pi's native
|
|
147
|
-
* resource loader without asking Pi packages to export Boring adapters.
|
|
148
|
-
*/
|
|
149
|
-
piPackages?: PiPackageSource[];
|
|
150
|
-
/**
|
|
151
|
-
* Native pi extension entrypoints contributed by this plugin.
|
|
152
|
-
* Passed to DefaultResourceLoader.additionalExtensionPaths so pi owns jiti
|
|
153
|
-
* loading and ctx.reload() re-imports fresh source.
|
|
154
|
-
*/
|
|
155
|
-
extensionPaths?: string[];
|
|
156
|
-
systemPrompt?: string;
|
|
157
|
-
skills?: PluginSkillSource[];
|
|
158
|
-
agentTools?: AgentTool[];
|
|
159
|
-
provisioning?: WorkspaceRuntimeProvisioning;
|
|
160
|
-
/** Static filesystem assets this plugin needs in production/serverless bundles. */
|
|
161
|
-
assets?: WorkspaceServerPluginAsset[];
|
|
162
|
-
routes?: FastifyPluginAsync;
|
|
163
|
-
/** UI state keys owned by this plugin that browser state PUTs must not overwrite. */
|
|
164
|
-
preservedUiStateKeys?: string[];
|
|
165
|
-
}
|
|
166
|
-
declare function validateServerPlugin(plugin: WorkspaceServerPlugin): void;
|
|
167
|
-
declare function defineServerPlugin<T extends WorkspaceServerPlugin>(plugin: T): T;
|
|
168
|
-
|
|
169
|
-
interface ServerBootstrapOptions {
|
|
170
|
-
plugins?: WorkspaceServerPlugin[];
|
|
171
|
-
defaults?: WorkspaceServerPlugin[];
|
|
172
|
-
excludeDefaults?: string[];
|
|
173
|
-
}
|
|
174
|
-
type WorkspaceRuntimeProvisioningInput = ProvisionWorkspaceRuntimeOptions["plugins"][number];
|
|
175
|
-
type WorkspaceProvisioningContribution = {
|
|
176
|
-
id: string;
|
|
177
|
-
provisioning: NonNullable<WorkspaceRuntimeProvisioningInput["provisioning"]>;
|
|
178
|
-
};
|
|
179
|
-
type WorkspaceRouteContribution = {
|
|
180
|
-
id: string;
|
|
181
|
-
routes: FastifyPluginAsync;
|
|
182
|
-
};
|
|
183
|
-
interface ServerBootstrapResult {
|
|
184
|
-
registered: string[];
|
|
185
|
-
systemPromptAppend: string;
|
|
186
|
-
piPackages: PiPackageSource[];
|
|
187
|
-
extensionPaths: string[];
|
|
188
|
-
agentTools: AgentTool[];
|
|
189
|
-
runtimePlugins: WorkspaceRuntimeProvisioningInput[];
|
|
190
|
-
provisioningContributions: WorkspaceProvisioningContribution[];
|
|
191
|
-
routeContributions: WorkspaceRouteContribution[];
|
|
192
|
-
preservedUiStateKeys: string[];
|
|
193
|
-
}
|
|
194
|
-
declare function bootstrapServer(options: ServerBootstrapOptions): ServerBootstrapResult;
|
|
195
|
-
|
|
196
|
-
declare function createInMemoryBridge(): UiBridge;
|
|
197
|
-
|
|
198
|
-
export { type BoringPluginSourceInput as B, type PluginRestartSurface as P, type ServerBootstrapOptions as S, type WorkspaceServerPlugin as W, type BoringPluginFrontTargetResolver as a, type WorkspaceProvisioningContribution as b, type WorkspaceRouteContribution as c, createInMemoryBridge as d, type WorkspaceRuntimeProvisioningInput as e, type WorkspaceServerPluginAsset as f, type BoringServerPluginManifest as g, type BoringPluginListEntry as h, type BoringPluginFrontTarget as i, type BoringPluginSource as j, type BoringPluginEvent as k, type BoringPluginFrontTargetResolverContext as l, type BoringPluginNativeFrontTarget as m, type BoringPluginNativeFrontTargetTrust as n, type BoringPluginSourceKind as o, type ServerBootstrapResult as p, bootstrapServer as q, defineServerPlugin as r, validateServerPlugin as v };
|