@hachej/boring-workspace 0.1.0

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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +94 -0
  3. package/dist/CodeEditor-DQqOn4xz.js +266 -0
  4. package/dist/CommandPalette-aM61U-b0.js +5229 -0
  5. package/dist/FileTree-DRq_bfue.js +245 -0
  6. package/dist/MarkdownEditor-DjiHxnRv.js +349 -0
  7. package/dist/WorkspaceLoadingState-By0dZoPD.js +568 -0
  8. package/dist/agent-tool-NvxKfist.d.ts +28 -0
  9. package/dist/app-front.d.ts +485 -0
  10. package/dist/app-front.js +452 -0
  11. package/dist/app-server.d.ts +53 -0
  12. package/dist/app-server.js +769 -0
  13. package/dist/bootstrapServer-BRUqUpVW.d.ts +66 -0
  14. package/dist/boring-workspace.css +1 -0
  15. package/dist/charts.d.ts +114 -0
  16. package/dist/charts.js +143 -0
  17. package/dist/events.d.ts +178 -0
  18. package/dist/events.js +88 -0
  19. package/dist/explorer-DtLUnuah.d.ts +129 -0
  20. package/dist/panel-DnvDNQac.js +6 -0
  21. package/dist/server.d.ts +84 -0
  22. package/dist/server.js +811 -0
  23. package/dist/shared.d.ts +113 -0
  24. package/dist/shared.js +11 -0
  25. package/dist/testing-e2e.d.ts +68 -0
  26. package/dist/testing-e2e.js +45 -0
  27. package/dist/testing.d.ts +464 -0
  28. package/dist/testing.js +10984 -0
  29. package/dist/utils-B6yFEsav.js +8 -0
  30. package/dist/workspace.css +5780 -0
  31. package/dist/workspace.d.ts +2119 -0
  32. package/dist/workspace.js +1884 -0
  33. package/docs/INTERFACES.md +58 -0
  34. package/docs/PLUGIN_STRUCTURE.md +162 -0
  35. package/docs/README.md +19 -0
  36. package/docs/bridge.md +135 -0
  37. package/docs/panels.md +102 -0
  38. package/docs/plans/GENERIC_EXPLORER_PLUGIN_PLAN.md +455 -0
  39. package/docs/plans/MACRO_PLUGIN_GENERIC_HELPERS_AUDIT.md +962 -0
  40. package/docs/plans/PLUGIN_OUTPUTS_ISOLATION_PLAN.md +301 -0
  41. package/docs/plans/README.md +9 -0
  42. package/docs/plans/UI_BRIDGE_OWNERSHIP_REFACTOR.md +303 -0
  43. package/docs/plans/archive/CODE_OWNERSHIP_CLEANUP_PLAN.md +387 -0
  44. package/docs/plans/archive/COMMAND_PALETTE_REGISTRY.md +814 -0
  45. package/docs/plans/archive/DECLARATIVE_LAYOUT_MIGRATION.md +277 -0
  46. package/docs/plans/archive/PLUGIN_MODEL.md +3674 -0
  47. package/docs/plans/archive/SRC_FOLDER_REORG_PLAN.md +307 -0
  48. package/docs/plans/archive/UNIFIED_EVENT_BUS.md +647 -0
  49. package/docs/plans/archive/WORKSPACE_V2_PLAN.md +2489 -0
  50. package/docs/plugins.md +158 -0
  51. package/package.json +164 -0
