@hachej/boring-workspace 0.1.17 → 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +36 -34
  2. package/dist/{FileTree-Dvaud3jU.js → FileTree-DHVB9rpk.js} +15 -15
  3. package/dist/{MarkdownEditor-sLkqTXDj.js → MarkdownEditor-L1KDH0bM.js} +1 -1
  4. package/dist/{WorkspaceLoadingState-zLzh1tGc.js → WorkspaceLoadingState-DYDxUYnx.js} +114 -110
  5. package/dist/WorkspaceProvider-CDPaAO5u.js +5971 -0
  6. package/dist/app-front.d.ts +94 -107
  7. package/dist/app-front.js +243 -233
  8. package/dist/app-server.d.ts +130 -15
  9. package/dist/app-server.js +1569 -304
  10. package/dist/{bootstrapServer-BreQ9QBc.d.ts → createInMemoryBridge-BDxDzihm.d.ts} +11 -26
  11. package/dist/manifest-CyNNdfYz.d.ts +58 -0
  12. package/dist/plugin.d.ts +199 -0
  13. package/dist/plugin.js +300 -0
  14. package/dist/server.d.ts +239 -4
  15. package/dist/server.js +901 -78
  16. package/dist/shared.d.ts +4 -112
  17. package/dist/surface-COYagY2m.d.ts +111 -0
  18. package/dist/testing.d.ts +19 -1
  19. package/dist/testing.js +2 -2
  20. package/dist/{agent-tool-DEtfQPVB.d.ts → ui-bridge-Gfh1MMgl.d.ts} +30 -30
  21. package/dist/workspace.css +36 -0
  22. package/dist/workspace.d.ts +165 -120
  23. package/dist/workspace.js +330 -377
  24. package/docs/INTERFACES.md +9 -9
  25. package/docs/PLUGIN_STRUCTURE.md +39 -145
  26. package/docs/PLUGIN_SYSTEM.md +355 -0
  27. package/docs/README.md +6 -1
  28. package/docs/plans/README.md +1 -0
  29. package/docs/plans/archive/HOT_RELOADABLE_AGENT_PLUGINS_PLAN.md +218 -0
  30. package/docs/plans/archive/RELOAD_PLUGGABILITY_PLAN.md +174 -0
  31. package/docs/plans/archive/UNIFIED_PLUGIN_SYSTEM_PLAN.md +769 -0
  32. package/package.json +11 -5
  33. package/dist/CommandPalette-CJHuTJlD.js +0 -5716
  34. package/docs/bridge.md +0 -135
  35. package/docs/panels.md +0 -102
  36. package/docs/plugins.md +0 -158
  37. /package/docs/plans/{MACRO_PLUGIN_GENERIC_HELPERS_AUDIT.md → archive/MACRO_PLUGIN_GENERIC_HELPERS_AUDIT.md} +0 -0
