@hachej/boring-workspace 0.1.42 → 0.1.44

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.
@@ -116,10 +116,11 @@ interface CreateWorkspaceAgentServerOptions extends WorkspaceAgentCreateOptions,
116
116
  /**
117
117
  * Install and advertise the boring plugin-authoring runtime.
118
118
  *
119
- * Keep this off for production/hosted workspaces unless a plugin-editing
120
- * experience is explicitly enabled. Remote sandboxes can support authoring,
121
- * but the CLI should be provisioned only for that activated editing mode,
122
- * not for every normal workspace boot.
119
+ * This option is ignored when `externalPlugins` is false. Keep it off for
120
+ * production/hosted workspaces unless a plugin-editing experience is
121
+ * explicitly enabled. Remote sandboxes can support authoring, but the CLI
122
+ * should be provisioned only for that activated editing mode, not for every
123
+ * normal workspace boot.
123
124
  *
124
125
  * Defaults to true for local/standalone strong-filesystem runtimes and false
125
126
  * for remote/best-effort runtimes. Core/full-app may choose a stricter
@@ -128,6 +129,14 @@ interface CreateWorkspaceAgentServerOptions extends WorkspaceAgentCreateOptions,
128
129
  installPluginAuthoring?: boolean;
129
130
  /** Optional host-owned front-target override for boring plugin list/event payloads. */
130
131
  boringPluginFrontTargetResolver?: BoringPluginFrontTargetResolver;
132
+ /**
133
+ * Single public-mode switch for user/global external plugins. When false,
134
+ * the server disables .pi/~/.pi/Pi-settings discovery, authoring CLI/prompt
135
+ * provisioning, plugin diagnostics, and external hot-reload resources. App/
136
+ * internal plugins from explicit `plugins`, `defaultPluginPackages`, and
137
+ * `additionalBoringPluginDirs` continue to work.
138
+ */
139
+ externalPlugins?: boolean;
131
140
  }
132
141
  declare const PLUGIN_AUTHORING_PROVISIONING_IDS: Set<string>;
133
142
  declare function omitPluginAuthoringProvisioning(plugins: WorkspaceRuntimeProvisioningInput[]): WorkspaceRuntimeProvisioningInput[];
@@ -145,7 +154,9 @@ interface CollectWorkspaceAgentServerPluginsOptions extends Pick<ServerBootstrap
145
154
  /** Whether to include built-in boring plugin-authoring provisioning/prompt resources. */
146
155
  installPluginAuthoring?: boolean;
147
156
  }
148
- declare function buildWorkspaceContextPrompt(): string;
157
+ declare function buildWorkspaceContextPrompt(options?: {
158
+ pluginAuthoringEnabled?: boolean;
159
+ }): string;
149
160
  declare function collectWorkspaceAgentServerPlugins(opts?: CollectWorkspaceAgentServerPluginsOptions): WorkspaceAgentServerPluginCollection;
