@hachej/boring-workspace 0.1.34 → 0.1.36
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-DWbh0xNI.js → FileTree-GkaIEJ9n.js} +1 -1
- package/dist/MarkdownEditor-DjZZnHcU.js +549 -0
- package/dist/{WorkspaceLoadingState-RVGURLJy.js → WorkspaceLoadingState-C664sU-y.js} +286 -252
- package/dist/WorkspaceProvider-CpK401MG.js +7394 -0
- package/dist/agent-tool-CB0RQyx9.d.ts +32 -0
- package/dist/app-front.d.ts +31 -3
- package/dist/app-front.js +886 -741
- package/dist/app-server.d.ts +4 -3
- package/dist/app-server.js +32 -0
- package/dist/boring-workspace.css +1 -1
- package/dist/{createInMemoryBridge-zb8MpO60.d.ts → createInMemoryBridge-e7QdNLSA.d.ts} +2 -1
- package/dist/plugin.d.ts +73 -1
- package/dist/plugin.js +47 -1
- package/dist/server.d.ts +14 -5
- package/dist/server.js +16 -0
- package/dist/shared.d.ts +2 -1
- package/dist/testing.js +1 -1
- package/dist/{ui-bridge-DFNem0df.d.ts → ui-bridge-LeBuZqfA.d.ts} +1 -32
- package/dist/workspace.css +299 -34
- package/dist/workspace.d.ts +49 -2
- package/dist/workspace.js +31 -30
- package/package.json +5 -5
- package/dist/MarkdownEditor-BhLjIyPQ.js +0 -540
- package/dist/WorkspaceProvider-hCE2wXKZ.js +0 -6567
package/dist/app-server.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { PiPackageSource, PiExtensionFactory, CreateAgentAppOptions, ProvisionWorkspaceRuntimeOptions } from '@hachej/boring-agent/server';
|
|
2
2
|
export { PiPackageSource as WorkspacePiPackageSource } from '@hachej/boring-agent/server';
|
|
3
3
|
import { FastifyInstance } from 'fastify';
|
|
4
|
-
import { W as WorkspaceServerPlugin, S as ServerBootstrapOptions, B as BoringPluginSourceInput, a as BoringPluginFrontTargetResolver, b as WorkspaceProvisioningContribution, c as WorkspaceRouteContribution, d as createInMemoryBridge } from './createInMemoryBridge-
|
|
5
|
-
export { e as ServerWorkspaceRuntimeProvisioningInput } from './createInMemoryBridge-
|
|
4
|
+
import { W as WorkspaceServerPlugin, S as ServerBootstrapOptions, B as BoringPluginSourceInput, a as BoringPluginFrontTargetResolver, b as WorkspaceProvisioningContribution, c as WorkspaceRouteContribution, d as createInMemoryBridge } from './createInMemoryBridge-e7QdNLSA.js';
|
|
5
|
+
export { e as ServerWorkspaceRuntimeProvisioningInput } from './createInMemoryBridge-e7QdNLSA.js';
|
|
6
6
|
import './manifest-C2vVgH_e.js';
|
|
7
|
-
import './
|
|
7
|
+
import './agent-tool-CB0RQyx9.js';
|
|
8
|
+
import './ui-bridge-LeBuZqfA.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Directory-source entry: `{ dir, options?, hotReload? }`. Resolved via
|
package/dist/app-server.js
CHANGED
|
@@ -111,6 +111,12 @@ function buildBoringSystemPrompt(opts) {
|
|
|
111
111
|
"- Dependency installs: do NOT install plugin UI dependencies at the workspace root. Install them inside `.pi/extensions/<name>/` and keep React/workspace/boring-ui-kit imports as host singletons, not plugin dependencies.",
|
|
112
112
|
"- Hot-reload agent tools: do NOT put them in `.pi/extensions/<name>/server/index.ts`; use `pi.extensions` instead. `boring.server` requires static composition plus process restart."
|
|
113
113
|
].join("\n"),
|
|
114
|
+
[
|
|
115
|
+
"## Installing an existing or published plugin",
|
|
116
|
+
"To ADD an existing or published plugin (not author a new one), use `boring-ui-plugin install <source>` via bash \u2014 `<source>` is `npm:<package>`, `git:<repo>`, `github:<owner>/<repo>`, an `http(s)` git URL, or a local path; add `--global` for all workspaces (default is this workspace).",
|
|
117
|
+
"A bare `npm install <package>` does NOT register it as a plugin (no `.pi/settings.json` package source), so it will NOT load \u2014 always use `boring-ui-plugin install`, then ask the user to `/reload` (a `boring.server` backend also needs a process restart).",
|
|
118
|
+
"Inspect with `boring-ui-plugin list [--json]`; remove with `boring-ui-plugin remove <id-or-source>`."
|
|
119
|
+
].join("\n"),
|
|
114
120
|
docsBlock
|
|
115
121
|
].join("\n\n");
|
|
116
122
|
}
|
|
@@ -994,6 +1000,16 @@ var BoringPluginAssetManager = class {
|
|
|
994
1000
|
this.frontTargetResolver = options.frontTargetResolver;
|
|
995
1001
|
this.includeLegacyFrontUrl = options.includeLegacyFrontUrl ?? true;
|
|
996
1002
|
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Replace the scanned source roots. Lets hosts re-resolve discovery inputs
|
|
1005
|
+
* (e.g. workspace `.pi/settings.json` package sources, which can gain
|
|
1006
|
+
* entries after `boring-ui-plugin install`) before the next load() so
|
|
1007
|
+
* `/reload` picks up newly installed plugin sources without a process
|
|
1008
|
+
* restart.
|
|
1009
|
+
*/
|
|
1010
|
+
setPluginDirs(pluginDirs) {
|
|
1011
|
+
this.pluginDirs = pluginDirs;
|
|
1012
|
+
}
|
|
997
1013
|
preflight() {
|
|
998
1014
|
return preflightBoringPlugins(this.pluginDirs);
|
|
999
1015
|
}
|
|
@@ -1973,6 +1989,20 @@ function createInMemoryBridge() {
|
|
|
1973
1989
|
};
|
|
1974
1990
|
}
|
|
1975
1991
|
|
|
1992
|
+
// src/shared/plugins/uiBridgeRegistry.ts
|
|
1993
|
+
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("@hachej/boring-workspace:active-ui-bridge");
|
|
1994
|
+
function slot() {
|
|
1995
|
+
return globalThis;
|
|
1996
|
+
}
|
|
1997
|
+
function registerWorkspaceUiBridge(bridge) {
|
|
1998
|
+
slot()[REGISTRY_KEY] = bridge;
|
|
1999
|
+
return () => {
|
|
2000
|
+
if (slot()[REGISTRY_KEY] === bridge) {
|
|
2001
|
+
slot()[REGISTRY_KEY] = void 0;
|
|
2002
|
+
}
|
|
2003
|
+
};
|
|
2004
|
+
}
|
|
2005
|
+
|
|
1976
2006
|
// src/server/ui-control/tools/uiTools.ts
|
|
1977
2007
|
import { stat } from "fs/promises";
|
|
1978
2008
|
import { resolve as resolve6, isAbsolute as isAbsolute4, relative as relative3, win32 } from "path";
|
|
@@ -2879,6 +2909,7 @@ function readWorkspacePluginPackagePiSnapshot(pluginDirs) {
|
|
|
2879
2909
|
async function createWorkspaceAgentServer(opts = {}) {
|
|
2880
2910
|
const workspaceRoot = opts.workspaceRoot ?? process.cwd();
|
|
2881
2911
|
const bridge = createInMemoryBridge();
|
|
2912
|
+
const unregisterUiBridge = registerWorkspaceUiBridge(bridge);
|
|
2882
2913
|
const resolvedMode = opts.runtimeModeAdapter?.id ?? opts.mode ?? autoDetectMode();
|
|
2883
2914
|
const modeAdapter = opts.runtimeModeAdapter ?? resolveMode(resolvedMode);
|
|
2884
2915
|
const workspaceFsCapability = modeAdapter.workspaceFsCapability ?? "best-effort";
|
|
@@ -3056,6 +3087,7 @@ async function createWorkspaceAgentServer(opts = {}) {
|
|
|
3056
3087
|
if (typeof app.addHook === "function") {
|
|
3057
3088
|
app.addHook("onClose", async () => {
|
|
3058
3089
|
await runtimeBackendRegistry.close();
|
|
3090
|
+
unregisterUiBridge();
|
|
3059
3091
|
});
|
|
3060
3092
|
}
|
|
3061
3093
|
await app.register(uiRoutes, { bridge, preserveStateKeys: pluginCollection.preservedUiStateKeys });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.dv-shell{--dv-background-color: var(--background);--dv-paneview-header-border-color: var(--border);--dv-tabs-and-actions-container-font-size: .8125rem;--dv-tabs-and-actions-container-height: 52px;--dv-tab-close-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");--dv-group-view-background-color: var(--background);--dv-tabs-and-actions-container-background-color: var(--background);--dv-activegroup-visiblepanel-tab-background-color: var(--background);--dv-activegroup-hiddenpanel-tab-background-color: var(--muted);--dv-inactivegroup-visiblepanel-tab-background-color: var(--background);--dv-inactivegroup-hiddenpanel-tab-background-color: var(--muted);--dv-activegroup-visiblepanel-tab-color: var(--foreground);--dv-activegroup-hiddenpanel-tab-color: var(--muted-foreground);--dv-inactivegroup-visiblepanel-tab-color: var(--foreground);--dv-inactivegroup-hiddenpanel-tab-color: var(--muted-foreground);--dv-tab-divider-color: transparent;--dv-drag-over-background-color: oklch(from var(--accent) l c h / .3);--dv-drag-over-border-color: var(--accent);--dv-separator-border: var(--border);color:var(--foreground);background-color:var(--background)}.dv-shell .dv-tabs-and-actions-container,.dv-shell .tabs-and-actions-container{background-color:var(--background)!important;border-bottom:1px solid oklch(from var(--border) l c h / .4);padding:6px 8px 0;gap:4px;align-items:flex-end}.dv-shell .dv-tabs-container,.dv-shell .tab-container{background-color:transparent!important;gap:4px;align-self:stretch;display:flex;align-items:flex-end}.workbench-dockview .dv-shell .dv-tabs-and-actions-container,.workbench-dockview .dv-shell .tabs-and-actions-container,.workbench-dockview .dv-tabs-and-actions-container,.workbench-dockview .tabs-and-actions-container{height:44px!important}.workbench-dockview[data-collapsed-sources=true] .dv-tabs-and-actions-container,.workbench-dockview[data-collapsed-sources=true] .tabs-and-actions-container{padding-left:44px!important}.workbench-dockview .dv-tabs-and-actions-container,.workbench-dockview .tabs-and-actions-container{padding-right:44px!important}.dv-shell .dv-tab,.dv-shell .tab{color:var(--muted-foreground)!important;background-color:transparent!important;border:1px solid transparent;border-top-left-radius:8px;border-top-right-radius:8px;transition:color .18s cubic-bezier(.22,1,.36,1),background-color .18s cubic-bezier(.22,1,.36,1),border-color .18s cubic-bezier(.22,1,.36,1);min-width:120px;max-width:220px;padding:0;height:34px;align-self:end;font-size:12.5px;letter-spacing:-.01em}.dv-shell .dv-tab:hover,.dv-shell .tab:hover{color:var(--foreground)!important;background-color:oklch(from var(--foreground) l c h / .04)!important}.dv-shell .dv-tab>*,.dv-shell .tab>*{width:100%;height:100%}.dv-shell .dv-tab.dv-active-tab,.dv-shell .tab.active-tab{color:var(--foreground)!important;background-color:var(--background)!important;border-color:oklch(from var(--border) l c h / .5);border-bottom-color:var(--background);margin-bottom:-1px;position:relative;z-index:1;font-weight:500}.dv-shell .dv-tab.dv-active-tab:before,.dv-shell .tab.active-tab:before{content:"";position:absolute;left:10px;right:10px;top:-1px;height:2px;background:var(--accent);border-radius:0 0 2px 2px;opacity:0;transition:opacity .2s cubic-bezier(.22,1,.36,1)}.dv-shell .dv-tab.dv-active-tab:hover:before,.dv-shell .tab.active-tab:hover:before{opacity:.7}.dv-shell .sash-container .sash,.dv-shell .dv-sash-container .dv-sash{transition:background-color .2s}.dv-shell .sash-container .sash:hover,.dv-shell .sash-container .sash.active,.dv-shell .dv-sash-container .dv-sash:hover,.dv-shell .dv-sash-container .dv-sash.dv-active{background-color:var(--primary);transition-delay:.15s}.dv-shell .drop-target-dropzone>.drop-target-selection,.dv-shell .dv-drop-target-dropzone>.dv-drop-target-selection{background-color:oklch(from var(--primary) l c h / .15);border:2px dashed var(--primary);border-radius:calc(var(--radius) - 2px)}.dv-shell .watermark,.dv-shell .dv-watermark{color:var(--muted-foreground)}.dv-shell,.dv-shell .dv-dockview,.dv-shell .dv-groupview,.dv-shell .groupview,.dv-shell .groupview>.content-container,.dv-shell .dv-view-container,.dv-shell .view-container{background-color:var(--background)}.dv-shell .dv-groupview,.dv-shell .groupview{color:var(--foreground)}.dv-shell .right-actions-container,.dv-shell .left-actions-container,.dv-shell .dv-right-actions-container,.dv-shell .dv-left-actions-container{color:var(--muted-foreground);display:flex;align-items:center;align-self:stretch}.dv-shell .right-actions-container:hover,.dv-shell .left-actions-container:hover,.dv-shell .dv-right-actions-container:hover,.dv-shell .dv-left-actions-container:hover{color:var(--foreground)}.dv-shell .dv-drag-image{opacity:.85;border:1px solid var(--border);border-radius:calc(var(--radius) - 2px);box-shadow:0 4px 12px #00000026}
|
|
1
|
+
.dv-shell{--dv-background-color: var(--background);--dv-paneview-header-border-color: var(--border);--dv-tabs-and-actions-container-font-size: .8125rem;--dv-tabs-and-actions-container-height: 52px;--dv-tab-close-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");--dv-group-view-background-color: var(--background);--dv-tabs-and-actions-container-background-color: var(--background);--dv-activegroup-visiblepanel-tab-background-color: var(--background);--dv-activegroup-hiddenpanel-tab-background-color: var(--muted);--dv-inactivegroup-visiblepanel-tab-background-color: var(--background);--dv-inactivegroup-hiddenpanel-tab-background-color: var(--muted);--dv-activegroup-visiblepanel-tab-color: var(--foreground);--dv-activegroup-hiddenpanel-tab-color: var(--muted-foreground);--dv-inactivegroup-visiblepanel-tab-color: var(--foreground);--dv-inactivegroup-hiddenpanel-tab-color: var(--muted-foreground);--dv-tab-divider-color: transparent;--dv-drag-over-background-color: oklch(from var(--accent) l c h / .3);--dv-drag-over-border-color: var(--accent);--dv-separator-border: var(--border);color:var(--foreground);background-color:var(--background)}.dv-shell .dv-tabs-and-actions-container,.dv-shell .tabs-and-actions-container{background-color:var(--background)!important;border-bottom:1px solid oklch(from var(--border) l c h / .4);padding:6px 8px 0;gap:4px;align-items:flex-end}.dv-shell .dv-tabs-container,.dv-shell .tab-container{background-color:transparent!important;gap:4px;align-self:stretch;display:flex;align-items:flex-end}.workbench-dockview .dv-shell .dv-tabs-and-actions-container,.workbench-dockview .dv-shell .tabs-and-actions-container,.workbench-dockview .dv-tabs-and-actions-container,.workbench-dockview .tabs-and-actions-container{height:44px!important}.workbench-dockview[data-collapsed-sources=true] .dv-tabs-and-actions-container,.workbench-dockview[data-collapsed-sources=true] .tabs-and-actions-container{padding-left:44px!important}.workbench-dockview .dv-tabs-and-actions-container,.workbench-dockview .tabs-and-actions-container{padding-right:44px!important}.dv-shell .dv-tab,.dv-shell .tab{color:var(--muted-foreground)!important;background-color:transparent!important;border:1px solid transparent;border-top-left-radius:8px;border-top-right-radius:8px;transition:color .18s cubic-bezier(.22,1,.36,1),background-color .18s cubic-bezier(.22,1,.36,1),border-color .18s cubic-bezier(.22,1,.36,1);min-width:120px;max-width:220px;padding:0;height:34px;align-self:end;font-size:12.5px;letter-spacing:-.01em}.dv-shell .dv-tab:hover,.dv-shell .tab:hover{color:var(--foreground)!important;background-color:oklch(from var(--foreground) l c h / .04)!important}.dv-shell .dv-tab>*,.dv-shell .tab>*{width:100%;height:100%}.dv-shell .dv-tab.dv-active-tab,.dv-shell .tab.active-tab{color:var(--foreground)!important;background-color:var(--background)!important;border-color:oklch(from var(--border) l c h / .5);border-bottom-color:var(--background);margin-bottom:-1px;position:relative;z-index:1;font-weight:500}.dv-shell .dv-tab.dv-active-tab:before,.dv-shell .tab.active-tab:before{content:"";position:absolute;left:10px;right:10px;top:-1px;height:2px;background:var(--accent);border-radius:0 0 2px 2px;opacity:0;transition:opacity .2s cubic-bezier(.22,1,.36,1)}.dv-shell .dv-tab.dv-active-tab:hover:before,.dv-shell .tab.active-tab:hover:before{opacity:.7}.dv-shell .sash-container .sash,.dv-shell .dv-sash-container .dv-sash{transition:background-color .2s}.dv-shell .sash-container .sash:hover,.dv-shell .sash-container .sash.active,.dv-shell .dv-sash-container .dv-sash:hover,.dv-shell .dv-sash-container .dv-sash.dv-active{background-color:var(--primary);transition-delay:.15s}.dv-shell .drop-target-dropzone>.drop-target-selection,.dv-shell .dv-drop-target-dropzone>.dv-drop-target-selection{background-color:oklch(from var(--primary) l c h / .15);border:2px dashed var(--primary);border-radius:calc(var(--radius) - 2px)}.dv-shell .watermark,.dv-shell .dv-watermark{color:var(--muted-foreground)}.dv-shell,.dv-shell .dv-dockview,.dv-shell .dv-groupview,.dv-shell .groupview,.dv-shell .groupview>.content-container,.dv-shell .dv-view-container,.dv-shell .view-container{background-color:var(--background)}.dv-shell .dv-groupview,.dv-shell .groupview{color:var(--foreground)}.dv-shell .right-actions-container,.dv-shell .left-actions-container,.dv-shell .dv-right-actions-container,.dv-shell .dv-left-actions-container{color:var(--muted-foreground);display:flex;align-items:center;align-self:stretch}.dv-shell .right-actions-container:hover,.dv-shell .left-actions-container:hover,.dv-shell .dv-right-actions-container:hover,.dv-shell .dv-left-actions-container:hover{color:var(--foreground)}.dv-shell .dv-drag-image{opacity:.85;border:1px solid var(--border);border-radius:calc(var(--radius) - 2px);box-shadow:0 4px 12px #00000026}.dv-chat-stage{--dv-tabs-and-actions-container-height: 32px;--dv-tabs-and-actions-container-font-size: .75rem;--dv-activegroup-visiblepanel-tab-background-color: transparent;--dv-activegroup-hiddenpanel-tab-background-color: transparent;--dv-inactivegroup-visiblepanel-tab-background-color: transparent;--dv-inactivegroup-hiddenpanel-tab-background-color: transparent}.dv-shell.dv-chat-stage .dv-tabs-and-actions-container{border-bottom:none;padding:0;gap:0;align-items:stretch}.dv-shell.dv-chat-stage .dv-tabs-and-actions-container.dv-single-tab .dv-tabs-container{width:100%}.dv-shell.dv-chat-stage .dv-tab,.dv-shell.dv-chat-stage .dv-tab.dv-active-tab{width:100%;height:100%;min-width:0;max-width:none;flex:1 1 auto;align-self:stretch;margin-bottom:0;padding:0;border:none;border-radius:0;background-color:transparent!important}.dv-shell.dv-chat-stage .dv-tab.dv-active-tab:before{content:none}.dv-chat-stage .dv-default-tab-action{display:none}.dv-chat-stage .dv-groupview{position:relative}.dv-chat-stage .dv-groupview:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;z-index:40;pointer-events:none;background:transparent;transition:background-color .22s cubic-bezier(.22,1,.36,1),box-shadow .22s cubic-bezier(.22,1,.36,1)}[data-boring-workspace-part=chat-pane-stage][data-multi-pane=true] .dv-groupview:not(.dv-active-group):after{background:oklch(from var(--foreground) l c h / .035)}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { B as BoringPackageBoringField, a as BoringPackagePiField } from './manifest-C2vVgH_e.js';
|
|
2
2
|
import { PiPackageSource, PluginSkillSource, ProvisionWorkspaceRuntimeOptions } from '@hachej/boring-agent/server';
|
|
3
3
|
import { FastifyPluginAsync } from 'fastify';
|
|
4
|
-
import { A as AgentTool
|
|
4
|
+
import { A as AgentTool } from './agent-tool-CB0RQyx9.js';
|
|
5
|
+
import { U as UiBridge } from './ui-bridge-LeBuZqfA.js';
|
|
5
6
|
|
|
6
7
|
type BoringPluginNativeFrontTargetTrust$1 = "local-trusted-native";
|
|
7
8
|
/**
|
package/dist/plugin.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { ComponentType, ReactNode } from 'react';
|
|
|
2
2
|
import { P as PaneProps, a as PanelConfig, S as SurfaceOpenRequest, c as SurfacePanelResolution } from './surface-obE7YwJk.js';
|
|
3
3
|
export { W as WORKSPACE_OPEN_PATH_SURFACE_KIND } from './surface-obE7YwJk.js';
|
|
4
4
|
export { B as BoringPackageBoringField, a as BoringPackagePiField, b as BoringPackagePiSource, c as BoringPackagePiSourceObject, d as BoringPluginManifestErrorCode, e as BoringPluginManifestIssue, f as BoringPluginManifestValidationResult, g as BoringPluginPackageJson, i as isSafePluginRelativePath, h as isValidBoringPluginId, v as validateBoringPluginManifest } from './manifest-C2vVgH_e.js';
|
|
5
|
+
import { a as UiCommand, C as CommandResult, U as UiBridge } from './ui-bridge-LeBuZqfA.js';
|
|
5
6
|
import 'dockview-react';
|
|
6
7
|
|
|
7
8
|
type CatalogBadge = {
|
|
@@ -128,6 +129,11 @@ interface BoringFrontSurfaceResolverRegistration {
|
|
|
128
129
|
source?: string;
|
|
129
130
|
resolve: (request: SurfaceOpenRequest) => SurfacePanelResolution | null | undefined;
|
|
130
131
|
}
|
|
132
|
+
type BoringFrontToolRenderer = (part: unknown) => ReactNode;
|
|
133
|
+
interface BoringFrontToolRendererRegistration {
|
|
134
|
+
id: string;
|
|
135
|
+
render: BoringFrontToolRenderer;
|
|
136
|
+
}
|
|
131
137
|
interface BoringFrontAPI {
|
|
132
138
|
registerProvider(registration: BoringFrontProviderRegistration): void;
|
|
133
139
|
registerBinding(registration: BoringFrontBindingRegistration): void;
|
|
@@ -136,6 +142,7 @@ interface BoringFrontAPI {
|
|
|
136
142
|
registerPanelCommand(registration: BoringFrontPanelCommandRegistration): void;
|
|
137
143
|
registerLeftTab<T = LeftTabParams>(registration: BoringFrontLeftTabRegistration<T>): void;
|
|
138
144
|
registerSurfaceResolver(registration: BoringFrontSurfaceResolverRegistration): void;
|
|
145
|
+
registerToolRenderer(registration: BoringFrontToolRendererRegistration): void;
|
|
139
146
|
}
|
|
140
147
|
type BoringFrontFactory = (api: BoringFrontAPI) => void | Promise<void>;
|
|
141
148
|
type BoringFrontSetup = (api: BoringFrontAPI) => void;
|
|
@@ -164,6 +171,7 @@ interface DefinePluginConfig {
|
|
|
164
171
|
providers?: ReadonlyArray<BoringFrontProviderRegistration>;
|
|
165
172
|
bindings?: ReadonlyArray<BoringFrontBindingRegistration>;
|
|
166
173
|
catalogs?: ReadonlyArray<CatalogConfig>;
|
|
174
|
+
toolRenderers?: ReadonlyArray<BoringFrontToolRendererRegistration>;
|
|
167
175
|
/**
|
|
168
176
|
* Escape hatch for registrations that can't be expressed declaratively.
|
|
169
177
|
* Called LAST, after every declarative field has been registered.
|
|
@@ -187,6 +195,7 @@ interface CapturedBoringFrontRegistrations {
|
|
|
187
195
|
panelCommands: BoringFrontPanelCommandRegistration[];
|
|
188
196
|
leftTabs: BoringFrontLeftTabRegistration<any>[];
|
|
189
197
|
surfaceResolvers: BoringFrontSurfaceResolverRegistration[];
|
|
198
|
+
toolRenderers: BoringFrontToolRendererRegistration[];
|
|
190
199
|
}
|
|
191
200
|
interface CapturedFrontPlugin {
|
|
192
201
|
id: string;
|
|
@@ -201,4 +210,67 @@ declare function createCapturingBoringFrontAPI(options?: {
|
|
|
201
210
|
}): CapturingBoringFrontAPIHandle;
|
|
202
211
|
declare function captureFrontPlugin(plugin: BoringFrontFactoryWithId): CapturedFrontPlugin;
|
|
203
212
|
|
|
204
|
-
|
|
213
|
+
/**
|
|
214
|
+
* In-process registry that lets a plugin's Pi slash command reach the live
|
|
215
|
+
* workspace `UiBridge` WITHOUT an HTTP round-trip or a `BORING_UI_URL` env var.
|
|
216
|
+
*
|
|
217
|
+
* Why this exists
|
|
218
|
+
* ---------------
|
|
219
|
+
* A Pi extension slash-command handler only receives Pi's terminal-oriented
|
|
220
|
+
* `ctx.ui` (notify/select/confirm). It has no concept of the boring-ui
|
|
221
|
+
* workspace UI bridge, so the old canonical template resorted to
|
|
222
|
+
* `fetch(BORING_UI_URL + "/api/v1/ui/commands")` — fragile, and it silently
|
|
223
|
+
* no-op'd whenever the env var was unset (which is the common case). The bridge
|
|
224
|
+
* is already an in-process object owned by the agent server, so the right thing
|
|
225
|
+
* is to call `bridge.postCommand(...)` directly — the exact same path the
|
|
226
|
+
* agent's `exec_ui` tool uses.
|
|
227
|
+
*
|
|
228
|
+
* Why globalThis
|
|
229
|
+
* --------------
|
|
230
|
+
* Hot-reloadable plugins are loaded by Pi through jiti, which keeps its own
|
|
231
|
+
* module cache. A plain module-level singleton populated by the server is NOT
|
|
232
|
+
* guaranteed to be the same instance the plugin imports. `globalThis` is shared
|
|
233
|
+
* across every module realm in the process, so a `Symbol.for`-keyed slot is the
|
|
234
|
+
* one storage that both the server and a jiti-loaded plugin observe identically.
|
|
235
|
+
*
|
|
236
|
+
* This module is browser-safe (only `globalThis` + types), so it can live on
|
|
237
|
+
* the `@hachej/boring-workspace/plugin` authoring surface.
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
/** The active workspace `UiBridge`, or `undefined` when none is registered. */
|
|
241
|
+
declare function getWorkspaceUiBridge(): UiBridge | undefined;
|
|
242
|
+
/**
|
|
243
|
+
* Thrown by the plugin-facing helpers when no workspace bridge is active — for
|
|
244
|
+
* example when plugin code runs under a bare Pi CLI with no workspace UI
|
|
245
|
+
* attached. The message is deliberately actionable.
|
|
246
|
+
*/
|
|
247
|
+
declare class NoWorkspaceUiBridgeError extends Error {
|
|
248
|
+
constructor();
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Dispatch an arbitrary UI command through the active workspace bridge. This is
|
|
252
|
+
* the same call the agent's `exec_ui` tool makes; the connected browser drains
|
|
253
|
+
* the command. Prefer the named helpers below for common actions.
|
|
254
|
+
*/
|
|
255
|
+
declare function execWorkspaceUi(command: UiCommand): Promise<CommandResult>;
|
|
256
|
+
interface OpenPanelArgs {
|
|
257
|
+
/** Tab instance id. Reuse the same id to re-activate an existing tab. */
|
|
258
|
+
id: string;
|
|
259
|
+
/** Panel component id (one of the workspace's registered panels). */
|
|
260
|
+
component: string;
|
|
261
|
+
/** Optional params forwarded to the panel component. */
|
|
262
|
+
params?: Record<string, unknown>;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Open an app/plugin panel in the workspace from a plugin slash command.
|
|
266
|
+
* In-process — no URL, no env. Throws `NoWorkspaceUiBridgeError` if no bridge.
|
|
267
|
+
*/
|
|
268
|
+
declare function openPanel(args: OpenPanelArgs): Promise<CommandResult>;
|
|
269
|
+
/**
|
|
270
|
+
* Show a workspace notification (toast) from a plugin slash command. Unlike
|
|
271
|
+
* Pi's `ctx.ui.notify` (a terminal notification that is swallowed in
|
|
272
|
+
* server/headless mode), this surfaces in the browser via the UI bridge.
|
|
273
|
+
*/
|
|
274
|
+
declare function notify(msg: string, level?: "info" | "warn" | "error"): Promise<CommandResult>;
|
|
275
|
+
|
|
276
|
+
export { type BoringFrontAPI, type BoringFrontBindingRegistration, type BoringFrontFactory, type BoringFrontFactoryWithId, type BoringFrontLeftTabRegistration, type BoringFrontPanelCommandRegistration, type BoringFrontPanelRegistration, type BoringFrontProviderRegistration, type BoringFrontSetup, type BoringFrontSurfaceResolverRegistration, type CapturedBoringFrontRegistrations, type CapturedFrontPlugin, type CapturingBoringFrontAPIHandle, type DefinePluginConfig, NoWorkspaceUiBridgeError, type OpenPanelArgs, PaneProps, captureFrontPlugin, createCapturingBoringFrontAPI, definePlugin, execWorkspaceUi, getWorkspaceUiBridge, notify, openPanel };
|
package/dist/plugin.js
CHANGED
|
@@ -29,6 +29,7 @@ function definePlugin(config) {
|
|
|
29
29
|
for (const provider of config.providers ?? []) api.registerProvider(provider);
|
|
30
30
|
for (const binding of config.bindings ?? []) api.registerBinding(binding);
|
|
31
31
|
for (const catalog of config.catalogs ?? []) api.registerCatalog(catalog);
|
|
32
|
+
for (const renderer of config.toolRenderers ?? []) api.registerToolRenderer(renderer);
|
|
32
33
|
if (config.setup) config.setup(api);
|
|
33
34
|
return void 0;
|
|
34
35
|
};
|
|
@@ -57,6 +58,7 @@ function createCapturingBoringFrontAPI(options = {}) {
|
|
|
57
58
|
const panelCommands = [];
|
|
58
59
|
const leftTabs = [];
|
|
59
60
|
const surfaceResolvers = [];
|
|
61
|
+
const toolRenderers = [];
|
|
60
62
|
const seen = /* @__PURE__ */ new Map();
|
|
61
63
|
const claim = (kind, id) => {
|
|
62
64
|
const key = `${kind}:${id}`;
|
|
@@ -104,6 +106,10 @@ function createCapturingBoringFrontAPI(options = {}) {
|
|
|
104
106
|
}
|
|
105
107
|
surfaceResolvers.push(registration);
|
|
106
108
|
},
|
|
109
|
+
registerToolRenderer(registration) {
|
|
110
|
+
claim("tool-renderer", registration.id);
|
|
111
|
+
toolRenderers.push(registration);
|
|
112
|
+
},
|
|
107
113
|
flush() {
|
|
108
114
|
return {
|
|
109
115
|
providers: clone(providers),
|
|
@@ -112,7 +118,8 @@ function createCapturingBoringFrontAPI(options = {}) {
|
|
|
112
118
|
panels: clone(panels),
|
|
113
119
|
panelCommands: clone(panelCommands),
|
|
114
120
|
leftTabs: clone(leftTabs),
|
|
115
|
-
surfaceResolvers: clone(surfaceResolvers)
|
|
121
|
+
surfaceResolvers: clone(surfaceResolvers),
|
|
122
|
+
toolRenderers: clone(toolRenderers)
|
|
116
123
|
};
|
|
117
124
|
}
|
|
118
125
|
};
|
|
@@ -290,12 +297,51 @@ function validateBoringPluginManifest(raw) {
|
|
|
290
297
|
|
|
291
298
|
// src/shared/types/surface.ts
|
|
292
299
|
var WORKSPACE_OPEN_PATH_SURFACE_KIND = "workspace.open.path";
|
|
300
|
+
|
|
301
|
+
// src/shared/plugins/uiBridgeRegistry.ts
|
|
302
|
+
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("@hachej/boring-workspace:active-ui-bridge");
|
|
303
|
+
function slot() {
|
|
304
|
+
return globalThis;
|
|
305
|
+
}
|
|
306
|
+
function getWorkspaceUiBridge() {
|
|
307
|
+
return slot()[REGISTRY_KEY];
|
|
308
|
+
}
|
|
309
|
+
var NoWorkspaceUiBridgeError = class extends Error {
|
|
310
|
+
constructor() {
|
|
311
|
+
super(
|
|
312
|
+
"No workspace UI bridge is active. This plugin command must run inside a boring-ui workspace agent (it cannot open panels from a bare Pi CLI)."
|
|
313
|
+
);
|
|
314
|
+
this.name = "NoWorkspaceUiBridgeError";
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
function requireBridge() {
|
|
318
|
+
const bridge = getWorkspaceUiBridge();
|
|
319
|
+
if (!bridge) throw new NoWorkspaceUiBridgeError();
|
|
320
|
+
return bridge;
|
|
321
|
+
}
|
|
322
|
+
async function execWorkspaceUi(command) {
|
|
323
|
+
return requireBridge().postCommand(command);
|
|
324
|
+
}
|
|
325
|
+
async function openPanel(args) {
|
|
326
|
+
return execWorkspaceUi({
|
|
327
|
+
kind: "openPanel",
|
|
328
|
+
params: { id: args.id, component: args.component, params: args.params }
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
async function notify(msg, level = "info") {
|
|
332
|
+
return execWorkspaceUi({ kind: "showNotification", params: { msg, level } });
|
|
333
|
+
}
|
|
293
334
|
export {
|
|
335
|
+
NoWorkspaceUiBridgeError,
|
|
294
336
|
WORKSPACE_OPEN_PATH_SURFACE_KIND,
|
|
295
337
|
captureFrontPlugin,
|
|
296
338
|
createCapturingBoringFrontAPI,
|
|
297
339
|
definePlugin,
|
|
340
|
+
execWorkspaceUi,
|
|
341
|
+
getWorkspaceUiBridge,
|
|
298
342
|
isSafePluginRelativePath,
|
|
299
343
|
isValidBoringPluginId,
|
|
344
|
+
notify,
|
|
345
|
+
openPanel,
|
|
300
346
|
validateBoringPluginManifest
|
|
301
347
|
};
|
package/dist/server.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { f as WorkspaceServerPluginAsset, g as BoringServerPluginManifest, B as BoringPluginSourceInput, a as BoringPluginFrontTargetResolver, h as BoringPluginListEntry, i as BoringPluginFrontTarget, j as BoringPluginSource, k as BoringPluginEvent, P as PluginRestartSurface } from './createInMemoryBridge-
|
|
2
|
-
export { l as BoringPluginFrontTargetResolverContext, m as BoringPluginNativeFrontTarget, n as BoringPluginNativeFrontTargetTrust, o as BoringPluginSourceKind, S as ServerBootstrapOptions, p as ServerBootstrapResult, b as WorkspaceProvisioningContribution, c as WorkspaceRouteContribution, W as WorkspaceServerPlugin, q as bootstrapServer, d as createInMemoryBridge, r as defineServerPlugin, v as validateServerPlugin } from './createInMemoryBridge-
|
|
1
|
+
import { f as WorkspaceServerPluginAsset, g as BoringServerPluginManifest, B as BoringPluginSourceInput, a as BoringPluginFrontTargetResolver, h as BoringPluginListEntry, i as BoringPluginFrontTarget, j as BoringPluginSource, k as BoringPluginEvent, P as PluginRestartSurface } from './createInMemoryBridge-e7QdNLSA.js';
|
|
2
|
+
export { l as BoringPluginFrontTargetResolverContext, m as BoringPluginNativeFrontTarget, n as BoringPluginNativeFrontTargetTrust, o as BoringPluginSourceKind, S as ServerBootstrapOptions, p as ServerBootstrapResult, b as WorkspaceProvisioningContribution, c as WorkspaceRouteContribution, W as WorkspaceServerPlugin, q as bootstrapServer, d as createInMemoryBridge, r as defineServerPlugin, v as validateServerPlugin } from './createInMemoryBridge-e7QdNLSA.js';
|
|
3
3
|
import { FastifyRequest, FastifyInstance } from 'fastify';
|
|
4
|
-
import { U as UiBridge
|
|
5
|
-
export { C as CommandResult, a as UiCommand, b as UiState } from './ui-bridge-
|
|
4
|
+
import { U as UiBridge } from './ui-bridge-LeBuZqfA.js';
|
|
5
|
+
export { C as CommandResult, a as UiCommand, b as UiState } from './ui-bridge-LeBuZqfA.js';
|
|
6
|
+
import { A as AgentTool } from './agent-tool-CB0RQyx9.js';
|
|
6
7
|
import { PiPackageSource } from '@hachej/boring-agent/server';
|
|
7
8
|
export { PiPackageSource as WorkspacePiPackageSource } from '@hachej/boring-agent/server';
|
|
8
9
|
import { PluginLogger } from './runtime-server.js';
|
|
@@ -226,7 +227,7 @@ interface LoadedBoringPluginPiSnapshot {
|
|
|
226
227
|
}
|
|
227
228
|
type Listener = (event: BoringPluginEvent) => void;
|
|
228
229
|
declare class BoringPluginAssetManager {
|
|
229
|
-
private
|
|
230
|
+
private pluginDirs;
|
|
230
231
|
private readonly errorRoot;
|
|
231
232
|
private readonly frontTargetResolver?;
|
|
232
233
|
private readonly includeLegacyFrontUrl;
|
|
@@ -237,6 +238,14 @@ declare class BoringPluginAssetManager {
|
|
|
237
238
|
private loading;
|
|
238
239
|
private reloadQueued;
|
|
239
240
|
constructor(options: BoringPluginAssetManagerOptions);
|
|
241
|
+
/**
|
|
242
|
+
* Replace the scanned source roots. Lets hosts re-resolve discovery inputs
|
|
243
|
+
* (e.g. workspace `.pi/settings.json` package sources, which can gain
|
|
244
|
+
* entries after `boring-ui-plugin install`) before the next load() so
|
|
245
|
+
* `/reload` picks up newly installed plugin sources without a process
|
|
246
|
+
* restart.
|
|
247
|
+
*/
|
|
248
|
+
setPluginDirs(pluginDirs: BoringPluginSourceInput[]): void;
|
|
240
249
|
preflight(): BoringPluginPreflightResult;
|
|
241
250
|
list(): BoringPluginListEntry[];
|
|
242
251
|
getError(pluginId: string): string | null;
|
package/dist/server.js
CHANGED
|
@@ -1026,6 +1026,12 @@ function buildBoringSystemPrompt(opts) {
|
|
|
1026
1026
|
"- Dependency installs: do NOT install plugin UI dependencies at the workspace root. Install them inside `.pi/extensions/<name>/` and keep React/workspace/boring-ui-kit imports as host singletons, not plugin dependencies.",
|
|
1027
1027
|
"- Hot-reload agent tools: do NOT put them in `.pi/extensions/<name>/server/index.ts`; use `pi.extensions` instead. `boring.server` requires static composition plus process restart."
|
|
1028
1028
|
].join("\n"),
|
|
1029
|
+
[
|
|
1030
|
+
"## Installing an existing or published plugin",
|
|
1031
|
+
"To ADD an existing or published plugin (not author a new one), use `boring-ui-plugin install <source>` via bash \u2014 `<source>` is `npm:<package>`, `git:<repo>`, `github:<owner>/<repo>`, an `http(s)` git URL, or a local path; add `--global` for all workspaces (default is this workspace).",
|
|
1032
|
+
"A bare `npm install <package>` does NOT register it as a plugin (no `.pi/settings.json` package source), so it will NOT load \u2014 always use `boring-ui-plugin install`, then ask the user to `/reload` (a `boring.server` backend also needs a process restart).",
|
|
1033
|
+
"Inspect with `boring-ui-plugin list [--json]`; remove with `boring-ui-plugin remove <id-or-source>`."
|
|
1034
|
+
].join("\n"),
|
|
1029
1035
|
docsBlock
|
|
1030
1036
|
].join("\n\n");
|
|
1031
1037
|
}
|
|
@@ -1624,6 +1630,16 @@ var BoringPluginAssetManager = class {
|
|
|
1624
1630
|
this.frontTargetResolver = options.frontTargetResolver;
|
|
1625
1631
|
this.includeLegacyFrontUrl = options.includeLegacyFrontUrl ?? true;
|
|
1626
1632
|
}
|
|
1633
|
+
/**
|
|
1634
|
+
* Replace the scanned source roots. Lets hosts re-resolve discovery inputs
|
|
1635
|
+
* (e.g. workspace `.pi/settings.json` package sources, which can gain
|
|
1636
|
+
* entries after `boring-ui-plugin install`) before the next load() so
|
|
1637
|
+
* `/reload` picks up newly installed plugin sources without a process
|
|
1638
|
+
* restart.
|
|
1639
|
+
*/
|
|
1640
|
+
setPluginDirs(pluginDirs) {
|
|
1641
|
+
this.pluginDirs = pluginDirs;
|
|
1642
|
+
}
|
|
1627
1643
|
preflight() {
|
|
1628
1644
|
return preflightBoringPlugins(this.pluginDirs);
|
|
1629
1645
|
}
|
package/dist/shared.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { C as CommandResult, U as UiBridge, a as UiCommand, b as UiState } from './ui-bridge-LeBuZqfA.js';
|
|
2
2
|
export { C as CommandConfig, P as PaneProps, a as PanelConfig, b as PanelRegistration, S as SurfaceOpenRequest, c as SurfacePanelResolution, d as SurfaceResolverConfig, e as SurfaceResolverRegistration, W as WORKSPACE_OPEN_PATH_SURFACE_KIND, f as definePanel } from './surface-obE7YwJk.js';
|
|
3
|
+
export { A as AgentTool, J as JSONSchema, T as ToolExecContext, a as ToolResult } from './agent-tool-CB0RQyx9.js';
|
|
3
4
|
import 'react';
|
|
4
5
|
import 'dockview-react';
|
|
5
6
|
|
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-
|
|
4
|
+
import { h as cs, q as fs, o as ps } from "./WorkspaceProvider-CpK401MG.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";
|
|
@@ -1,34 +1,3 @@
|
|
|
1
|
-
type JSONSchema = Record<string, unknown>;
|
|
2
|
-
type ToolReadinessRequirement = 'workspace-fs' | 'sandbox-exec' | 'ui-bridge' | 'runtime-dependencies' | `runtime:${string}`;
|
|
3
|
-
interface ToolExecContext {
|
|
4
|
-
abortSignal: AbortSignal;
|
|
5
|
-
toolCallId: string;
|
|
6
|
-
onUpdate?: (partial: string) => void;
|
|
7
|
-
/** Agent chat/session id executing this tool, when known. */
|
|
8
|
-
sessionId?: string;
|
|
9
|
-
}
|
|
10
|
-
interface ToolResult {
|
|
11
|
-
content: Array<{
|
|
12
|
-
type: "text";
|
|
13
|
-
text: string;
|
|
14
|
-
}>;
|
|
15
|
-
isError?: boolean;
|
|
16
|
-
details?: unknown;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Structural tool contract accepted from workspace plugins and UI tool
|
|
20
|
-
* factories. Kept agent-runtime-neutral so only the app integration layer
|
|
21
|
-
* needs to import @hachej/boring-agent.
|
|
22
|
-
*/
|
|
23
|
-
interface AgentTool {
|
|
24
|
-
name: string;
|
|
25
|
-
description: string;
|
|
26
|
-
promptSnippet?: string;
|
|
27
|
-
readinessRequirements?: ToolReadinessRequirement[];
|
|
28
|
-
parameters: JSONSchema;
|
|
29
|
-
execute(params: Record<string, unknown>, ctx: ToolExecContext): Promise<ToolResult>;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
1
|
interface UiBridge {
|
|
33
2
|
getState(): Promise<UiState | null>;
|
|
34
3
|
setState(state: UiState): Promise<void>;
|
|
@@ -99,4 +68,4 @@ interface CommandResult {
|
|
|
99
68
|
};
|
|
100
69
|
}
|
|
101
70
|
|
|
102
|
-
export type {
|
|
71
|
+
export type { CommandResult as C, UiBridge as U, UiCommand as a, UiState as b };
|