package/dist/shared.d.ts CHANGED
@@ -1,112 +1,4 @@
1
- export { A as AgentTool, C as CommandResult, J as JSONSchema, T as ToolExecContext, c as ToolResult, U as UiBridge, a as UiCommand, b as UiState } from './agent-tool-DEtfQPVB.js';
2
- import { ComponentType } from 'react';
3
- import { DockviewPanelApi, DockviewApi } from 'dockview-react';
4
-
5
- /**
6
- * Shared panel and command types — no runtime deps beyond React/dockview.
7
- *
8
- * Importable from BOTH front and server bundles without dragging in
9
- * platform-specific code.
10
- */
11
-
12
- /**
13
- * Unified prop shape for panel components rendered inside DockviewShell.
14
- *
15
- * Structurally mirrors dockview's `IDockviewPanelProps<T>` so dockview
16
- * can render registered components directly — no wrapper, no field
17
- * renaming, no `as` casts. We re-state the shape (rather than re-export
18
- * dockview's type) so the workspace package owns its public contract:
19
- * if dockview's type ever drifts, only the wiring inside DockviewShell
20
- * needs to change.
21
- *
22
- * Use {@link definePanel} for type-safe registration.
23
- *
24
- * @typeParam T - Shape of the panel-specific `params` payload. Defaults
25
- * to `unknown` because layouts restored from JSON are inherently
26
- * un-typed at runtime; use a generic param when you control the
27
- * addPanel call site, otherwise read defensively.
28
- */
29
- interface PaneProps<T = unknown> {
30
- /** App-supplied data for this panel instance (e.g. `{ path: string }`). */
31
- params: T;
32
- /** Per-panel control surface (close, setActive, setTitle, …). */
33
- api: DockviewPanelApi;
34
- /** Top-level dockview API (groups, addPanel, removePanel, fromJSON, …). */
35
- containerApi: DockviewApi;
36
- /** Optional className forwarded to the pane's root element. */
37
- className?: string;
38
- }
39
- interface PanelConfig<T = any> {
40
- id: string;
41
- title: string;
42
- icon?: ComponentType<{
43
- className?: string;
44
- }>;
45
- /** Placement hint: "left" | "center" | "right" | "bottom" | "left-tab" | "right-tab" */
46
- placement?: string;
47
- requiresCapabilities?: string[];
48
- essential?: boolean;
49
- chromeless?: boolean;
50
- /** Source: "builtin" | "app" */
51
- source?: string;
52
- pluginId?: string;
53
- /**
54
- * Whether to wrap the component with React.lazy + Suspense. Omit to let
55
- * the registry auto-detect: zero-arg functions (factories) are treated as
56
- * lazy; components that accept a props argument are treated as eager.
57
- */
58
- lazy?: boolean;
59
- component: ComponentType<PaneProps<T>> | (() => Promise<{
60
- default: ComponentType<PaneProps<T>>;
61
- }>);
62
- }
63
- type PanelRegistration<T = any> = Omit<PanelConfig<T>, 'id'>;
64
- /**
65
- * Identity helper for type-safe panel registration. Pure runtime
66
- * passthrough — the value of this is forcing TypeScript to verify that
67
- * the registered component accepts the params shape declared on the
68
- * config. Without it, apps tend to widen `component` to
69
- * `ComponentType<PaneProps<unknown>>` and lose the link.
70
- *
71
- * ```ts
72
- * const editorPanel = definePanel<{ path: string }>({
73
- * id: "code-editor",
74
- * title: "Editor",
75
- * component: CodeEditorPane, // typechecked against PaneProps<{ path: string }>
76
- * placement: "center",
77
- * })
78
- * ```
79
- */
80
- declare function definePanel<T = unknown>(config: PanelConfig<T>): PanelConfig<T>;
81
- interface CommandConfig {
82
- id: string;
83
- title: string;
84
- run: () => void;
85
- keywords?: string[];
86
- shortcut?: string;
87
- when?: () => boolean;
88
- pluginId?: string;
89
- }
90
-
91
- declare const WORKSPACE_OPEN_PATH_SURFACE_KIND = "workspace.open.path";
92
- interface SurfaceOpenRequest {
93
- kind: string;
94
- target: string;
95
- meta?: Record<string, unknown>;
96
- }
97
- interface SurfacePanelResolution {
98
- component: string;
99
- id?: string;
100
- title?: string;
101
- params?: Record<string, unknown>;
102
- score?: number;
103
- }
104
- interface SurfaceResolverConfig {
105
- id: string;
106
- resolve: (request: SurfaceOpenRequest) => SurfacePanelResolution | undefined;
107
- source?: string;
108
- pluginId?: string;
109
- }
110
- type SurfaceResolverRegistration = Omit<SurfaceResolverConfig, "id">;
111
-
112
- export { type CommandConfig, type PaneProps, type PanelConfig, type PanelRegistration, type SurfaceOpenRequest, type SurfacePanelResolution, type SurfaceResolverConfig, type SurfaceResolverRegistration, WORKSPACE_OPEN_PATH_SURFACE_KIND, definePanel };
1
+ export { A as AgentTool, C as CommandResult, J as JSONSchema, T as ToolExecContext, a as ToolResult, U as UiBridge, b as UiCommand, c as UiState } from './ui-bridge-Gfh1MMgl.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-COYagY2m.js';
3
+ import 'react';
4
+ import 'dockview-react';
@@ -0,0 +1,111 @@
1
+ import { ComponentType } from 'react';
2
+ import { DockviewPanelApi, DockviewApi } from 'dockview-react';
3
+
4
+ /**
5
+ * Shared panel and command types — no runtime deps beyond React/dockview.
6
+ *
7
+ * Importable from BOTH front and server bundles without dragging in
8
+ * platform-specific code.
9
+ */
10
+
11
+ /**
12
+ * Unified prop shape for panel components rendered inside DockviewShell.
13
+ *
14
+ * Structurally mirrors dockview's `IDockviewPanelProps<T>` so dockview
15
+ * can render registered components directly — no wrapper, no field
16
+ * renaming, no `as` casts. We re-state the shape (rather than re-export
17
+ * dockview's type) so the workspace package owns its public contract:
18
+ * if dockview's type ever drifts, only the wiring inside DockviewShell
19
+ * needs to change.
20
+ *
21
+ * Use {@link definePanel} for type-safe registration.
22
+ *
23
+ * @typeParam T - Shape of the panel-specific `params` payload. Defaults
24
+ * to `unknown` because layouts restored from JSON are inherently
25
+ * un-typed at runtime; use a generic param when you control the
26
+ * addPanel call site, otherwise read defensively.
27
+ */
28
+ interface PaneProps<T = unknown> {
29
+ /** App-supplied data for this panel instance (e.g. `{ path: string }`). */
30
+ params: T;
31
+ /** Per-panel control surface (close, setActive, setTitle, …). */
32
+ api: DockviewPanelApi;
33
+ /** Top-level dockview API (groups, addPanel, removePanel, fromJSON, …). */
34
+ containerApi: DockviewApi;
35
+ /** Optional className forwarded to the pane's root element. */
36
+ className?: string;
37
+ }
38
+ interface PanelConfig<T = any> {
39
+ id: string;
40
+ title: string;
41
+ icon?: ComponentType<{
42
+ className?: string;
43
+ }>;
44
+ /** Placement hint: "left" | "center" | "right" | "bottom" | "left-tab" | "right-tab" */
45
+ placement?: string;
46
+ requiresCapabilities?: string[];
47
+ essential?: boolean;
48
+ chromeless?: boolean;
49
+ /** Source: "builtin" | "app" */
50
+ source?: string;
51
+ pluginId?: string;
52
+ /**
53
+ * Whether to wrap the component with React.lazy + Suspense. Omit to let
54
+ * the registry auto-detect: zero-arg functions (factories) are treated as
55
+ * lazy; components that accept a props argument are treated as eager.
56
+ */
57
+ lazy?: boolean;
58
+ component: ComponentType<PaneProps<T>> | (() => Promise<{
59
+ default: ComponentType<PaneProps<T>>;
60
+ }>);
61
+ }
62
+ type PanelRegistration<T = any> = Omit<PanelConfig<T>, 'id'>;
63
+ /**
64
+ * Identity helper for type-safe panel registration. Pure runtime
65
+ * passthrough — the value of this is forcing TypeScript to verify that
66
+ * the registered component accepts the params shape declared on the
67
+ * config. Without it, apps tend to widen `component` to
68
+ * `ComponentType<PaneProps<unknown>>` and lose the link.
69
+ *
70
+ * ```ts
71
+ * const editorPanel = definePanel<{ path: string }>({
72
+ * id: "code-editor",
73
+ * title: "Editor",
74
+ * component: CodeEditorPane, // typechecked against PaneProps<{ path: string }>
75
+ * placement: "center",
76
+ * })
77
+ * ```
78
+ */
79
+ declare function definePanel<T = unknown>(config: PanelConfig<T>): PanelConfig<T>;
80
+ interface CommandConfig {
81
+ id: string;
82
+ title: string;
83
+ run: () => void;
84
+ keywords?: string[];
85
+ shortcut?: string;
86
+ when?: () => boolean;
87
+ pluginId?: string;
88
+ }
89
+
90
+ declare const WORKSPACE_OPEN_PATH_SURFACE_KIND = "workspace.open.path";
91
+ interface SurfaceOpenRequest {
92
+ kind: string;
93
+ target: string;
94
+ meta?: Record<string, unknown>;
95
+ }
96
+ interface SurfacePanelResolution {
97
+ component: string;
98
+ id?: string;
99
+ title?: string;
100
+ params?: Record<string, unknown>;
101
+ score?: number;
102
+ }
103
+ interface SurfaceResolverConfig {
104
+ id: string;
105
+ resolve: (request: SurfaceOpenRequest) => SurfacePanelResolution | undefined;
106
+ source?: string;
107
+ pluginId?: string;
108
+ }
109
+ type SurfaceResolverRegistration = Omit<SurfaceResolverConfig, "id">;
110
+
111
+ export { type CommandConfig as C, type PaneProps as P, type SurfaceOpenRequest as S, WORKSPACE_OPEN_PATH_SURFACE_KIND as W, type PanelConfig as a, type PanelRegistration as b, type SurfacePanelResolution as c, type SurfaceResolverConfig as d, type SurfaceResolverRegistration as e, definePanel as f };
package/dist/testing.d.ts CHANGED
@@ -252,15 +252,33 @@ declare class PanelRegistry {
252
252
  private capabilities;
253
253
  private listeners;
254
254
  private snapshotCache;
255
+ private lazyComponentCache;
256
+ private wrapperComponentCache;
257
+ private generation;
255
258
  constructor(capabilities?: Record<string, boolean>);
256
259
  register(id: string, config: PanelRegistration): void;
257
- unregisterByPluginId(pluginId: string): void;
260
+ unregister(id: string): void;
261
+ /**
262
+ * Atomic replace: unregister all panels owned by `pluginId`, then register
263
+ * the new set, in one emit cycle. Subscribers see exactly one intermediate
264
+ * state — never an empty registry between unregister and re-register.
265
+ *
266
+ * Collision policy: a new registration whose id is already owned by a
267
+ * DIFFERENT pluginId is skipped with a warning. Preserves cross-plugin
268
+ * isolation during reload — a renamed plugin can't silently steal another
269
+ * plugin's panel id. Teardown + rebuild as a single observable transition,
270
+ * driven by the front-side SSE reload subscriber.
271
+ */
272
+ replaceByPluginId(pluginId: string, panels: PanelConfig[]): void;
258
273
  get(id: string): PanelConfig | undefined;
259
274
  has(id: string): boolean;
260
275
  list(): PanelConfig[];
276
+ listAll(): PanelConfig[];
261
277
  getComponents(): Record<string, ComponentType<any>>;
262
278
  subscribe: (cb: () => void) => (() => void);
263
279
  getSnapshot: () => readonly PanelConfig[];
280
+ private getWrappedComponent;
281
+ private getLazyComponent;
264
282
  private emit;
265
283
  private filteredPanels;
266
284
  private satisfiesCapabilities;
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 { i as cs, p as fs, ak as ps } from "./CommandPalette-CJHuTJlD.js";
4
+ import { h as cs, o as fs, aj as ps } from "./WorkspaceProvider-CDPaAO5u.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";
@@ -10682,7 +10682,7 @@ function $b(e, r) {
10682
10682
  try {
10683
10683
  const a = localStorage.getItem(e);
10684
10684
  if (a) {
10685
- const s = JSON.parse(a), c = Array.isArray(s.sessions) ? s.sessions : Array.isArray(s.items) ? s.items : null;
10685
+ const s = JSON.parse(a), c = Array.isArray(s.sessions) ? s.sessions : null;
10686
10686
  if (c)
10687
10687
  return { sessions: c, activeId: s.activeId ?? ((t = c[0]) == null ? void 0 : t.id) ?? "" };
10688
10688
  }
@@ -1,3 +1,32 @@
1
+ type JSONSchema = Record<string, unknown>;
2
+ interface ToolExecContext {
3
+ abortSignal: AbortSignal;
4
+ toolCallId: string;
5
+ onUpdate?: (partial: string) => void;
6
+ /** Agent chat/session id executing this tool, when known. */
7
+ sessionId?: string;
8
+ }
9
+ interface ToolResult {
10
+ content: Array<{
11
+ type: "text";
12
+ text: string;
13
+ }>;
14
+ isError?: boolean;
15
+ details?: unknown;
16
+ }
17
+ /**
18
+ * Structural tool contract accepted from workspace plugins and UI tool
19
+ * factories. Kept agent-runtime-neutral so only the app integration layer
20
+ * needs to import @hachej/boring-agent.
21
+ */
22
+ interface AgentTool {
23
+ name: string;
24
+ description: string;
25
+ promptSnippet?: string;
26
+ parameters: JSONSchema;
27
+ execute(params: Record<string, unknown>, ctx: ToolExecContext): Promise<ToolResult>;
28
+ }
29
+
1
30
  interface UiBridge {
2
31
  getState(): Promise<UiState | null>;
3
32
  setState(state: UiState): Promise<void>;
@@ -68,33 +97,4 @@ interface CommandResult {
68
97
  };
69
98
  }
70
99
 
71
- type JSONSchema = Record<string, unknown>;
72
- interface ToolExecContext {
73
- abortSignal: AbortSignal;
74
- toolCallId: string;
75
- onUpdate?: (partial: string) => void;
76
- /** Agent chat/session id executing this tool, when known. */
77
- sessionId?: string;
78
- }
79
- interface ToolResult {
80
- content: Array<{
81
- type: "text";
82
- text: string;
83
- }>;
84
- isError?: boolean;
85
- details?: unknown;
86
- }
87
- /**
88
- * Structural tool contract accepted from workspace plugins and UI tool
89
- * factories. Kept agent-runtime-neutral so only the app integration layer
90
- * needs to import @hachej/boring-agent.
91
- */
92
- interface AgentTool {
93
- name: string;
94
- description: string;
95
- promptSnippet?: string;
96
- parameters: JSONSchema;
97
- execute(params: Record<string, unknown>, ctx: ToolExecContext): Promise<ToolResult>;
98
- }
99
-
100
- export type { AgentTool as A, CommandResult as C, JSONSchema as J, ToolExecContext as T, UiBridge as U, UiCommand as a, UiState as b, ToolResult as c };
100
+ export type { AgentTool as A, CommandResult as C, JSONSchema as J, ToolExecContext as T, UiBridge as U, ToolResult as a, UiCommand as b, UiState as c };
@@ -1603,6 +1603,9 @@
1603
1603
  .block {
1604
1604
  display: block;
1605
1605
  }
1606
+ .contents {
1607
+ display: contents;
1608
+ }
1606
1609
  .flex {
1607
1610
  display: flex;
1608
1611
  }
@@ -1793,6 +1796,9 @@
1793
1796
  .rotate-90 {
1794
1797
  rotate: 90deg;
1795
1798
  }
1799
+ .transform {
1800
+ transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
1801
+ }
1796
1802
  .animate-pulse {
1797
1803
  animation: var(--animate-pulse);
1798
1804
  }
@@ -2483,6 +2489,11 @@
2483
2489
  -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
2484
2490
  backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
2485
2491
  }
2492
+ .transition {
2493
+ transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
2494
+ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
2495
+ transition-duration: var(--tw-duration, var(--default-transition-duration));
2496
+ }
2486
2497
  .transition-\[width\,min-width\,max-width\] {
2487
2498
  transition-property: width,min-width,max-width;
2488
2499
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
@@ -5968,6 +5979,26 @@
5968
5979
  inherits: false;
5969
5980
  initial-value: 0;
5970
5981
  }
5982
+ @property --tw-rotate-x {
5983
+ syntax: "*";
5984
+ inherits: false;
5985
+ }
5986
+ @property --tw-rotate-y {
5987
+ syntax: "*";
5988
+ inherits: false;
5989
+ }
5990
+ @property --tw-rotate-z {
5991
+ syntax: "*";
5992
+ inherits: false;
5993
+ }
5994
+ @property --tw-skew-x {
5995
+ syntax: "*";
5996
+ inherits: false;
5997
+ }
5998
+ @property --tw-skew-y {
5999
+ syntax: "*";
6000
+ inherits: false;
6001
+ }
5971
6002
  @property --tw-space-y-reverse {
5972
6003
  syntax: "*";
5973
6004
  inherits: false;
@@ -6198,6 +6229,11 @@
6198
6229
  --tw-translate-x: 0;
6199
6230
  --tw-translate-y: 0;
6200
6231
  --tw-translate-z: 0;
6232
+ --tw-rotate-x: initial;
6233
+ --tw-rotate-y: initial;
6234
+ --tw-rotate-z: initial;
6235
+ --tw-skew-x: initial;
6236
+ --tw-skew-y: initial;
6201
6237
  --tw-space-y-reverse: 0;
6202
6238
  --tw-border-style: solid;
6203
6239
  --tw-leading: initial;