150
161
  declare function provisionWorkspaceAgentServer(opts: {
151
162
  workspaceRoot: string;
@@ -1070,7 +1070,7 @@ var BoringPluginAssetManager = class {
1070
1070
  additionalSkillPaths: [...new Set(plugins.flatMap((plugin) => plugin.skillPaths ?? []).map(skillPathForPiLoader))],
1071
1071
  packages: compactPiPackages(normalizeBoringPluginPiPackages(plugins)),
1072
1072
  extensionPaths: plugins.flatMap((plugin) => plugin.extensionPaths ?? []),
1073
- ...prompts.length > 0 ? { systemPromptAppend: `# Loaded boring-ui plugin context
1073
+ ...prompts.length > 0 ? { systemPromptAppend: `# Loaded app-provided context
1074
1074
 
1075
1075
  ${prompts.join("\n\n")}` } : {}
1076
1076
  };
@@ -1824,7 +1824,7 @@ async function runtimeBackendGateway(app, opts) {
1824
1824
  function aggregatePluginPrompts(manager) {
1825
1825
  const prompts = manager.list().map((plugin) => plugin.pi?.systemPrompt?.trim()).filter((prompt) => Boolean(prompt));
1826
1826
  if (prompts.length === 0) return void 0;
1827
- return `# Loaded boring-ui plugin context
1827
+ return `# Loaded app-provided context
1828
1828
 
1829
1829
  ${prompts.join("\n\n")}`;
1830
1830
  }
@@ -2182,14 +2182,14 @@ function createExecUiTool(uiBridge, opts = {}) {
2182
2182
  " params:{seriesId:'GDPC1'}}}",
2183
2183
  "",
2184
2184
  " openSurface params: { kind: string, target: string, meta?: object }",
2185
- " \u2014 Open a plugin-owned target through the workspace",
2186
- " surface resolver registry. Use this when a plugin",
2185
+ " \u2014 Open an app-owned target through the workspace",
2186
+ " surface resolver registry. Use this when the app",
2187
2187
  " defines the mapping from domain target to panel",
2188
2188
  " component, for example a catalog row.",
2189
2189
  " Example: {kind:'openSurface', params:{",
2190
- " kind:'my-plugin.open-row',",
2190
+ " kind:'catalog.open-row',",
2191
2191
  " target:'orders_daily',",
2192
- " meta:{catalogId:'my-plugin'}}}",
2192
+ " meta:{catalogId:'data-catalog'}}}",
2193
2193
  "",
2194
2194
  " closePanel params: { id: string }",
2195
2195
  " closeWorkbenchLeftPane params: {}",
@@ -2721,13 +2721,18 @@ function resolveBoringPiSkillPaths(workspaceRoot) {
2721
2721
  const skillFile = join7(root, "skills", "boring-plugin-authoring", "SKILL.md");
2722
2722
  return existsSync7(skillFile) ? [skillFile] : [];
2723
2723
  }
2724
- function buildWorkspaceContextPrompt() {
2724
+ function buildWorkspaceContextPrompt(options = {}) {
2725
2725
  return [
2726
2726
  "## Workspace",
2727
2727
  "- Root: `$BORING_AGENT_WORKSPACE_ROOT` (exported into every bash invocation)",
2728
- "- Generated plugin skills: `$BORING_AGENT_WORKSPACE_ROOT/.boring-agent/skills/` \u2014 readable with normal file tools",
2729
2728
  "- User workspace skills: `$BORING_AGENT_WORKSPACE_ROOT/.agents/skills/`",
2730
- "- Runtime CLIs (`boring-ui-plugin`, `bm`, `python`, `pip`, `uv`) come from `.boring-agent/node`, `.boring-agent/venv`, and `.boring-agent/sdk/uv` and are already on PATH"
2729
+ ...options.pluginAuthoringEnabled ? [
2730
+ "- Generated plugin skills: `$BORING_AGENT_WORKSPACE_ROOT/.boring-agent/skills/` \u2014 readable with normal file tools",
2731
+ "- Runtime CLIs (`boring-ui-plugin`, `bm`, `python`, `pip`, `uv`) come from `.boring-agent/node`, `.boring-agent/venv`, and `.boring-agent/sdk/uv` and are already on PATH"
2732
+ ] : [
2733
+ "- Runtime CLIs (`bm`, `python`, `pip`, `uv`) come from `.boring-agent/node`, `.boring-agent/venv`, and `.boring-agent/sdk/uv` when provisioned",
2734
+ "- This public app does not expose Boring plugin creation or installation. If asked about Boring plugins, do not explain how to create/install them; say that this app does not expose that feature and continue with normal workspace tasks."
2735
+ ]
2731
2736
  ].join("\n");
2732
2737
  }
2733
2738
  function collectWorkspaceAgentServerPlugins(opts = {}) {
@@ -2821,7 +2826,7 @@ function readPiSettingsBoringPluginSources(settingsPath, workspaceId) {
2821
2826
  }))
2822
2827
  );
2823
2828
  }
2824
- function collectBoringPluginSources(workspaceRoot, pluginCollection, additionalPluginDirs = []) {
2829
+ function collectBoringPluginSources(workspaceRoot, pluginCollection, additionalPluginDirs = [], externalPluginsEnabled = true) {
2825
2830
  const extensionPaths = pluginCollection.agentOptions.pi?.extensionPaths ?? [];
2826
2831
  const pluginRoots = extensionPaths.flatMap((path) => {
2827
2832
  try {
@@ -2830,13 +2835,16 @@ function collectBoringPluginSources(workspaceRoot, pluginCollection, additionalP
2830
2835
  return [];
2831
2836
  }
2832
2837
  });
2833
- return uniquePluginSources([
2838
+ const externalSources = externalPluginsEnabled ? [
2834
2839
  { rootDir: join7(workspaceRoot, ".pi", "extensions"), kind: "external", workspaceId: workspaceRoot },
2835
2840
  { rootDir: join7(workspaceRoot, ".pi", "npm"), kind: "external", workspaceId: workspaceRoot },
2836
2841
  { rootDir: join7(workspaceRoot, ".pi", "git"), kind: "external", workspaceId: workspaceRoot },
2837
2842
  { rootDir: join7(homedir(), ".pi", "agent", "extensions"), kind: "external" },
2838
2843
  ...readPiSettingsBoringPluginSources(join7(workspaceRoot, ".pi", "settings.json"), workspaceRoot),
2839
- ...readPiSettingsBoringPluginSources(join7(homedir(), ".pi", "agent", "settings.json")),
2844
+ ...readPiSettingsBoringPluginSources(join7(homedir(), ".pi", "agent", "settings.json"))
2845
+ ] : [];
2846
+ return uniquePluginSources([
2847
+ ...externalSources,
2840
2848
  ...pluginRoots.map((rootDir) => ({ rootDir, kind: "internal" })),
2841
2849
  ...additionalPluginDirs.map((entry) => typeof entry === "string" ? { rootDir: entry, kind: "internal" } : entry)
2842
2850
  ]);
@@ -2886,7 +2894,7 @@ function readWorkspacePluginPackageRuntimePlugins(pluginDirs) {
2886
2894
  function aggregatePluginSystemPromptsFromScan(scan) {
2887
2895
  const prompts = scan.plugins.map((plugin) => plugin.pi?.systemPrompt?.trim()).filter((prompt) => Boolean(prompt));
2888
2896
  if (prompts.length === 0) return void 0;
2889
- return `# Loaded boring-ui plugin context
2897
+ return `# Loaded app-provided context
2890
2898
 
2891
2899
  ${prompts.join("\n\n")}`;
2892
2900
  }
@@ -2919,6 +2927,7 @@ async function createWorkspaceAgentServer(opts = {}) {
2919
2927
  const modeAdapter = opts.runtimeModeAdapter ?? resolveMode(resolvedMode);
2920
2928
  const workspaceFsCapability = modeAdapter.workspaceFsCapability ?? "best-effort";
2921
2929
  const validateUiPaths = opts.validateUiPaths ?? workspaceFsCapability === "strong";
2930
+ const externalPluginsEnabled = opts.externalPlugins !== false;
2922
2931
  const uiTools = createWorkspaceUiTools(bridge, {
2923
2932
  workspaceRoot: validateUiPaths ? workspaceRoot : void 0
2924
2933
  });
@@ -2936,7 +2945,7 @@ async function createWorkspaceAgentServer(opts = {}) {
2936
2945
  const resolvedPlugins = await Promise.all(
2937
2946
  allPluginEntries.map((entry) => resolveOnePluginEntry(entry, ctx))
2938
2947
  );
2939
- const pluginAuthoringEnabled = (opts.installPluginAuthoring ?? workspaceFsCapability === "strong") && !(opts.excludeDefaults ?? []).includes("boring-ui-plugin-cli-package");
2948
+ const pluginAuthoringEnabled = externalPluginsEnabled && (opts.installPluginAuthoring ?? workspaceFsCapability === "strong") && !(opts.excludeDefaults ?? []).includes("boring-ui-plugin-cli-package");
2940
2949
  const pluginCollection = collectWorkspaceAgentServerPlugins({
2941
2950
  ...opts,
2942
2951
  plugins: resolvedPlugins,
@@ -2956,7 +2965,7 @@ async function createWorkspaceAgentServer(opts = {}) {
2956
2965
  const refreshBoringPluginDirs = () => {
2957
2966
  const next = uniquePluginSources([
2958
2967
  ...defaultPluginPackagePaths.map((rootDir) => ({ rootDir, kind: "internal" })),
2959
- ...collectBoringPluginSources(workspaceRoot, pluginCollection, opts.additionalBoringPluginDirs)
2968
+ ...collectBoringPluginSources(workspaceRoot, pluginCollection, opts.additionalBoringPluginDirs, externalPluginsEnabled)
2960
2969
  ]);
2961
2970
  boringPluginDirs.splice(0, boringPluginDirs.length, ...next);
2962
2971
  return boringPluginDirs;
@@ -3022,13 +3031,14 @@ async function createWorkspaceAgentServer(opts = {}) {
3022
3031
  ...opts,
3023
3032
  mode: resolvedMode,
3024
3033
  workspaceRoot,
3034
+ externalPlugins: externalPluginsEnabled,
3025
3035
  extraTools: [
3026
3036
  ...opts.extraTools ?? [],
3027
3037
  ...uiTools,
3028
3038
  ...pluginCollection.agentOptions.extraTools ?? []
3029
3039
  ],
3030
3040
  systemPromptAppend: [
3031
- workspaceFsCapability === "strong" ? buildWorkspaceContextPrompt() : void 0,
3041
+ workspaceFsCapability === "strong" ? buildWorkspaceContextPrompt({ pluginAuthoringEnabled }) : void 0,
3032
3042
  // `boring-ui-plugin` resolves via PATH from the provisioned workspace
3033
3043
  // runtime. It is the slim setup component for agent-authored plugins;
3034
3044
  // do not route plugin authoring through the full human-facing CLI.
package/dist/server.js CHANGED
@@ -508,14 +508,14 @@ function createExecUiTool(uiBridge, opts = {}) {
508
508
  " params:{seriesId:'GDPC1'}}}",
509
509
  "",
510
510
  " openSurface params: { kind: string, target: string, meta?: object }",
511
- " \u2014 Open a plugin-owned target through the workspace",
512
- " surface resolver registry. Use this when a plugin",
511
+ " \u2014 Open an app-owned target through the workspace",
512
+ " surface resolver registry. Use this when the app",
513
513
  " defines the mapping from domain target to panel",
514
514
  " component, for example a catalog row.",
515
515
  " Example: {kind:'openSurface', params:{",
516
- " kind:'my-plugin.open-row',",
516
+ " kind:'catalog.open-row',",
517
517
  " target:'orders_daily',",
518
- " meta:{catalogId:'my-plugin'}}}",
518
+ " meta:{catalogId:'data-catalog'}}}",
519
519
  "",
520
520
  " closePanel params: { id: string }",
521
521
  " closeWorkbenchLeftPane params: {}",
@@ -1700,7 +1700,7 @@ var BoringPluginAssetManager = class {
1700
1700
  additionalSkillPaths: [...new Set(plugins.flatMap((plugin) => plugin.skillPaths ?? []).map(skillPathForPiLoader))],
1701
1701
  packages: compactPiPackages(normalizeBoringPluginPiPackages(plugins)),
1702
1702
  extensionPaths: plugins.flatMap((plugin) => plugin.extensionPaths ?? []),
1703
- ...prompts.length > 0 ? { systemPromptAppend: `# Loaded boring-ui plugin context
1703
+ ...prompts.length > 0 ? { systemPromptAppend: `# Loaded app-provided context
1704
1704
 
1705
1705
  ${prompts.join("\n\n")}` } : {}
1706
1706
  };
@@ -1968,7 +1968,7 @@ async function boringPluginRoutes(app, opts) {
1968
1968
  function aggregatePluginPrompts(manager) {
1969
1969
  const prompts = manager.list().map((plugin) => plugin.pi?.systemPrompt?.trim()).filter((prompt) => Boolean(prompt));
1970
1970
  if (prompts.length === 0) return void 0;
1971
- return `# Loaded boring-ui plugin context
1971
+ return `# Loaded app-provided context
1972
1972
 
1973
1973
  ${prompts.join("\n\n")}`;
1974
1974
  }
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-DkZAxsYo.js";
4
+ import { h as cs, q as fs, o as ps } from "./WorkspaceProvider-CSwoKjTp.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";
package/dist/workspace.js CHANGED
@@ -1,17 +1,17 @@
1
1
  var V = Object.defineProperty;
2
2
  var X = (e, t, r) => t in e ? V(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
3
3
  var T = (e, t, r) => X(e, typeof t != "symbol" ? t + "" : t, r);
4
- import { u as K, p as Q, a as Y, b as Z, D as ee } from "./WorkspaceProvider-DkZAxsYo.js";
5
- import { A as Je, C as Ge, c as Ve, d as Xe, e as Qe, F as Ye, f as Ze, M as et, g as tt, P as rt, h as at, i as nt, j as st, k as ot, R as it, S as lt, l as ct, m as dt, T as ut, U as pt, W as ft, n as mt, o as ht, q as gt, r as bt, s as yt, t as vt, v as xt, w as kt, x as wt, y as Pt, z as St, B as Ct, E as Nt, G as Et, H as Rt, I as Tt, J as It, K as Ot, L as Ft, N as Lt, O as Mt, Q as Bt, V as Wt, X as Dt, Y as Kt, Z as $t, _ as jt, $ as zt, a0 as Ht, a1 as Ut, a2 as _t, a3 as qt, a4 as At, a5 as Jt, a6 as Gt, a7 as Vt, a8 as Xt, a9 as Qt, aa as Yt, ab as Zt, ac as er, ad as tr, ae as rr, af as ar, ag as nr, ah as sr, ai as or, aj as ir, ak as lr, al as cr, am as dr, an as ur, ao as pr, ap as fr, aq as mr, ar as hr, as as gr } from "./WorkspaceProvider-DkZAxsYo.js";
4
+ import { u as K, p as Q, a as Y, b as Z, D as ee } from "./WorkspaceProvider-CSwoKjTp.js";
5
+ import { A as Je, C as Ge, c as Ve, d as Xe, e as Qe, F as Ye, f as Ze, M as et, g as tt, P as rt, h as at, i as nt, j as st, k as ot, R as it, S as lt, l as ct, m as dt, T as ut, U as pt, W as ft, n as mt, o as ht, q as gt, r as bt, s as yt, t as vt, v as xt, w as kt, x as wt, y as Pt, z as St, B as Ct, E as Nt, G as Et, H as Rt, I as Tt, J as It, K as Ot, L as Ft, N as Lt, O as Mt, Q as Bt, V as Wt, X as Dt, Y as Kt, Z as $t, _ as jt, $ as zt, a0 as Ht, a1 as Ut, a2 as _t, a3 as qt, a4 as At, a5 as Jt, a6 as Gt, a7 as Vt, a8 as Xt, a9 as Qt, aa as Yt, ab as Zt, ac as er, ad as tr, ae as rr, af as ar, ag as nr, ah as sr, ai as or, aj as ir, ak as lr, al as cr, am as dr, an as ur, ao as pr, ap as fr, aq as mr, ar as hr, as as gr } from "./WorkspaceProvider-CSwoKjTp.js";
6
6
  import { c as C } from "./utils-B6yFEsav.js";
7
- import { C as yr, T as vr, W as xr, b as kr } from "./WorkspaceLoadingState-yp4vNmrT.js";
7
+ import { C as yr, T as vr, W as xr, b as kr } from "./WorkspaceLoadingState-BoFzsDji.js";
8
8
  import { jsx as a, jsxs as g, Fragment as te } from "react/jsx-runtime";
9
9
  import { Button as P, Sheet as re, SheetContent as ae, SheetHeader as ne, SheetTitle as se, SheetDescription as oe, EmptyState as ie, Kbd as I, ErrorState as le, IconButton as O } from "@hachej/boring-ui-kit";
10
10
  import { Toaster as Pr, dismissToast as Sr, toast as Cr } from "@hachej/boring-ui-kit";
11
11
  import { useSyncExternalStore as $, useState as N, useEffect as k, useRef as S, useCallback as b, useMemo as w, Suspense as ce, Component as de } from "react";
12
12
  import { C as Er, c as Rr } from "./CodeEditor-DQqOn4xz.js";
13
- import { FileTree as Ir } from "./FileTree-CVsvICGP.js";
14
- import { MarkdownEditor as Fr } from "./MarkdownEditor-BvaGmzWP.js";
13
+ import { FileTree as Ir } from "./FileTree-DKzSeYJX.js";
14
+ import { MarkdownEditor as Fr } from "./MarkdownEditor-FJtYn6Xx.js";
15
15
  import { MenuIcon as ue, PanelLeftOpenIcon as pe, PanelLeftCloseIcon as fe, PinIcon as me, CheckIcon as he, CopyIcon as ge } from "lucide-react";
16
16
  import { d as Mr } from "./panel-DnvDNQac.js";
17
17
  function We() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hachej/boring-workspace",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
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.",
@@ -135,9 +135,9 @@
135
135
  "tailwind-merge": "^2.0.0",
136
136
  "zod": "^3.23.0",
137
137
  "zustand": "^5.0.0",
138
- "@hachej/boring-agent": "0.1.42",
139
- "@hachej/boring-ui-kit": "0.1.42",
140
- "@hachej/boring-ui-plugin-cli": "0.1.42"
138
+ "@hachej/boring-agent": "0.1.44",
139
+ "@hachej/boring-ui-plugin-cli": "0.1.44",
140
+ "@hachej/boring-ui-kit": "0.1.44"
141
141
  },
142
142
  "devDependencies": {
143
143
  "@tailwindcss/postcss": "^4.0.0",