@hachej/boring-workspace 0.1.40 → 0.1.42
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 +26 -261
- package/dist/{FileTree-DNIzusWa.js → FileTree-CVsvICGP.js} +1 -1
- package/dist/MarkdownEditor-BvaGmzWP.js +582 -0
- package/dist/{WorkspaceLoadingState-EratTJfG.js → WorkspaceLoadingState-yp4vNmrT.js} +21 -22
- package/dist/{WorkspaceProvider-uuxyAx3i.js → WorkspaceProvider-DkZAxsYo.js} +2902 -2741
- package/dist/app-front.d.ts +5 -0
- package/dist/app-front.js +221 -217
- package/dist/app-server.d.ts +2 -2
- package/dist/app-server.js +23 -5
- package/dist/{createInMemoryBridge-DSjZ9efK.d.ts → createInMemoryBridge-siFWq_R_.d.ts} +8 -0
- package/dist/plugin.d.ts +4 -2
- package/dist/server.d.ts +3 -3
- package/dist/server.js +23 -5
- package/dist/shared.d.ts +1 -1
- package/dist/{surface-obE7YwJk.d.ts → surface-DmIalUmP.d.ts} +2 -0
- package/dist/testing.d.ts +2 -0
- package/dist/testing.js +1 -1
- package/dist/workspace.css +112 -16
- package/dist/workspace.d.ts +8 -2
- package/dist/workspace.js +5 -5
- package/docs/INTERFACES.md +1 -1
- package/docs/PLUGIN_STRUCTURE.md +3 -3
- package/docs/PLUGIN_SYSTEM.md +46 -4
- package/docs/README.md +85 -22
- package/package.json +4 -4
- package/dist/MarkdownEditor-DhVfKSAq.js +0 -549
- /package/docs/plans/{ASK_USER_QUESTIONS_PLUGIN_SPEC.md → archive/ASK_USER_QUESTIONS_PLUGIN_SPEC.md} +0 -0
- /package/docs/plans/{FULL_PAGE_PANEL_ROUTE_SPEC.md → archive/FULL_PAGE_PANEL_ROUTE_SPEC.md} +0 -0
- /package/docs/plans/{GENERIC_EXPLORER_PLUGIN_PLAN.md → archive/GENERIC_EXPLORER_PLUGIN_PLAN.md} +0 -0
- /package/docs/plans/{PANE_TO_AGENT_CHAT_ACTIONS_SPEC.md → archive/PANE_TO_AGENT_CHAT_ACTIONS_SPEC.md} +0 -0
- /package/docs/plans/{PLUGIN_OUTPUTS_ISOLATION_PLAN.md → archive/PLUGIN_OUTPUTS_ISOLATION_PLAN.md} +0 -0
- /package/docs/plans/{README.md → archive/README.md} +0 -0
- /package/docs/plans/{UI_BRIDGE_OWNERSHIP_REFACTOR.md → archive/UI_BRIDGE_OWNERSHIP_REFACTOR.md} +0 -0
package/dist/app-server.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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-siFWq_R_.js';
|
|
5
|
+
export { e as ServerWorkspaceRuntimeProvisioningInput } from './createInMemoryBridge-siFWq_R_.js';
|
|
6
6
|
import './manifest-C2vVgH_e.js';
|
|
7
7
|
import './agent-tool-CB0RQyx9.js';
|
|
8
8
|
import './ui-bridge-LeBuZqfA.js';
|
package/dist/app-server.js
CHANGED
|
@@ -360,7 +360,8 @@ function normalizeBoringPluginSource(input) {
|
|
|
360
360
|
return {
|
|
361
361
|
rootDir: resolve2(input.rootDir),
|
|
362
362
|
kind: input.kind,
|
|
363
|
-
...input.workspaceId ? { workspaceId: input.workspaceId } : {}
|
|
363
|
+
...input.workspaceId ? { workspaceId: input.workspaceId } : {},
|
|
364
|
+
...input.registered ? { registered: true } : {}
|
|
364
365
|
};
|
|
365
366
|
}
|
|
366
367
|
function pluginIdFromPackageJson(pkg, rootDir) {
|
|
@@ -423,10 +424,14 @@ function packagePathContainmentIssues(rootDir, pkg) {
|
|
|
423
424
|
function discoverBoringPluginDirs(pluginDirs) {
|
|
424
425
|
const out = /* @__PURE__ */ new Map();
|
|
425
426
|
const missingPackageJson = [];
|
|
427
|
+
const missingDirs = [];
|
|
426
428
|
for (const raw of pluginDirs) {
|
|
427
429
|
const source = normalizeBoringPluginSource(raw);
|
|
428
430
|
const dir = source.rootDir;
|
|
429
|
-
if (!existsSync2(dir))
|
|
431
|
+
if (!existsSync2(dir)) {
|
|
432
|
+
if (source.registered) missingDirs.push(dir);
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
430
435
|
const info = statSync(dir);
|
|
431
436
|
if (!info.isDirectory()) continue;
|
|
432
437
|
const hasPackageJson = existsSync2(join2(dir, "package.json"));
|
|
@@ -441,13 +446,14 @@ function discoverBoringPluginDirs(pluginDirs) {
|
|
|
441
446
|
if (!out.has(child)) out.set(child, { ...source, rootDir: child });
|
|
442
447
|
}
|
|
443
448
|
const collectionDirNames = /* @__PURE__ */ new Set(["extensions", "npm", "git"]);
|
|
444
|
-
if (!hasPackageJson && childPackageDirs.length === 0 && !collectionDirNames.has(basename(dir))) {
|
|
449
|
+
if (!hasPackageJson && (source.registered || childPackageDirs.length === 0 && !collectionDirNames.has(basename(dir)))) {
|
|
445
450
|
missingPackageJson.push(dir);
|
|
446
451
|
}
|
|
447
452
|
}
|
|
448
453
|
return {
|
|
449
454
|
sources: [...out.values()].sort((a, b) => a.rootDir.localeCompare(b.rootDir)),
|
|
450
|
-
missingPackageJson: [...new Set(missingPackageJson)].sort()
|
|
455
|
+
missingPackageJson: [...new Set(missingPackageJson)].sort(),
|
|
456
|
+
missingDirs: [...new Set(missingDirs)].sort()
|
|
451
457
|
};
|
|
452
458
|
}
|
|
453
459
|
function scanBoringPlugins(pluginDirs) {
|
|
@@ -455,6 +461,9 @@ function scanBoringPlugins(pluginDirs) {
|
|
|
455
461
|
const plugins = [];
|
|
456
462
|
const seenIds = /* @__PURE__ */ new Map();
|
|
457
463
|
const discovered = discoverBoringPluginDirs(pluginDirs);
|
|
464
|
+
for (const pluginDir of discovered.missingDirs) {
|
|
465
|
+
errors.push({ pluginDir, code: "MISSING_PLUGIN_DIR", message: "registered plugin source directory does not exist" });
|
|
466
|
+
}
|
|
458
467
|
for (const pluginDir of discovered.missingPackageJson) {
|
|
459
468
|
errors.push({ pluginDir, code: "MISSING_PACKAGE_JSON", message: "package.json is missing" });
|
|
460
469
|
}
|
|
@@ -471,7 +480,16 @@ function scanBoringPlugins(pluginDirs) {
|
|
|
471
480
|
});
|
|
472
481
|
continue;
|
|
473
482
|
}
|
|
474
|
-
if (!hasPluginMetadata(raw))
|
|
483
|
+
if (!hasPluginMetadata(raw)) {
|
|
484
|
+
if (source.registered) {
|
|
485
|
+
errors.push({
|
|
486
|
+
pluginDir: rootDir,
|
|
487
|
+
code: "INVALID_PLUGIN_METADATA",
|
|
488
|
+
message: 'package.json has no "boring" or "pi" plugin metadata'
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
475
493
|
const result = validateBoringPluginManifest(raw);
|
|
476
494
|
if (!result.valid) {
|
|
477
495
|
const pluginId = safePluginIdFromPackageJson(raw, rootDir);
|
|
@@ -60,6 +60,14 @@ interface BoringPluginSource {
|
|
|
60
60
|
rootDir: string;
|
|
61
61
|
kind: BoringPluginSourceKind;
|
|
62
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;
|
|
63
71
|
}
|
|
64
72
|
type BoringPluginSourceInput = string | BoringPluginSource;
|
|
65
73
|
interface BoringServerPluginManifest {
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ComponentType, ReactNode } from 'react';
|
|
2
|
-
import { P as PaneProps, a as PanelConfig, S as SurfaceOpenRequest, c as SurfacePanelResolution } from './surface-
|
|
3
|
-
export { W as WORKSPACE_OPEN_PATH_SURFACE_KIND } from './surface-
|
|
2
|
+
import { P as PaneProps, a as PanelConfig, S as SurfaceOpenRequest, c as SurfacePanelResolution } from './surface-DmIalUmP.js';
|
|
3
|
+
export { W as WORKSPACE_OPEN_PATH_SURFACE_KIND } from './surface-DmIalUmP.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
5
|
import { a as UiCommand, C as CommandResult, U as UiBridge } from './ui-bridge-LeBuZqfA.js';
|
|
6
6
|
import 'dockview-react';
|
|
@@ -70,6 +70,8 @@ interface LeftTabParams {
|
|
|
70
70
|
searchQuery?: string;
|
|
71
71
|
bridge?: unknown;
|
|
72
72
|
chromeless?: boolean;
|
|
73
|
+
/** Optional DOM target for left-tab toolbar actions owned by the pane. */
|
|
74
|
+
chromeActionsElement?: Element | null;
|
|
73
75
|
revealFileTreeRequest?: {
|
|
74
76
|
path: string;
|
|
75
77
|
seq: number;
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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-siFWq_R_.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-siFWq_R_.js';
|
|
3
3
|
import { FastifyRequest, FastifyInstance } from 'fastify';
|
|
4
4
|
import { U as UiBridge } from './ui-bridge-LeBuZqfA.js';
|
|
5
5
|
export { C as CommandResult, a as UiCommand, b as UiState } from './ui-bridge-LeBuZqfA.js';
|
|
@@ -164,7 +164,7 @@ declare function buildBoringSystemPrompt(opts: BuildBoringSystemPromptOptions):
|
|
|
164
164
|
interface BoringPluginPreflightIssue {
|
|
165
165
|
pluginDir: string;
|
|
166
166
|
pluginId?: string;
|
|
167
|
-
code: "MISSING_PACKAGE_JSON" | "INVALID_PACKAGE_JSON" | "INVALID_PLUGIN_METADATA";
|
|
167
|
+
code: "MISSING_PLUGIN_DIR" | "MISSING_PACKAGE_JSON" | "INVALID_PACKAGE_JSON" | "INVALID_PLUGIN_METADATA";
|
|
168
168
|
message: string;
|
|
169
169
|
}
|
|
170
170
|
interface BoringPluginPreflightResult {
|
package/dist/server.js
CHANGED
|
@@ -1238,7 +1238,8 @@ function normalizeBoringPluginSource(input) {
|
|
|
1238
1238
|
return {
|
|
1239
1239
|
rootDir: resolve3(input.rootDir),
|
|
1240
1240
|
kind: input.kind,
|
|
1241
|
-
...input.workspaceId ? { workspaceId: input.workspaceId } : {}
|
|
1241
|
+
...input.workspaceId ? { workspaceId: input.workspaceId } : {},
|
|
1242
|
+
...input.registered ? { registered: true } : {}
|
|
1242
1243
|
};
|
|
1243
1244
|
}
|
|
1244
1245
|
function pluginIdFromPackageJson(pkg, rootDir) {
|
|
@@ -1301,10 +1302,14 @@ function packagePathContainmentIssues(rootDir, pkg) {
|
|
|
1301
1302
|
function discoverBoringPluginDirs(pluginDirs) {
|
|
1302
1303
|
const out = /* @__PURE__ */ new Map();
|
|
1303
1304
|
const missingPackageJson = [];
|
|
1305
|
+
const missingDirs = [];
|
|
1304
1306
|
for (const raw of pluginDirs) {
|
|
1305
1307
|
const source = normalizeBoringPluginSource(raw);
|
|
1306
1308
|
const dir = source.rootDir;
|
|
1307
|
-
if (!existsSync2(dir))
|
|
1309
|
+
if (!existsSync2(dir)) {
|
|
1310
|
+
if (source.registered) missingDirs.push(dir);
|
|
1311
|
+
continue;
|
|
1312
|
+
}
|
|
1308
1313
|
const info = statSync(dir);
|
|
1309
1314
|
if (!info.isDirectory()) continue;
|
|
1310
1315
|
const hasPackageJson = existsSync2(join3(dir, "package.json"));
|
|
@@ -1319,13 +1324,14 @@ function discoverBoringPluginDirs(pluginDirs) {
|
|
|
1319
1324
|
if (!out.has(child)) out.set(child, { ...source, rootDir: child });
|
|
1320
1325
|
}
|
|
1321
1326
|
const collectionDirNames = /* @__PURE__ */ new Set(["extensions", "npm", "git"]);
|
|
1322
|
-
if (!hasPackageJson && childPackageDirs.length === 0 && !collectionDirNames.has(basename(dir))) {
|
|
1327
|
+
if (!hasPackageJson && (source.registered || childPackageDirs.length === 0 && !collectionDirNames.has(basename(dir)))) {
|
|
1323
1328
|
missingPackageJson.push(dir);
|
|
1324
1329
|
}
|
|
1325
1330
|
}
|
|
1326
1331
|
return {
|
|
1327
1332
|
sources: [...out.values()].sort((a, b) => a.rootDir.localeCompare(b.rootDir)),
|
|
1328
|
-
missingPackageJson: [...new Set(missingPackageJson)].sort()
|
|
1333
|
+
missingPackageJson: [...new Set(missingPackageJson)].sort(),
|
|
1334
|
+
missingDirs: [...new Set(missingDirs)].sort()
|
|
1329
1335
|
};
|
|
1330
1336
|
}
|
|
1331
1337
|
function scanBoringPlugins(pluginDirs) {
|
|
@@ -1333,6 +1339,9 @@ function scanBoringPlugins(pluginDirs) {
|
|
|
1333
1339
|
const plugins = [];
|
|
1334
1340
|
const seenIds = /* @__PURE__ */ new Map();
|
|
1335
1341
|
const discovered = discoverBoringPluginDirs(pluginDirs);
|
|
1342
|
+
for (const pluginDir of discovered.missingDirs) {
|
|
1343
|
+
errors.push({ pluginDir, code: "MISSING_PLUGIN_DIR", message: "registered plugin source directory does not exist" });
|
|
1344
|
+
}
|
|
1336
1345
|
for (const pluginDir of discovered.missingPackageJson) {
|
|
1337
1346
|
errors.push({ pluginDir, code: "MISSING_PACKAGE_JSON", message: "package.json is missing" });
|
|
1338
1347
|
}
|
|
@@ -1349,7 +1358,16 @@ function scanBoringPlugins(pluginDirs) {
|
|
|
1349
1358
|
});
|
|
1350
1359
|
continue;
|
|
1351
1360
|
}
|
|
1352
|
-
if (!hasPluginMetadata(raw))
|
|
1361
|
+
if (!hasPluginMetadata(raw)) {
|
|
1362
|
+
if (source.registered) {
|
|
1363
|
+
errors.push({
|
|
1364
|
+
pluginDir: rootDir,
|
|
1365
|
+
code: "INVALID_PLUGIN_METADATA",
|
|
1366
|
+
message: 'package.json has no "boring" or "pi" plugin metadata'
|
|
1367
|
+
});
|
|
1368
|
+
}
|
|
1369
|
+
continue;
|
|
1370
|
+
}
|
|
1353
1371
|
const result = validateBoringPluginManifest(raw);
|
|
1354
1372
|
if (!result.valid) {
|
|
1355
1373
|
const pluginId = safePluginIdFromPackageJson(raw, rootDir);
|
package/dist/shared.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { C as CommandResult, U as UiBridge, a as UiCommand, b as UiState } from './ui-bridge-LeBuZqfA.js';
|
|
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-
|
|
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-DmIalUmP.js';
|
|
3
3
|
export { A as AgentTool, J as JSONSchema, T as ToolExecContext, a as ToolResult } from './agent-tool-CB0RQyx9.js';
|
|
4
4
|
import 'react';
|
|
5
5
|
import 'dockview-react';
|
|
@@ -47,6 +47,8 @@ interface PanelConfig<T = any> {
|
|
|
47
47
|
essential?: boolean;
|
|
48
48
|
chromeless?: boolean;
|
|
49
49
|
supportsFullPage?: boolean;
|
|
50
|
+
/** Center-panel id opened when this config is used as a left-tab category. */
|
|
51
|
+
defaultPanelId?: string;
|
|
50
52
|
/** Source: "builtin" | "app" */
|
|
51
53
|
source?: string;
|
|
52
54
|
pluginId?: string;
|
package/dist/testing.d.ts
CHANGED
|
@@ -231,6 +231,8 @@ declare interface PanelConfig<T = any> {
|
|
|
231
231
|
essential?: boolean;
|
|
232
232
|
chromeless?: boolean;
|
|
233
233
|
supportsFullPage?: boolean;
|
|
234
|
+
/** Center-panel id opened when this config is used as a left-tab category. */
|
|
235
|
+
defaultPanelId?: string;
|
|
234
236
|
/** Source: "builtin" | "app" */
|
|
235
237
|
source?: string;
|
|
236
238
|
pluginId?: string;
|
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-DkZAxsYo.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.css
CHANGED
|
@@ -1484,6 +1484,9 @@
|
|
|
1484
1484
|
.-top-1\.5 {
|
|
1485
1485
|
top: calc(var(--spacing) * -1.5);
|
|
1486
1486
|
}
|
|
1487
|
+
.-top-px {
|
|
1488
|
+
top: -1px;
|
|
1489
|
+
}
|
|
1487
1490
|
.top-0 {
|
|
1488
1491
|
top: calc(var(--spacing) * 0);
|
|
1489
1492
|
}
|
|
@@ -1508,6 +1511,9 @@
|
|
|
1508
1511
|
.right-3 {
|
|
1509
1512
|
right: calc(var(--spacing) * 3);
|
|
1510
1513
|
}
|
|
1514
|
+
.-bottom-px {
|
|
1515
|
+
bottom: -1px;
|
|
1516
|
+
}
|
|
1511
1517
|
.bottom-0 {
|
|
1512
1518
|
bottom: calc(var(--spacing) * 0);
|
|
1513
1519
|
}
|
|
@@ -2809,6 +2815,67 @@
|
|
|
2809
2815
|
}
|
|
2810
2816
|
}
|
|
2811
2817
|
}
|
|
2818
|
+
.after\:absolute {
|
|
2819
|
+
&::after {
|
|
2820
|
+
content: var(--tw-content);
|
|
2821
|
+
position: absolute;
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
.after\:inset-y-2 {
|
|
2825
|
+
&::after {
|
|
2826
|
+
content: var(--tw-content);
|
|
2827
|
+
inset-block: calc(var(--spacing) * 2);
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
.after\:left-1\/2 {
|
|
2831
|
+
&::after {
|
|
2832
|
+
content: var(--tw-content);
|
|
2833
|
+
left: calc(1 / 2 * 100%);
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
.after\:w-px {
|
|
2837
|
+
&::after {
|
|
2838
|
+
content: var(--tw-content);
|
|
2839
|
+
width: 1px;
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
.after\:-translate-x-1\/2 {
|
|
2843
|
+
&::after {
|
|
2844
|
+
content: var(--tw-content);
|
|
2845
|
+
--tw-translate-x: calc(calc(1 / 2 * 100%) * -1);
|
|
2846
|
+
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
.after\:rounded-full {
|
|
2850
|
+
&::after {
|
|
2851
|
+
content: var(--tw-content);
|
|
2852
|
+
border-radius: calc(infinity * 1px);
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
.after\:bg-border\/55 {
|
|
2856
|
+
&::after {
|
|
2857
|
+
content: var(--tw-content);
|
|
2858
|
+
background-color: var(--boring-border);
|
|
2859
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2860
|
+
background-color: color-mix(in oklab, var(--boring-border) 55%, transparent);
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2864
|
+
.after\:transition-\[width\,background-color\] {
|
|
2865
|
+
&::after {
|
|
2866
|
+
content: var(--tw-content);
|
|
2867
|
+
transition-property: width,background-color;
|
|
2868
|
+
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
2869
|
+
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
.after\:duration-150 {
|
|
2873
|
+
&::after {
|
|
2874
|
+
content: var(--tw-content);
|
|
2875
|
+
--tw-duration: 150ms;
|
|
2876
|
+
transition-duration: 150ms;
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2812
2879
|
.hover\:-translate-y-0\.5 {
|
|
2813
2880
|
&:hover {
|
|
2814
2881
|
@media (hover: hover) {
|
|
@@ -2835,6 +2902,13 @@
|
|
|
2835
2902
|
}
|
|
2836
2903
|
}
|
|
2837
2904
|
}
|
|
2905
|
+
.hover\:\!bg-transparent {
|
|
2906
|
+
&:hover {
|
|
2907
|
+
@media (hover: hover) {
|
|
2908
|
+
background-color: transparent !important;
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2838
2912
|
.hover\:bg-accent {
|
|
2839
2913
|
&:hover {
|
|
2840
2914
|
@media (hover: hover) {
|
|
@@ -2862,16 +2936,6 @@
|
|
|
2862
2936
|
}
|
|
2863
2937
|
}
|
|
2864
2938
|
}
|
|
2865
|
-
.hover\:bg-border\/70 {
|
|
2866
|
-
&:hover {
|
|
2867
|
-
@media (hover: hover) {
|
|
2868
|
-
background-color: var(--boring-border);
|
|
2869
|
-
@supports (color: color-mix(in lab, red, red)) {
|
|
2870
|
-
background-color: color-mix(in oklab, var(--boring-border) 70%, transparent);
|
|
2871
|
-
}
|
|
2872
|
-
}
|
|
2873
|
-
}
|
|
2874
|
-
}
|
|
2875
2939
|
.hover\:bg-destructive\/10 {
|
|
2876
2940
|
&:hover {
|
|
2877
2941
|
@media (hover: hover) {
|
|
@@ -2985,10 +3049,26 @@
|
|
|
2985
3049
|
}
|
|
2986
3050
|
}
|
|
2987
3051
|
}
|
|
2988
|
-
.hover
|
|
3052
|
+
.hover\:after\:w-1 {
|
|
3053
|
+
&:hover {
|
|
3054
|
+
@media (hover: hover) {
|
|
3055
|
+
&::after {
|
|
3056
|
+
content: var(--tw-content);
|
|
3057
|
+
width: calc(var(--spacing) * 1);
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
.hover\:after\:bg-foreground\/35 {
|
|
2989
3063
|
&:hover {
|
|
2990
3064
|
@media (hover: hover) {
|
|
2991
|
-
|
|
3065
|
+
&::after {
|
|
3066
|
+
content: var(--tw-content);
|
|
3067
|
+
background-color: var(--boring-foreground);
|
|
3068
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
3069
|
+
background-color: color-mix(in oklab, var(--boring-foreground) 35%, transparent);
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
2992
3072
|
}
|
|
2993
3073
|
}
|
|
2994
3074
|
}
|
|
@@ -3063,11 +3143,27 @@
|
|
|
3063
3143
|
cursor: grabbing;
|
|
3064
3144
|
}
|
|
3065
3145
|
}
|
|
3066
|
-
.active
|
|
3146
|
+
.active\:\!bg-transparent {
|
|
3067
3147
|
&:active {
|
|
3068
|
-
background-color:
|
|
3069
|
-
|
|
3070
|
-
|
|
3148
|
+
background-color: transparent !important;
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
.active\:after\:w-1 {
|
|
3152
|
+
&:active {
|
|
3153
|
+
&::after {
|
|
3154
|
+
content: var(--tw-content);
|
|
3155
|
+
width: calc(var(--spacing) * 1);
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
.active\:after\:bg-foreground\/50 {
|
|
3160
|
+
&:active {
|
|
3161
|
+
&::after {
|
|
3162
|
+
content: var(--tw-content);
|
|
3163
|
+
background-color: var(--boring-foreground);
|
|
3164
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
3165
|
+
background-color: color-mix(in oklab, var(--boring-foreground) 50%, transparent);
|
|
3166
|
+
}
|
|
3071
3167
|
}
|
|
3072
3168
|
}
|
|
3073
3169
|
}
|
package/dist/workspace.d.ts
CHANGED
|
@@ -994,6 +994,8 @@ export declare interface LeftTabParams {
|
|
|
994
994
|
searchQuery?: string;
|
|
995
995
|
bridge?: unknown;
|
|
996
996
|
chromeless?: boolean;
|
|
997
|
+
/** Optional DOM target for left-tab toolbar actions owned by the pane. */
|
|
998
|
+
chromeActionsElement?: Element | null;
|
|
997
999
|
revealFileTreeRequest?: {
|
|
998
1000
|
path: string;
|
|
999
1001
|
seq: number;
|
|
@@ -1146,6 +1148,8 @@ export declare interface PanelConfig<T = any> {
|
|
|
1146
1148
|
essential?: boolean;
|
|
1147
1149
|
chromeless?: boolean;
|
|
1148
1150
|
supportsFullPage?: boolean;
|
|
1151
|
+
/** Center-panel id opened when this config is used as a left-tab category. */
|
|
1152
|
+
defaultPanelId?: string;
|
|
1149
1153
|
/** Source: "builtin" | "app" */
|
|
1150
1154
|
source?: string;
|
|
1151
1155
|
pluginId?: string;
|
|
@@ -1489,7 +1493,7 @@ export declare interface SurfaceResolverRegistryLike {
|
|
|
1489
1493
|
register(id: string, config: SurfaceResolverRegistration): void;
|
|
1490
1494
|
}
|
|
1491
1495
|
|
|
1492
|
-
export declare function SurfaceShell({ rootDir, sidebarDefaultWidth, sidebarMinWidth, sidebarMaxWidth, storageKey, onReady, onChange, onClose, extraPanels, defaultLeftTab, initialPanels, className, }: SurfaceShellProps): JSX.Element;
|
|
1496
|
+
export declare function SurfaceShell({ rootDir, sidebarDefaultWidth, sidebarMinWidth, sidebarMaxWidth, storageKey, onReady, onChange, onClose, extraPanels, defaultLeftTab, onReloadAgentPlugins, initialPanels, className, }: SurfaceShellProps): JSX.Element;
|
|
1493
1497
|
|
|
1494
1498
|
export declare interface SurfaceShellApi {
|
|
1495
1499
|
/** Open a file in the workbench. Idempotent — re-activates an existing pane for the same path. */
|
|
@@ -1536,6 +1540,7 @@ export declare interface SurfaceShellProps {
|
|
|
1536
1540
|
*/
|
|
1537
1541
|
extraPanels?: string[];
|
|
1538
1542
|
defaultLeftTab?: string;
|
|
1543
|
+
onReloadAgentPlugins?: () => void | Promise<unknown>;
|
|
1539
1544
|
initialPanels?: Array<{
|
|
1540
1545
|
id: string;
|
|
1541
1546
|
component: string;
|
|
@@ -1849,7 +1854,7 @@ export declare function useWorkspaceContextOptional(): WorkspaceContextValue | n
|
|
|
1849
1854
|
|
|
1850
1855
|
export declare function useWorkspaceRequestId(): string | null;
|
|
1851
1856
|
|
|
1852
|
-
export declare function WorkbenchLeftPane({ rootDir, bridge, defaultTab, revealFileTreeRequest, onOpenPanel, onCollapse, className, }: WorkbenchLeftPaneProps): JSX.Element;
|
|
1857
|
+
export declare function WorkbenchLeftPane({ rootDir, bridge, defaultTab, revealFileTreeRequest, onOpenPanel, onReloadAgentPlugins, onCollapse, className, }: WorkbenchLeftPaneProps): JSX.Element;
|
|
1853
1858
|
|
|
1854
1859
|
declare interface WorkbenchLeftPaneOpenPanelConfig {
|
|
1855
1860
|
id: string;
|
|
@@ -1867,6 +1872,7 @@ export declare interface WorkbenchLeftPaneProps {
|
|
|
1867
1872
|
seq: number;
|
|
1868
1873
|
} | null;
|
|
1869
1874
|
onOpenPanel?: (config: WorkbenchLeftPaneOpenPanelConfig) => void;
|
|
1875
|
+
onReloadAgentPlugins?: () => void | Promise<unknown>;
|
|
1870
1876
|
onCollapse?: () => void;
|
|
1871
1877
|
className?: string;
|
|
1872
1878
|
}
|
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-
|
|
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-
|
|
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";
|
|
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-
|
|
7
|
+
import { C as yr, T as vr, W as xr, b as kr } from "./WorkspaceLoadingState-yp4vNmrT.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-
|
|
14
|
-
import { MarkdownEditor as Fr } from "./MarkdownEditor-
|
|
13
|
+
import { FileTree as Ir } from "./FileTree-CVsvICGP.js";
|
|
14
|
+
import { MarkdownEditor as Fr } from "./MarkdownEditor-BvaGmzWP.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/docs/INTERFACES.md
CHANGED
package/docs/PLUGIN_STRUCTURE.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Plugin Structure
|
|
2
2
|
|
|
3
3
|
Canonical quick reference for boring-ui plugin layouts. For the full current
|
|
4
|
-
contract, see [`PLUGIN_SYSTEM.md`](./PLUGIN_SYSTEM.md). For
|
|
5
|
-
architecture, see the repo-level
|
|
6
|
-
[`docs/runtime-plugin-v2-hot-reload-plan.md`](../../../docs/runtime-plugin-v2-hot-reload-plan.md).
|
|
4
|
+
contract, see [`PLUGIN_SYSTEM.md`](./PLUGIN_SYSTEM.md). For the historical
|
|
5
|
+
hosted/runtime architecture exploration, see the archived repo-level
|
|
6
|
+
[`docs/plans/archive/runtime-plugin-v2-hot-reload-plan.md`](../../../docs/plans/archive/runtime-plugin-v2-hot-reload-plan.md).
|
|
7
7
|
|
|
8
8
|
## Generated/runtime plugin
|
|
9
9
|
|
package/docs/PLUGIN_SYSTEM.md
CHANGED
|
@@ -6,8 +6,9 @@ example `PLUGIN_SYSTEM.md §4.5`), so keep headings stable when editing.
|
|
|
6
6
|
|
|
7
7
|
This document describes the implementation as it exists now. Historical
|
|
8
8
|
implementation plans live under `packages/workspace/docs/plans/archive/`.
|
|
9
|
-
For
|
|
10
|
-
|
|
9
|
+
For the historical generated/hosted runtime-plugin architecture exploration,
|
|
10
|
+
see the archived repo-level
|
|
11
|
+
`docs/plans/archive/runtime-plugin-v2-hot-reload-plan.md`.
|
|
11
12
|
|
|
12
13
|
## Contents
|
|
13
14
|
|
|
@@ -27,7 +28,7 @@ For future generated/hosted runtime-plugin architecture, see the repo-level
|
|
|
27
28
|
| Term | Definition |
|
|
28
29
|
| --- | --- |
|
|
29
30
|
| **App/internal plugin** | Trusted package composed by the app at boot. May export `boring.server`, Fastify routes, agent tools, providers, catalogs, and domain APIs. Server changes require restart/redeploy. |
|
|
30
|
-
| **Runtime/generated plugin** | Workspace-local plugin under `.pi/extensions/<id>/`, usually produced by `boring-ui-plugin scaffold`. It is hot-loaded for front/Pi resources, but must not rely on dynamic backend routes. |
|
|
31
|
+
| **Runtime/generated plugin** | Workspace-local plugin under `.pi/extensions/<id>/`, usually produced by `boring-ui-plugin scaffold`. Also called an **external** plugin in trust-model terms. It is hot-loaded for front/Pi resources, but must not rely on dynamic backend routes. |
|
|
31
32
|
| **Boring plugin package** | Node package with `package.json#boring` and/or `package.json#pi`. App-default packages are declared in `package.json#boring.defaultPluginPackages` or passed to `createWorkspaceAgentServer`. |
|
|
32
33
|
| **Boring front factory** | Default export of `boring.front`: `(api: BoringFrontAPI) => void | Promise<void>`. Usually created with `definePlugin({ ... })`. |
|
|
33
34
|
| **Workspace server plugin** | Trusted boot-time server contribution returned by `defineServerPlugin({ ... })` or a compatible object. May include routes, tools, system prompt, Pi resources, and provisioning. |
|
|
@@ -35,6 +36,25 @@ For future generated/hosted runtime-plugin architecture, see the repo-level
|
|
|
35
36
|
| **Revision** | Per-plugin monotonic integer. It bumps on signature changes and is appended to browser front imports for cache busting. |
|
|
36
37
|
| **Surface resolver** | Front contribution that maps a typed request such as `open-path` to a panel id/title/params. File opens should route through this path. |
|
|
37
38
|
|
|
39
|
+
### 1.1 Trust model (internal vs external)
|
|
40
|
+
|
|
41
|
+
The two tiers differ by **provenance and trust**, not just lifecycle:
|
|
42
|
+
|
|
43
|
+
| | App/internal plugin | Runtime/generated ("external") plugin |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| Provenance | App-owned package, composed at boot | Workspace-local `.pi/extensions/`, often agent-generated |
|
|
46
|
+
| Trust | Trusted app module | Trusted **only** as local developer/workspace code |
|
|
47
|
+
| Front | Native React in the host tree | Native React (local trusted context) |
|
|
48
|
+
| Server/routes/tools | Full power: Fastify routes, static `agentTools`, providers, domain APIs | Route-free; no `boring.server`; backend work goes through Pi tools |
|
|
49
|
+
| Reload | Restart/redeploy | `/reload` hot-swaps front + Pi resources |
|
|
50
|
+
|
|
51
|
+
Plugin tools' `execute()` run in the **host Node process and bypass the
|
|
52
|
+
sandbox by design**; plugin loading is local-mode-only (skipped under
|
|
53
|
+
`vercel-sandbox`). Hosted/marketplace plugins — untrusted external code that
|
|
54
|
+
would need iframe fronts and sandbox-proxied tools — are **not implemented**;
|
|
55
|
+
that provenance/permission model is a future phase (see §7 and the archived
|
|
56
|
+
repo-level `docs/plans/archive/runtime-plugin-trust-modes-plan.md`).
|
|
57
|
+
|
|
38
58
|
---
|
|
39
59
|
|
|
40
60
|
## 2. End-to-end behaviour
|
|
@@ -241,6 +261,27 @@ boring-ui-plugin verify <name>
|
|
|
241
261
|
Do not teach agents to copy `packages/plugin-cli/templates/plugin` for generated runtime
|
|
242
262
|
plugins. That template is an app/internal publishable package example.
|
|
243
263
|
|
|
264
|
+
### 4.7 Chat slash commands
|
|
265
|
+
|
|
266
|
+
Plugins can contribute **chat `/slash` commands** — a separate surface from the
|
|
267
|
+
command-palette `commands` output. There is no `!` bang-command; the composer
|
|
268
|
+
parses `/name args` only.
|
|
269
|
+
|
|
270
|
+
- **Front registry** (`packages/agent/src/front/slashCommands/registry.ts`):
|
|
271
|
+
`SlashCommand { name, description, kind?, source?, sourcePlugin?, handler }`.
|
|
272
|
+
`kind: 'local'` runs in the browser; `kind: 'skill'` is forwarded to the Pi
|
|
273
|
+
agent as `skill: <name>\n\n<args>`. The chat composer (`PiChatPanel`)
|
|
274
|
+
intercepts `/` input before it reaches the harness.
|
|
275
|
+
- **Server commands** are listed from the harness via
|
|
276
|
+
`GET /api/v1/agent/commands` (consumed by `useServerCommands`) and executed
|
|
277
|
+
via `POST /api/v1/agent/commands/execute` — this route **bypasses the
|
|
278
|
+
harness chat loop**; Pi executes the command natively. `source`
|
|
279
|
+
(`extension`/`prompt`/`skill`) and `sourcePlugin` tag where a command came
|
|
280
|
+
from in the picker.
|
|
281
|
+
- **How a plugin contributes one**: ship a Pi extension/prompt/skill in its
|
|
282
|
+
`package.json#pi` block — Pi-sourced commands appear automatically. No
|
|
283
|
+
harness changes required.
|
|
284
|
+
|
|
244
285
|
---
|
|
245
286
|
|
|
246
287
|
## 5. Key algorithms
|
|
@@ -327,7 +368,8 @@ while capturing the front factory.
|
|
|
327
368
|
plugin RPC for purity.
|
|
328
369
|
- Dynamic provider/binding trees for runtime hot-loaded plugins in this PR.
|
|
329
370
|
- Marketplace signing/provenance/permissions. Those belong to the next runtime
|
|
330
|
-
plugin architecture phase.
|
|
371
|
+
plugin architecture phase. Promotion (external → internal) is designed as an
|
|
372
|
+
explicit admin action with pinned provenance + restart — not implemented yet.
|
|
331
373
|
|
|
332
374
|
---
|
|
333
375
|
|