@@ -0,0 +1,568 @@
1
+ import { jsxs as d, jsx as o, Fragment as H } from "react/jsx-runtime";
2
+ import { useCallback as b, useMemo as A, useEffect as S, useState as V, Suspense as X, useRef as q } from "react";
3
+ import { LoadingState as Z, ResizeHandle as G, IconButton as $, Button as J, Kbd as Q } from "@hachej/boring-ui-kit";
4
+ import { c as g } from "./utils-B6yFEsav.js";
5
+ import { $ as Y, a6 as ee, E as te, am as ne, ak as re, u as oe } from "./CommandPalette-aM61U-b0.js";
6
+ import { Search as ae, Plus as ie } from "lucide-react";
7
+ function be(e, t, r = !0) {
8
+ if (!r || typeof window > "u") return t;
9
+ try {
10
+ const n = window.localStorage.getItem(e);
11
+ if (n === "1") return !0;
12
+ if (n === "0") return !1;
13
+ } catch {
14
+ }
15
+ return t;
16
+ }
17
+ function we(e, t, r = !0) {
18
+ if (!(!r || typeof window > "u"))
19
+ try {
20
+ window.localStorage.setItem(e, t ? "1" : "0");
21
+ } catch {
22
+ }
23
+ }
24
+ function F(e, t, r = !0) {
25
+ if (!r || typeof window > "u") return t;
26
+ try {
27
+ const n = window.localStorage.getItem(e);
28
+ if (n === null) return t;
29
+ const i = Number(n);
30
+ return Number.isFinite(i) ? i : t;
31
+ } catch {
32
+ }
33
+ return t;
34
+ }
35
+ function se(e, t, r = !0) {
36
+ if (!(!r || typeof window > "u"))
37
+ try {
38
+ window.localStorage.setItem(e, String(Math.round(t)));
39
+ } catch {
40
+ }
41
+ }
42
+ function ve(e = {}) {
43
+ const {
44
+ nav: t = "session-list",
45
+ navParams: r,
46
+ center: n = "chat",
47
+ centerParams: i,
48
+ surface: c,
49
+ surfaceParams: l,
50
+ sidebar: s,
51
+ sidebarParams: w
52
+ } = e, p = [];
53
+ return t && p.push({
54
+ id: "nav",
55
+ position: "left",
56
+ panel: t,
57
+ params: r,
58
+ locked: !0,
59
+ hideHeader: !0,
60
+ constraints: { minWidth: 60, maxWidth: 60 }
61
+ }), p.push({
62
+ id: "center",
63
+ position: "center",
64
+ panel: n,
65
+ params: i,
66
+ hideHeader: !0
67
+ }), s && p.push({
68
+ id: "sidebar",
69
+ position: "left",
70
+ panel: s,
71
+ params: w,
72
+ hideHeader: !0,
73
+ collapsible: !0,
74
+ collapsedWidth: 40,
75
+ constraints: { minWidth: 200, maxWidthViewportRatio: 0.5 }
76
+ }), c && p.push({
77
+ id: "surface",
78
+ position: "right",
79
+ panel: c,
80
+ params: l,
81
+ hideHeader: !0,
82
+ dynamic: !0,
83
+ placeholder: "empty"
84
+ }), { version: "2.0", groups: p };
85
+ }
86
+ function xe(e) {
87
+ const t = e.nav !== null, r = e.surface !== void 0, n = !!e.surface, i = e.nav || "session-list", c = e.center ?? "chat", l = e.surface || "artifact-surface", s = ce(), [w, p] = j(
88
+ e.storageKey ? `${e.storageKey}:drawerWidth` : void 0,
89
+ 260
90
+ ), [T, U] = j(
91
+ e.storageKey ? `${e.storageKey}:surfaceWidth` : void 0,
92
+ 680
93
+ ), f = Y(), W = C(w, 200, 360), M = Math.max(480, Math.floor(s * 0.72)), P = C(T, 480, M), z = N(e.centerParams, "getSurface"), I = N(e.centerParams, "isWorkbenchOpen"), O = N(e.centerParams, "openWorkbench"), u = R(e.navParams, "onClose"), h = R(e.surfaceParams, "onClose"), B = R(e.navParams, "onCreate"), v = t ? !!u : !!e.onOpenNav, x = n ? !!h : !!e.onOpenSurface, y = b(() => {
94
+ var a;
95
+ if (t) {
96
+ u == null || u();
97
+ return;
98
+ }
99
+ (a = e.onOpenNav) == null || a.call(e);
100
+ }, [u, t, e.onOpenNav]), k = b(() => {
101
+ var a;
102
+ if (n) {
103
+ h == null || h();
104
+ return;
105
+ }
106
+ (a = e.onOpenSurface) == null || a.call(e);
107
+ }, [h, e.onOpenSurface, n]), _ = b(() => {
108
+ t && (u == null || u()), n && (h == null || h()), D(), de();
109
+ }, [u, h, t, n]);
110
+ return ee({
111
+ shortcuts: A(() => {
112
+ const a = [];
113
+ return v && a.push({ key: "1", mod: !0, handler: y }), x && a.push({ key: "2", mod: !0, handler: k }), c === "chat" && a.push({ key: "Escape", allowInEditable: !0, handler: _ }), a;
114
+ }, [v, x, c, _, y, k])
115
+ }), S(() => {
116
+ const a = "workspace:chat-layout", m = "agent:chat-layout";
117
+ return f.unregisterByPluginId(a), f.unregisterByPluginId(m), f.registerCommand({
118
+ id: "workspace:open-session-history",
119
+ title: t ? "Close Session History" : "Open Session History",
120
+ keywords: ["sessions", "history", "drawer", t ? "close" : "open"],
121
+ shortcut: "⌘1",
122
+ pluginId: a,
123
+ when: () => v,
124
+ run: y
125
+ }), f.registerCommand({
126
+ id: "workspace:open-workbench",
127
+ title: n ? "Close Workbench" : "Open Workbench",
128
+ keywords: ["surface", "artifacts", "sources", "workbench", n ? "close" : "open"],
129
+ shortcut: "⌘2",
130
+ pluginId: a,
131
+ when: () => x,
132
+ run: k
133
+ }), c === "chat" && f.registerCommand({
134
+ id: "agent:focus-chat",
135
+ title: "Focus Chat",
136
+ keywords: ["agent", "chat", "prompt", "composer", "input", "focus"],
137
+ pluginId: m,
138
+ run: _
139
+ }), B && f.registerCommand({
140
+ id: "agent:new-chat",
141
+ title: "New Chat",
142
+ keywords: ["agent", "chat", "session", "new"],
143
+ pluginId: m,
144
+ run: B
145
+ }), () => {
146
+ f.unregisterByPluginId(a), f.unregisterByPluginId(m);
147
+ };
148
+ }, [
149
+ f,
150
+ t,
151
+ c,
152
+ r,
153
+ n,
154
+ e.navParams,
155
+ e.surfaceParams,
156
+ e.onOpenNav,
157
+ e.onOpenSurface,
158
+ v,
159
+ x,
160
+ u,
161
+ h,
162
+ B,
163
+ _,
164
+ y,
165
+ k
166
+ ]), S(() => {
167
+ if (!z || !I || !O) return;
168
+ const a = {
169
+ surface: z,
170
+ isWorkbenchOpen: I,
171
+ openWorkbench: O
172
+ };
173
+ return te.on(ne.uiCommand, ({ command: m }) => {
174
+ re(m, a);
175
+ });
176
+ }, [z, I, O]), /* @__PURE__ */ d(
177
+ "div",
178
+ {
179
+ "data-boring-workspace": "",
180
+ "data-boring-workspace-part": "shell",
181
+ className: g("relative flex h-full min-h-0 w-full overflow-hidden bg-background", e.className),
182
+ children: [
183
+ /* @__PURE__ */ d(
184
+ "aside",
185
+ {
186
+ "data-boring-workspace-part": "session-drawer",
187
+ "data-boring-state": t ? "expanded" : "collapsed",
188
+ "aria-label": "Session browser",
189
+ "aria-hidden": !t,
190
+ className: g(
191
+ "relative h-full min-h-0 shrink-0 overflow-hidden bg-background",
192
+ "transition-[width,min-width,max-width] duration-[280ms] ease-[cubic-bezier(0.22,1,0.36,1)]",
193
+ t && "border-r border-[color:oklch(from_var(--border)_l_c_h/0.6)]"
194
+ ),
195
+ style: {
196
+ width: t ? W : 0,
197
+ minWidth: t ? W : 0,
198
+ maxWidth: t ? W : 0,
199
+ willChange: "width"
200
+ },
201
+ children: [
202
+ /* @__PURE__ */ o(
203
+ "div",
204
+ {
205
+ className: g(
206
+ "h-full min-h-0 overflow-hidden",
207
+ "transition-opacity duration-[200ms] ease-[cubic-bezier(0.22,1,0.36,1)]",
208
+ t ? "opacity-100" : "opacity-0"
209
+ ),
210
+ children: /* @__PURE__ */ o(L, { id: i, params: e.navParams })
211
+ }
212
+ ),
213
+ t ? /* @__PURE__ */ o(
214
+ E,
215
+ {
216
+ side: "drawer-right",
217
+ ariaLabel: "Resize sessions drawer",
218
+ onResize: (a) => p((m) => C(m + a, 200, 360))
219
+ }
220
+ ) : null
221
+ ]
222
+ }
223
+ ),
224
+ /* @__PURE__ */ d(
225
+ "main",
226
+ {
227
+ "data-boring-workspace-part": "chat-stage",
228
+ "aria-label": "Chat stage",
229
+ className: "relative h-full min-h-0 min-w-0 flex-1 overflow-hidden bg-background",
230
+ children: [
231
+ /* @__PURE__ */ o(L, { id: c, params: e.centerParams }),
232
+ !t && e.onOpenNav ? /* @__PURE__ */ o(
233
+ K,
234
+ {
235
+ side: "left",
236
+ icon: "sessions",
237
+ onClick: e.onOpenNav,
238
+ label: "Sessions",
239
+ hint: "⌘1"
240
+ }
241
+ ) : null,
242
+ !n && e.onOpenSurface ? /* @__PURE__ */ o(
243
+ K,
244
+ {
245
+ side: "right",
246
+ icon: "workbench",
247
+ onClick: e.onOpenSurface,
248
+ label: "Workbench",
249
+ hint: "⌘2"
250
+ }
251
+ ) : null
252
+ ]
253
+ }
254
+ ),
255
+ r ? /* @__PURE__ */ d(
256
+ "aside",
257
+ {
258
+ "data-boring-workspace-part": "workbench",
259
+ "data-boring-state": n ? "expanded" : "collapsed",
260
+ "aria-label": n ? "Surface" : void 0,
261
+ "aria-hidden": !n,
262
+ className: g(
263
+ "relative h-full min-h-0 shrink-0 overflow-hidden bg-background",
264
+ "transition-[width,min-width,max-width] duration-[280ms] ease-[cubic-bezier(0.22,1,0.36,1)]",
265
+ n && "border-l border-[color:oklch(from_var(--border)_l_c_h/0.6)]"
266
+ ),
267
+ style: {
268
+ width: n ? P : 0,
269
+ minWidth: n ? P : 0,
270
+ maxWidth: n ? P : 0,
271
+ willChange: "width"
272
+ },
273
+ children: [
274
+ /* @__PURE__ */ o(
275
+ "div",
276
+ {
277
+ className: g(
278
+ "h-full min-h-0 overflow-hidden",
279
+ "transition-opacity duration-[200ms] ease-[cubic-bezier(0.22,1,0.36,1)]",
280
+ n ? "opacity-100" : "opacity-0"
281
+ ),
282
+ children: /* @__PURE__ */ o(L, { id: l, params: e.surfaceParams })
283
+ }
284
+ ),
285
+ n ? /* @__PURE__ */ o(
286
+ E,
287
+ {
288
+ side: "surface-left",
289
+ ariaLabel: "Resize workbench",
290
+ onResize: (a) => U((m) => C(m - a, 480, M))
291
+ }
292
+ ) : null
293
+ ]
294
+ }
295
+ ) : null
296
+ ]
297
+ }
298
+ );
299
+ }
300
+ function C(e, t, r) {
301
+ return Math.max(t, Math.min(r, e));
302
+ }
303
+ function j(e, t) {
304
+ const [r, n] = V(
305
+ () => e ? F(e, t) : t
306
+ );
307
+ S(() => {
308
+ n(e ? F(e, t) : t);
309
+ }, [e, t]);
310
+ const i = b(
311
+ (c) => {
312
+ n((l) => {
313
+ const s = typeof c == "function" ? c(l) : c;
314
+ return e && se(e, s), s;
315
+ });
316
+ },
317
+ [e]
318
+ );
319
+ return [r, i];
320
+ }
321
+ function ce() {
322
+ const [e, t] = V(() => typeof window < "u" ? window.innerWidth : 1200);
323
+ return S(() => {
324
+ const r = () => t(window.innerWidth);
325
+ return window.addEventListener("resize", r), () => window.removeEventListener("resize", r);
326
+ }, []), e;
327
+ }
328
+ function E({ side: e, ariaLabel: t, onResize: r }) {
329
+ const n = q(null), i = b((s) => {
330
+ s.preventDefault(), n.current = s.clientX, s.currentTarget.setPointerCapture(s.pointerId), document.body.style.cursor = "col-resize", document.body.style.userSelect = "none";
331
+ }, []), c = b((s) => {
332
+ if (n.current === null) return;
333
+ const w = s.clientX - n.current;
334
+ n.current = s.clientX, r(w);
335
+ }, [r]), l = b((s) => {
336
+ n.current !== null && (n.current = null, s.currentTarget.releasePointerCapture(s.pointerId), document.body.style.cursor = "", document.body.style.userSelect = "");
337
+ }, []);
338
+ return /* @__PURE__ */ o(
339
+ G,
340
+ {
341
+ "aria-label": t,
342
+ orientation: "vertical",
343
+ onResizeStart: i,
344
+ onPointerMove: c,
345
+ onPointerUp: l,
346
+ onPointerCancel: l,
347
+ className: g(
348
+ "absolute top-0 bottom-0 z-20 bg-transparent",
349
+ "transition-colors duration-200",
350
+ "hover:bg-border/70 hover:[transition-delay:150ms]",
351
+ "active:bg-muted-foreground/30",
352
+ e === "drawer-right" ? "right-0" : "left-0"
353
+ )
354
+ }
355
+ );
356
+ }
357
+ function N(e, t) {
358
+ const r = e == null ? void 0 : e[t];
359
+ return typeof r == "function" ? r : void 0;
360
+ }
361
+ function R(e, t) {
362
+ return N(e, t);
363
+ }
364
+ function D() {
365
+ if (typeof document > "u") return;
366
+ const e = document.querySelector(
367
+ '[data-boring-agent] textarea[name="message"], textarea[name="message"]'
368
+ );
369
+ e == null || e.focus();
370
+ }
371
+ function de() {
372
+ typeof window > "u" || window.requestAnimationFrame(() => {
373
+ D(), window.setTimeout(D, 320);
374
+ });
375
+ }
376
+ function L({ id: e, params: t }) {
377
+ const r = oe(), i = A(() => r.getComponents(), [r])[e], c = A(() => le(e), [e]);
378
+ return i ? /* @__PURE__ */ o(X, { fallback: /* @__PURE__ */ o(Z, { centered: !0 }), children: /* @__PURE__ */ o(
379
+ i,
380
+ {
381
+ params: t,
382
+ api: c,
383
+ containerApi: {}
384
+ }
385
+ ) }) : null;
386
+ }
387
+ function le(e) {
388
+ return {
389
+ id: e,
390
+ title: e,
391
+ setTitle: () => {
392
+ },
393
+ setActive: () => {
394
+ },
395
+ close: () => {
396
+ },
397
+ updateParameters: () => {
398
+ },
399
+ onDidParametersChange: () => ({ dispose() {
400
+ } }),
401
+ onDidActiveChange: () => ({ dispose() {
402
+ } }),
403
+ onDidDimensionsChange: () => ({ dispose() {
404
+ } }),
405
+ onDidLocationChange: () => ({ dispose() {
406
+ } }),
407
+ onDidTitleChange: () => ({ dispose() {
408
+ } }),
409
+ onWillFocus: () => ({ dispose() {
410
+ } }),
411
+ onDidFocus: () => ({ dispose() {
412
+ } }),
413
+ onDidBlur: () => ({ dispose() {
414
+ } }),
415
+ onWillVisibilityChange: () => ({ dispose() {
416
+ } }),
417
+ onDidVisibilityChange: () => ({ dispose() {
418
+ } }),
419
+ onDidConstraintsChange: () => ({ dispose() {
420
+ } })
421
+ };
422
+ }
423
+ function K({
424
+ side: e,
425
+ icon: t,
426
+ onClick: r,
427
+ label: n,
428
+ hint: i
429
+ }) {
430
+ return /* @__PURE__ */ o(
431
+ $,
432
+ {
433
+ type: "button",
434
+ variant: "ghost",
435
+ size: "icon-sm",
436
+ onClick: r,
437
+ "aria-label": n,
438
+ title: i ? `${n} (${i})` : n,
439
+ className: g(
440
+ "absolute top-1/2 z-30 h-9 w-9 -translate-y-1/2 gap-0.5 rounded-lg bg-background text-muted-foreground",
441
+ e === "left" ? "left-2" : "right-2",
442
+ "shadow-[0_1px_2px_-1px_oklch(0_0_0/0.08),0_2px_8px_-4px_oklch(0_0_0/0.10),inset_0_0_0_1px_oklch(from_var(--border)_l_c_h/0.7)]",
443
+ "hover:-translate-y-[calc(50%+1px)] hover:bg-muted/60 hover:text-foreground hover:shadow-[0_2px_4px_-1px_oklch(0_0_0/0.08),0_4px_12px_-4px_oklch(0_0_0/0.10),inset_0_0_0_1px_oklch(from_var(--border)_l_c_h/0.9)]",
444
+ "focus-visible:ring-ring/40"
445
+ ),
446
+ children: t === "sessions" ? /* @__PURE__ */ d("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
447
+ /* @__PURE__ */ o("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeWidth: "1.8" }),
448
+ /* @__PURE__ */ o("path", { d: "M12 7v5l3.2 2", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })
449
+ ] }) : /* @__PURE__ */ o("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ o("path", { d: "M3 7.5 A1.5 1.5 0 0 1 4.5 6 h4 l2 2 h9 A1.5 1.5 0 0 1 21 9.5 V17.5 A1.5 1.5 0 0 1 19.5 19 H4.5 A1.5 1.5 0 0 1 3 17.5 Z", stroke: "currentColor", strokeWidth: "1.8", strokeLinejoin: "round" }) })
450
+ }
451
+ );
452
+ }
453
+ function ye({
454
+ appTitle: e = "Boring",
455
+ sessionTitle: t,
456
+ onCommandPalette: r,
457
+ onNewChat: n,
458
+ topBarLeft: i,
459
+ topBarRight: c,
460
+ className: l
461
+ }) {
462
+ const s = c ?? null;
463
+ return /* @__PURE__ */ d(
464
+ "header",
465
+ {
466
+ "data-boring-workspace-part": "topbar",
467
+ className: g(
468
+ "relative flex items-center justify-between gap-3 px-4",
469
+ "bg-background border-b border-[color:oklch(from_var(--border)_l_c_h/0.4)]",
470
+ l
471
+ ),
472
+ style: { height: 52 },
473
+ "aria-label": "App top bar",
474
+ children: [
475
+ /* @__PURE__ */ o("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: i ?? /* @__PURE__ */ d(H, { children: [
476
+ /* @__PURE__ */ o(
477
+ "div",
478
+ {
479
+ "aria-hidden": "true",
480
+ className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background",
481
+ children: e.charAt(0).toUpperCase()
482
+ }
483
+ ),
484
+ /* @__PURE__ */ o("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: e }),
485
+ t && /* @__PURE__ */ d(H, { children: [
486
+ /* @__PURE__ */ o("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
487
+ /* @__PURE__ */ o("span", { className: "truncate text-[13px] font-normal text-muted-foreground", children: t })
488
+ ] })
489
+ ] }) }),
490
+ /* @__PURE__ */ d(
491
+ J,
492
+ {
493
+ type: "button",
494
+ variant: "ghost",
495
+ size: "sm",
496
+ onClick: r,
497
+ className: "group h-7 gap-1.5 px-1.5 text-[12.5px] text-muted-foreground/60 hover:bg-transparent hover:text-foreground focus-visible:text-foreground",
498
+ "aria-label": "Search catalogs and commands",
499
+ title: "Command palette (⌘K)",
500
+ children: [
501
+ /* @__PURE__ */ o(ae, { className: "h-3.5 w-3.5 shrink-0 opacity-70", strokeWidth: 1.75 }),
502
+ /* @__PURE__ */ o("span", { className: "font-normal tracking-tight", children: "Search" }),
503
+ /* @__PURE__ */ o(Q, { className: "ml-1 border-0 bg-transparent p-0 text-[10px] shadow-none group-hover:text-muted-foreground", children: "⌘K" })
504
+ ]
505
+ }
506
+ ),
507
+ /* @__PURE__ */ d("div", { className: "flex flex-1 shrink-0 items-center justify-end gap-1", children: [
508
+ n && /* @__PURE__ */ o(
509
+ $,
510
+ {
511
+ type: "button",
512
+ variant: "ghost",
513
+ size: "icon-sm",
514
+ onClick: n,
515
+ "aria-label": "New chat",
516
+ title: "New chat",
517
+ children: /* @__PURE__ */ o(ie, { className: "h-4 w-4" })
518
+ }
519
+ ),
520
+ s
521
+ ] })
522
+ ]
523
+ }
524
+ );
525
+ }
526
+ function ke({
527
+ title: e = "Loading workspace",
528
+ description: t = "Preparing the workspace context.",
529
+ status: r = "Loading",
530
+ fullscreen: n = !0,
531
+ className: i
532
+ }) {
533
+ return /* @__PURE__ */ o(
534
+ "section",
535
+ {
536
+ role: "status",
537
+ "aria-live": "polite",
538
+ "aria-busy": "true",
539
+ className: g(
540
+ "flex h-full w-full items-center justify-center bg-background px-6 text-foreground",
541
+ n ? "min-h-screen" : "min-h-[240px]",
542
+ i
543
+ ),
544
+ children: /* @__PURE__ */ d("div", { className: "flex w-full max-w-sm flex-col items-center gap-5 text-center", children: [
545
+ /* @__PURE__ */ o("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg border border-border bg-card text-foreground", children: /* @__PURE__ */ o(
546
+ "span",
547
+ {
548
+ "aria-hidden": "true",
549
+ className: "h-5 w-5 animate-spin rounded-full border-2 border-current border-t-transparent opacity-70"
550
+ }
551
+ ) }),
552
+ /* @__PURE__ */ d("div", { className: "space-y-2", children: [
553
+ /* @__PURE__ */ o("h2", { className: "text-base font-medium text-foreground", children: e }),
554
+ t ? /* @__PURE__ */ o("p", { className: "text-sm leading-6 text-muted-foreground", children: t }) : null
555
+ ] }),
556
+ r ? /* @__PURE__ */ o("p", { className: "text-xs font-medium text-muted-foreground/80", children: r }) : null
557
+ ] })
558
+ }
559
+ );
560
+ }
561
+ export {
562
+ xe as C,
563
+ ye as T,
564
+ ke as W,
565
+ ve as b,
566
+ be as r,
567
+ we as w
568
+ };
@@ -0,0 +1,28 @@
1
+ type JSONSchema = Record<string, unknown>;
2
+ interface ToolExecContext {
3
+ abortSignal: AbortSignal;
4
+ toolCallId: string;
5
+ onUpdate?: (partial: string) => void;
6
+ }
7
+ interface ToolResult {
8
+ content: Array<{
9
+ type: "text";
10
+ text: string;
11
+ }>;
12
+ isError?: boolean;
13
+ details?: unknown;
14
+ }
15
+ /**
16
+ * Structural tool contract accepted from workspace plugins and UI tool
17
+ * factories. Kept agent-runtime-neutral so only the app integration layer
18
+ * needs to import @hachej/boring-agent.
19
+ */
20
+ interface AgentTool {
21
+ name: string;
22
+ description: string;
23
+ promptSnippet?: string;
24
+ parameters: JSONSchema;
25
+ execute(params: Record<string, unknown>, ctx: ToolExecContext): Promise<ToolResult>;
26
+ }
27
+
28
+ export type { AgentTool as A, JSONSchema as J, ToolExecContext as T, ToolResult as a };