@hachej/boring-workspace 0.1.12 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{WorkspaceLoadingState-CPQBxYFG.js → WorkspaceLoadingState-BjZGQLS_.js} +85 -85
- package/dist/app-front.js +1 -1
- package/dist/app-server.d.ts +3 -3
- package/dist/app-server.js +25 -13
- package/dist/server.d.ts +3 -3
- package/dist/server.js +17 -10
- package/dist/workspace.css +0 -3
- package/dist/workspace.js +1 -1
- package/package.json +3 -3
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { jsxs as d, jsx as
|
|
2
|
-
import { useCallback as
|
|
1
|
+
import { jsxs as d, jsx as a, Fragment as H } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback as p, useMemo as D, useEffect as S, useState as V, Suspense as U, useRef as q } from "react";
|
|
3
3
|
import { LoadingState as Z, ResizeHandle as G, IconButton as $, Button as J, Kbd as Q } from "@hachej/boring-ui-kit";
|
|
4
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
|
|
6
|
-
import { Search as
|
|
7
|
-
function
|
|
5
|
+
import { $ as Y, a6 as ee, E as te, am as ne, ak as re, u as ae } from "./CommandPalette-Dme9em28.js";
|
|
6
|
+
import { Search as oe, Plus as ie } from "lucide-react";
|
|
7
|
+
function pe(e, t, r = !0) {
|
|
8
8
|
if (!r || typeof window > "u") return t;
|
|
9
9
|
try {
|
|
10
10
|
const n = window.localStorage.getItem(e);
|
|
@@ -49,8 +49,8 @@ function ve(e = {}) {
|
|
|
49
49
|
surfaceParams: l,
|
|
50
50
|
sidebar: s,
|
|
51
51
|
sidebarParams: w
|
|
52
|
-
} = e,
|
|
53
|
-
return t &&
|
|
52
|
+
} = e, b = [];
|
|
53
|
+
return t && b.push({
|
|
54
54
|
id: "nav",
|
|
55
55
|
position: "left",
|
|
56
56
|
panel: t,
|
|
@@ -58,13 +58,13 @@ function ve(e = {}) {
|
|
|
58
58
|
locked: !0,
|
|
59
59
|
hideHeader: !0,
|
|
60
60
|
constraints: { minWidth: 60, maxWidth: 60 }
|
|
61
|
-
}),
|
|
61
|
+
}), b.push({
|
|
62
62
|
id: "center",
|
|
63
63
|
position: "center",
|
|
64
64
|
panel: n,
|
|
65
65
|
params: i,
|
|
66
66
|
hideHeader: !0
|
|
67
|
-
}), s &&
|
|
67
|
+
}), s && b.push({
|
|
68
68
|
id: "sidebar",
|
|
69
69
|
position: "left",
|
|
70
70
|
panel: s,
|
|
@@ -73,7 +73,7 @@ function ve(e = {}) {
|
|
|
73
73
|
collapsible: !0,
|
|
74
74
|
collapsedWidth: 40,
|
|
75
75
|
constraints: { minWidth: 200, maxWidthViewportRatio: 0.5 }
|
|
76
|
-
}), c &&
|
|
76
|
+
}), c && b.push({
|
|
77
77
|
id: "surface",
|
|
78
78
|
position: "right",
|
|
79
79
|
panel: c,
|
|
@@ -81,45 +81,45 @@ function ve(e = {}) {
|
|
|
81
81
|
hideHeader: !0,
|
|
82
82
|
dynamic: !0,
|
|
83
83
|
placeholder: "empty"
|
|
84
|
-
}), { version: "2.0", groups:
|
|
84
|
+
}), { version: "2.0", groups: b };
|
|
85
85
|
}
|
|
86
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,
|
|
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, b] = E(
|
|
88
88
|
e.storageKey ? `${e.storageKey}:drawerWidth` : void 0,
|
|
89
89
|
260
|
|
90
|
-
), [T,
|
|
90
|
+
), [T, X] = E(
|
|
91
91
|
e.storageKey ? `${e.storageKey}:surfaceWidth` : void 0,
|
|
92
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 =
|
|
94
|
-
var
|
|
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 = p(() => {
|
|
94
|
+
var o;
|
|
95
95
|
if (t) {
|
|
96
96
|
u == null || u();
|
|
97
97
|
return;
|
|
98
98
|
}
|
|
99
|
-
(
|
|
100
|
-
}, [u, t, e.onOpenNav]), k =
|
|
101
|
-
var
|
|
99
|
+
(o = e.onOpenNav) == null || o.call(e);
|
|
100
|
+
}, [u, t, e.onOpenNav]), k = p(() => {
|
|
101
|
+
var o;
|
|
102
102
|
if (n) {
|
|
103
103
|
h == null || h();
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
|
-
(
|
|
107
|
-
}, [h, e.onOpenSurface, n]), _ =
|
|
108
|
-
t && (u == null || u()), n && (h == null || h()),
|
|
106
|
+
(o = e.onOpenSurface) == null || o.call(e);
|
|
107
|
+
}, [h, e.onOpenSurface, n]), _ = p(() => {
|
|
108
|
+
t && (u == null || u()), n && (h == null || h()), A(), de();
|
|
109
109
|
}, [u, h, t, n]);
|
|
110
110
|
return ee({
|
|
111
|
-
shortcuts:
|
|
112
|
-
const
|
|
113
|
-
return v &&
|
|
111
|
+
shortcuts: D(() => {
|
|
112
|
+
const o = [];
|
|
113
|
+
return v && o.push({ key: "1", mod: !0, handler: y }), x && o.push({ key: "2", mod: !0, handler: k }), c === "chat" && o.push({ key: "Escape", allowInEditable: !0, handler: _ }), o;
|
|
114
114
|
}, [v, x, c, _, y, k])
|
|
115
115
|
}), S(() => {
|
|
116
|
-
const
|
|
117
|
-
return f.unregisterByPluginId(
|
|
116
|
+
const o = "workspace:chat-layout", m = "agent:chat-layout";
|
|
117
|
+
return f.unregisterByPluginId(o), f.unregisterByPluginId(m), f.registerCommand({
|
|
118
118
|
id: "workspace:open-session-history",
|
|
119
119
|
title: t ? "Close Session History" : "Open Session History",
|
|
120
120
|
keywords: ["sessions", "history", "drawer", t ? "close" : "open"],
|
|
121
121
|
shortcut: "⌘1",
|
|
122
|
-
pluginId:
|
|
122
|
+
pluginId: o,
|
|
123
123
|
when: () => v,
|
|
124
124
|
run: y
|
|
125
125
|
}), f.registerCommand({
|
|
@@ -127,7 +127,7 @@ function xe(e) {
|
|
|
127
127
|
title: n ? "Close Workbench" : "Open Workbench",
|
|
128
128
|
keywords: ["surface", "artifacts", "sources", "workbench", n ? "close" : "open"],
|
|
129
129
|
shortcut: "⌘2",
|
|
130
|
-
pluginId:
|
|
130
|
+
pluginId: o,
|
|
131
131
|
when: () => x,
|
|
132
132
|
run: k
|
|
133
133
|
}), c === "chat" && f.registerCommand({
|
|
@@ -143,7 +143,7 @@ function xe(e) {
|
|
|
143
143
|
pluginId: m,
|
|
144
144
|
run: B
|
|
145
145
|
}), () => {
|
|
146
|
-
f.unregisterByPluginId(
|
|
146
|
+
f.unregisterByPluginId(o), f.unregisterByPluginId(m);
|
|
147
147
|
};
|
|
148
148
|
}, [
|
|
149
149
|
f,
|
|
@@ -165,13 +165,13 @@ function xe(e) {
|
|
|
165
165
|
k
|
|
166
166
|
]), S(() => {
|
|
167
167
|
if (!z || !I || !O) return;
|
|
168
|
-
const
|
|
168
|
+
const o = {
|
|
169
169
|
surface: z,
|
|
170
170
|
isWorkbenchOpen: I,
|
|
171
171
|
openWorkbench: O
|
|
172
172
|
};
|
|
173
173
|
return te.on(ne.uiCommand, ({ command: m }) => {
|
|
174
|
-
re(m,
|
|
174
|
+
re(m, o);
|
|
175
175
|
});
|
|
176
176
|
}, [z, I, O]), /* @__PURE__ */ d(
|
|
177
177
|
"div",
|
|
@@ -199,7 +199,7 @@ function xe(e) {
|
|
|
199
199
|
willChange: "width"
|
|
200
200
|
},
|
|
201
201
|
children: [
|
|
202
|
-
/* @__PURE__ */
|
|
202
|
+
/* @__PURE__ */ a(
|
|
203
203
|
"div",
|
|
204
204
|
{
|
|
205
205
|
className: g(
|
|
@@ -207,15 +207,15 @@ function xe(e) {
|
|
|
207
207
|
"transition-opacity duration-[200ms] ease-[cubic-bezier(0.22,1,0.36,1)]",
|
|
208
208
|
t ? "opacity-100" : "opacity-0"
|
|
209
209
|
),
|
|
210
|
-
children: /* @__PURE__ */
|
|
210
|
+
children: /* @__PURE__ */ a(L, { id: i, params: e.navParams })
|
|
211
211
|
}
|
|
212
212
|
),
|
|
213
|
-
t ? /* @__PURE__ */
|
|
214
|
-
|
|
213
|
+
t ? /* @__PURE__ */ a(
|
|
214
|
+
K,
|
|
215
215
|
{
|
|
216
216
|
side: "drawer-right",
|
|
217
217
|
ariaLabel: "Resize sessions drawer",
|
|
218
|
-
onResize: (
|
|
218
|
+
onResize: (o) => b((m) => C(m + o, 200, 360))
|
|
219
219
|
}
|
|
220
220
|
) : null
|
|
221
221
|
]
|
|
@@ -228,9 +228,9 @@ function xe(e) {
|
|
|
228
228
|
"aria-label": "Chat stage",
|
|
229
229
|
className: "relative h-full min-h-0 min-w-0 flex-1 overflow-hidden bg-background",
|
|
230
230
|
children: [
|
|
231
|
-
/* @__PURE__ */
|
|
232
|
-
!t && e.onOpenNav ? /* @__PURE__ */
|
|
233
|
-
|
|
231
|
+
/* @__PURE__ */ a(L, { id: c, params: e.centerParams }),
|
|
232
|
+
!t && e.onOpenNav ? /* @__PURE__ */ a(
|
|
233
|
+
j,
|
|
234
234
|
{
|
|
235
235
|
side: "left",
|
|
236
236
|
icon: "sessions",
|
|
@@ -239,8 +239,8 @@ function xe(e) {
|
|
|
239
239
|
hint: "⌘1"
|
|
240
240
|
}
|
|
241
241
|
) : null,
|
|
242
|
-
!n && e.onOpenSurface ? /* @__PURE__ */
|
|
243
|
-
|
|
242
|
+
!n && e.onOpenSurface ? /* @__PURE__ */ a(
|
|
243
|
+
j,
|
|
244
244
|
{
|
|
245
245
|
side: "right",
|
|
246
246
|
icon: "workbench",
|
|
@@ -271,7 +271,7 @@ function xe(e) {
|
|
|
271
271
|
willChange: "width"
|
|
272
272
|
},
|
|
273
273
|
children: [
|
|
274
|
-
/* @__PURE__ */
|
|
274
|
+
/* @__PURE__ */ a(
|
|
275
275
|
"div",
|
|
276
276
|
{
|
|
277
277
|
className: g(
|
|
@@ -279,15 +279,15 @@ function xe(e) {
|
|
|
279
279
|
"transition-opacity duration-[200ms] ease-[cubic-bezier(0.22,1,0.36,1)]",
|
|
280
280
|
n ? "opacity-100" : "opacity-0"
|
|
281
281
|
),
|
|
282
|
-
children: /* @__PURE__ */
|
|
282
|
+
children: /* @__PURE__ */ a(L, { id: l, params: e.surfaceParams })
|
|
283
283
|
}
|
|
284
284
|
),
|
|
285
|
-
n ? /* @__PURE__ */
|
|
286
|
-
|
|
285
|
+
n ? /* @__PURE__ */ a(
|
|
286
|
+
K,
|
|
287
287
|
{
|
|
288
288
|
side: "surface-left",
|
|
289
289
|
ariaLabel: "Resize workbench",
|
|
290
|
-
onResize: (
|
|
290
|
+
onResize: (o) => X((m) => C(m - o, 480, M))
|
|
291
291
|
}
|
|
292
292
|
) : null
|
|
293
293
|
]
|
|
@@ -300,14 +300,14 @@ function xe(e) {
|
|
|
300
300
|
function C(e, t, r) {
|
|
301
301
|
return Math.max(t, Math.min(r, e));
|
|
302
302
|
}
|
|
303
|
-
function
|
|
303
|
+
function E(e, t) {
|
|
304
304
|
const [r, n] = V(
|
|
305
305
|
() => e ? F(e, t) : t
|
|
306
306
|
);
|
|
307
307
|
S(() => {
|
|
308
308
|
n(e ? F(e, t) : t);
|
|
309
309
|
}, [e, t]);
|
|
310
|
-
const i =
|
|
310
|
+
const i = p(
|
|
311
311
|
(c) => {
|
|
312
312
|
n((l) => {
|
|
313
313
|
const s = typeof c == "function" ? c(l) : c;
|
|
@@ -325,17 +325,17 @@ function ce() {
|
|
|
325
325
|
return window.addEventListener("resize", r), () => window.removeEventListener("resize", r);
|
|
326
326
|
}, []), e;
|
|
327
327
|
}
|
|
328
|
-
function
|
|
329
|
-
const n = q(null), i =
|
|
328
|
+
function K({ side: e, ariaLabel: t, onResize: r }) {
|
|
329
|
+
const n = q(null), i = p((s) => {
|
|
330
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 =
|
|
331
|
+
}, []), c = p((s) => {
|
|
332
332
|
if (n.current === null) return;
|
|
333
333
|
const w = s.clientX - n.current;
|
|
334
334
|
n.current = s.clientX, r(w);
|
|
335
|
-
}, [r]), l =
|
|
335
|
+
}, [r]), l = p((s) => {
|
|
336
336
|
n.current !== null && (n.current = null, s.currentTarget.releasePointerCapture(s.pointerId), document.body.style.cursor = "", document.body.style.userSelect = "");
|
|
337
337
|
}, []);
|
|
338
|
-
return /* @__PURE__ */
|
|
338
|
+
return /* @__PURE__ */ a(
|
|
339
339
|
G,
|
|
340
340
|
{
|
|
341
341
|
"aria-label": t,
|
|
@@ -361,7 +361,7 @@ function N(e, t) {
|
|
|
361
361
|
function R(e, t) {
|
|
362
362
|
return N(e, t);
|
|
363
363
|
}
|
|
364
|
-
function
|
|
364
|
+
function A() {
|
|
365
365
|
if (typeof document > "u") return;
|
|
366
366
|
const e = document.querySelector(
|
|
367
367
|
'[data-boring-agent] textarea[name="message"], textarea[name="message"]'
|
|
@@ -370,12 +370,12 @@ function D() {
|
|
|
370
370
|
}
|
|
371
371
|
function de() {
|
|
372
372
|
typeof window > "u" || window.requestAnimationFrame(() => {
|
|
373
|
-
|
|
373
|
+
A(), window.setTimeout(A, 320);
|
|
374
374
|
});
|
|
375
375
|
}
|
|
376
376
|
function L({ id: e, params: t }) {
|
|
377
|
-
const r =
|
|
378
|
-
return i ? /* @__PURE__ */
|
|
377
|
+
const r = ae(), i = D(() => r.getComponents(), [r])[e], c = D(() => le(e), [e]);
|
|
378
|
+
return i ? /* @__PURE__ */ a(U, { fallback: /* @__PURE__ */ a(Z, { centered: !0 }), children: /* @__PURE__ */ a(
|
|
379
379
|
i,
|
|
380
380
|
{
|
|
381
381
|
params: t,
|
|
@@ -420,14 +420,14 @@ function le(e) {
|
|
|
420
420
|
} })
|
|
421
421
|
};
|
|
422
422
|
}
|
|
423
|
-
function
|
|
423
|
+
function j({
|
|
424
424
|
side: e,
|
|
425
425
|
icon: t,
|
|
426
426
|
onClick: r,
|
|
427
427
|
label: n,
|
|
428
428
|
hint: i
|
|
429
429
|
}) {
|
|
430
|
-
return /* @__PURE__ */
|
|
430
|
+
return /* @__PURE__ */ a(
|
|
431
431
|
$,
|
|
432
432
|
{
|
|
433
433
|
type: "button",
|
|
@@ -444,9 +444,9 @@ function K({
|
|
|
444
444
|
"focus-visible:ring-ring/40"
|
|
445
445
|
),
|
|
446
446
|
children: t === "sessions" ? /* @__PURE__ */ d("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
|
|
447
|
-
/* @__PURE__ */
|
|
448
|
-
/* @__PURE__ */
|
|
449
|
-
] }) : /* @__PURE__ */
|
|
447
|
+
/* @__PURE__ */ a("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeWidth: "1.8" }),
|
|
448
|
+
/* @__PURE__ */ a("path", { d: "M12 7v5l3.2 2", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })
|
|
449
|
+
] }) : /* @__PURE__ */ a("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ a("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
450
|
}
|
|
451
451
|
);
|
|
452
452
|
}
|
|
@@ -465,26 +465,26 @@ function ye({
|
|
|
465
465
|
{
|
|
466
466
|
"data-boring-workspace-part": "topbar",
|
|
467
467
|
className: g(
|
|
468
|
-
"relative flex items-center justify-between gap-
|
|
468
|
+
"relative flex items-center justify-between gap-2 px-3",
|
|
469
469
|
"bg-background border-b border-[color:oklch(from_var(--border)_l_c_h/0.4)]",
|
|
470
470
|
l
|
|
471
471
|
),
|
|
472
|
-
style: { height:
|
|
472
|
+
style: { height: 40 },
|
|
473
473
|
"aria-label": "App top bar",
|
|
474
474
|
children: [
|
|
475
|
-
/* @__PURE__ */
|
|
476
|
-
/* @__PURE__ */
|
|
477
|
-
"
|
|
475
|
+
/* @__PURE__ */ a("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: i ?? /* @__PURE__ */ d(H, { children: [
|
|
476
|
+
/* @__PURE__ */ a(
|
|
477
|
+
"img",
|
|
478
478
|
{
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
479
|
+
src: "https://chatgpt.com/backend-api/estuary/content?id=file_000000006a4471f4b8411fcbfde271c6&ts=493962&p=fs&cid=1&sig=b406cfec61d387bdedd898858283b389f31ad2bd3eb7a358a6d1efa23e9afa83&v=0",
|
|
480
|
+
alt: e,
|
|
481
|
+
className: "h-6 w-6 shrink-0 rounded-md"
|
|
482
482
|
}
|
|
483
483
|
),
|
|
484
|
-
/* @__PURE__ */
|
|
484
|
+
/* @__PURE__ */ a("span", { className: "truncate text-[12px] font-medium tracking-tight text-foreground", children: e }),
|
|
485
485
|
t && /* @__PURE__ */ d(H, { children: [
|
|
486
|
-
/* @__PURE__ */
|
|
487
|
-
/* @__PURE__ */
|
|
486
|
+
/* @__PURE__ */ a("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
|
|
487
|
+
/* @__PURE__ */ a("span", { className: "truncate text-[12px] font-normal text-muted-foreground", children: t })
|
|
488
488
|
] })
|
|
489
489
|
] }) }),
|
|
490
490
|
/* @__PURE__ */ d(
|
|
@@ -494,18 +494,18 @@ function ye({
|
|
|
494
494
|
variant: "ghost",
|
|
495
495
|
size: "sm",
|
|
496
496
|
onClick: r,
|
|
497
|
-
className: "group h-
|
|
497
|
+
className: "group h-6 gap-1 px-1.5 text-[12px] text-muted-foreground/60 hover:bg-transparent hover:text-foreground focus-visible:text-foreground",
|
|
498
498
|
"aria-label": "Search catalogs and commands",
|
|
499
499
|
title: "Command palette (⌘K)",
|
|
500
500
|
children: [
|
|
501
|
-
/* @__PURE__ */
|
|
502
|
-
/* @__PURE__ */
|
|
503
|
-
/* @__PURE__ */
|
|
501
|
+
/* @__PURE__ */ a(oe, { className: "h-3 w-3 shrink-0 opacity-70", strokeWidth: 1.75 }),
|
|
502
|
+
/* @__PURE__ */ a("span", { className: "font-normal tracking-tight", children: "Search" }),
|
|
503
|
+
/* @__PURE__ */ a(Q, { className: "ml-1 border-0 bg-transparent p-0 text-[10px] shadow-none group-hover:text-muted-foreground", children: "⌘K" })
|
|
504
504
|
]
|
|
505
505
|
}
|
|
506
506
|
),
|
|
507
507
|
/* @__PURE__ */ d("div", { className: "flex flex-1 shrink-0 items-center justify-end gap-1", children: [
|
|
508
|
-
n && /* @__PURE__ */
|
|
508
|
+
n && /* @__PURE__ */ a(
|
|
509
509
|
$,
|
|
510
510
|
{
|
|
511
511
|
type: "button",
|
|
@@ -514,7 +514,7 @@ function ye({
|
|
|
514
514
|
onClick: n,
|
|
515
515
|
"aria-label": "New chat",
|
|
516
516
|
title: "New chat",
|
|
517
|
-
children: /* @__PURE__ */
|
|
517
|
+
children: /* @__PURE__ */ a(ie, { className: "h-4 w-4" })
|
|
518
518
|
}
|
|
519
519
|
),
|
|
520
520
|
s
|
|
@@ -530,7 +530,7 @@ function ke({
|
|
|
530
530
|
fullscreen: n = !0,
|
|
531
531
|
className: i
|
|
532
532
|
}) {
|
|
533
|
-
return /* @__PURE__ */
|
|
533
|
+
return /* @__PURE__ */ a(
|
|
534
534
|
"section",
|
|
535
535
|
{
|
|
536
536
|
role: "status",
|
|
@@ -542,7 +542,7 @@ function ke({
|
|
|
542
542
|
i
|
|
543
543
|
),
|
|
544
544
|
children: /* @__PURE__ */ d("div", { className: "flex w-full max-w-sm flex-col items-center gap-5 text-center", children: [
|
|
545
|
-
/* @__PURE__ */
|
|
545
|
+
/* @__PURE__ */ a("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg border border-border bg-card text-foreground", children: /* @__PURE__ */ a(
|
|
546
546
|
"span",
|
|
547
547
|
{
|
|
548
548
|
"aria-hidden": "true",
|
|
@@ -550,10 +550,10 @@ function ke({
|
|
|
550
550
|
}
|
|
551
551
|
) }),
|
|
552
552
|
/* @__PURE__ */ d("div", { className: "space-y-2", children: [
|
|
553
|
-
/* @__PURE__ */
|
|
554
|
-
t ? /* @__PURE__ */
|
|
553
|
+
/* @__PURE__ */ a("h2", { className: "text-base font-medium text-foreground", children: e }),
|
|
554
|
+
t ? /* @__PURE__ */ a("p", { className: "text-sm leading-6 text-muted-foreground", children: t }) : null
|
|
555
555
|
] }),
|
|
556
|
-
r ? /* @__PURE__ */
|
|
556
|
+
r ? /* @__PURE__ */ a("p", { className: "text-xs font-medium text-muted-foreground/80", children: r }) : null
|
|
557
557
|
] })
|
|
558
558
|
}
|
|
559
559
|
);
|
|
@@ -563,6 +563,6 @@ export {
|
|
|
563
563
|
ye as T,
|
|
564
564
|
ke as W,
|
|
565
565
|
ve as b,
|
|
566
|
-
|
|
566
|
+
pe as r,
|
|
567
567
|
we as w
|
|
568
568
|
};
|
package/dist/app-front.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx as d, jsxs as Te, Fragment as x } from "react/jsx-runtime";
|
|
|
2
2
|
import { useSyncExternalStore as ze, useMemo as v, useRef as K, useState as X, useEffect as y, useCallback as P } from "react";
|
|
3
3
|
import { ChatPanel as Fe, useSessions as Ge } from "@hachej/boring-agent/front";
|
|
4
4
|
import { aj as ke, q as Ye, ak as Qe, u as Xe, al as Ze } from "./CommandPalette-Dme9em28.js";
|
|
5
|
-
import { T as He, C as qe, r as Ee, w as et, W as $e } from "./WorkspaceLoadingState-
|
|
5
|
+
import { T as He, C as qe, r as Ee, w as et, W as $e } from "./WorkspaceLoadingState-BjZGQLS_.js";
|
|
6
6
|
function tt() {
|
|
7
7
|
const e = `s${Date.now()}`;
|
|
8
8
|
return {
|
package/dist/app-server.d.ts
CHANGED
|
@@ -28,9 +28,9 @@ interface CreateWorkspaceAgentServerOptions extends WorkspaceAgentCreateOptions,
|
|
|
28
28
|
};
|
|
29
29
|
/**
|
|
30
30
|
* Whether exec_ui should stat-check file paths against the workspaceRoot
|
|
31
|
-
* before queueing the command. Defaults to true
|
|
32
|
-
*
|
|
33
|
-
* not on the host server running
|
|
31
|
+
* before queueing the command. Defaults to true only for local host-backed
|
|
32
|
+
* modes (direct/local). Remote sandbox modes should leave this false because
|
|
33
|
+
* workspace files may not exist on the host server running Fastify.
|
|
34
34
|
*/
|
|
35
35
|
validateUiPaths?: boolean;
|
|
36
36
|
}
|
package/dist/app-server.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// src/app/server/createWorkspaceAgentServer.ts
|
|
2
2
|
import {
|
|
3
|
+
autoDetectMode,
|
|
3
4
|
createAgentApp,
|
|
4
|
-
provisionRuntimeWorkspace
|
|
5
|
+
provisionRuntimeWorkspace,
|
|
6
|
+
resolveMode
|
|
5
7
|
} from "@hachej/boring-agent/server";
|
|
6
8
|
import { join } from "path";
|
|
7
9
|
|
|
@@ -49,7 +51,7 @@ function createInMemoryBridge() {
|
|
|
49
51
|
|
|
50
52
|
// src/server/ui-control/tools/uiTools.ts
|
|
51
53
|
import { access } from "fs/promises";
|
|
52
|
-
import { resolve, isAbsolute, relative } from "path";
|
|
54
|
+
import { resolve, isAbsolute, relative, win32 } from "path";
|
|
53
55
|
function makeError(message) {
|
|
54
56
|
return {
|
|
55
57
|
content: [{ type: "text", text: message }],
|
|
@@ -61,9 +63,15 @@ function getPathParam(kind, params) {
|
|
|
61
63
|
const raw = kind === "navigateToLine" ? params.file : params.path;
|
|
62
64
|
return typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
63
65
|
}
|
|
66
|
+
function isPathAbsolute(filePath) {
|
|
67
|
+
return isAbsolute(filePath) || win32.isAbsolute(filePath);
|
|
68
|
+
}
|
|
69
|
+
function isOutsideWorkspaceRel(rel) {
|
|
70
|
+
return rel === ".." || rel.startsWith("../") || rel.startsWith("..\\") || isPathAbsolute(rel);
|
|
71
|
+
}
|
|
64
72
|
function validatePathSyntax(relPath, workspaceRoot) {
|
|
65
73
|
const rootHint = workspaceRoot ? ` (${workspaceRoot})` : "";
|
|
66
|
-
if (
|
|
74
|
+
if (isPathAbsolute(relPath)) {
|
|
67
75
|
return {
|
|
68
76
|
ok: false,
|
|
69
77
|
reason: `path "${relPath}" is absolute \u2014 pass a path relative to the workspace root${rootHint}.`
|
|
@@ -85,7 +93,7 @@ async function validatePath(workspaceRoot, relPath) {
|
|
|
85
93
|
if (!syntax.ok) return syntax;
|
|
86
94
|
const resolved = resolve(workspaceRoot, relPath);
|
|
87
95
|
const rel = relative(workspaceRoot, resolved);
|
|
88
|
-
if (
|
|
96
|
+
if (isOutsideWorkspaceRel(rel)) {
|
|
89
97
|
return {
|
|
90
98
|
ok: false,
|
|
91
99
|
reason: `path "${relPath}" escapes the workspace root (${workspaceRoot}).`
|
|
@@ -188,13 +196,14 @@ function createExecUiTool(uiBridge, opts = {}) {
|
|
|
188
196
|
" auto-opens if collapsed. Path must be relative to the",
|
|
189
197
|
" workspace root (e.g. `src/foo.ts`, not `foo.ts` if it",
|
|
190
198
|
" lives under src/).",
|
|
191
|
-
" Recovery on file-not-found:
|
|
192
|
-
"
|
|
193
|
-
" exist. On that error,
|
|
194
|
-
" grep) to locate the file,
|
|
195
|
-
" openFile AGAIN using the EXACT path
|
|
196
|
-
" give up and don't switch to the read
|
|
197
|
-
" until openFile succeeds or no candidate
|
|
199
|
+
" Recovery on file-not-found: when the server has local",
|
|
200
|
+
" filesystem access, this tool stat-checks the path and",
|
|
201
|
+
" returns an error if it doesn't exist. On that error,",
|
|
202
|
+
" immediately call find (or grep) to locate the file,",
|
|
203
|
+
" then call exec_ui openFile AGAIN using the EXACT path",
|
|
204
|
+
" returned \u2014 don't give up and don't switch to the read",
|
|
205
|
+
" tool. Repeat until openFile succeeds or no candidate",
|
|
206
|
+
" is found.",
|
|
198
207
|
" Example: {kind:'openFile', params:{path:'README.md'}}",
|
|
199
208
|
"",
|
|
200
209
|
" openPanel params: { id: string, component: string,",
|
|
@@ -747,7 +756,9 @@ async function provisionWorkspaceAgentServer(opts) {
|
|
|
747
756
|
async function createWorkspaceAgentServer(opts = {}) {
|
|
748
757
|
const workspaceRoot = opts.workspaceRoot ?? process.cwd();
|
|
749
758
|
const bridge = createInMemoryBridge();
|
|
750
|
-
const
|
|
759
|
+
const resolvedMode = opts.runtimeModeAdapter?.id ?? opts.mode ?? autoDetectMode();
|
|
760
|
+
const workspaceFsCapability = opts.runtimeModeAdapter ? opts.runtimeModeAdapter.workspaceFsCapability ?? "best-effort" : resolveMode(resolvedMode).workspaceFsCapability ?? "best-effort";
|
|
761
|
+
const validateUiPaths = opts.validateUiPaths ?? workspaceFsCapability === "strong";
|
|
751
762
|
const uiTools = createWorkspaceUiTools(bridge, {
|
|
752
763
|
workspaceRoot: validateUiPaths ? workspaceRoot : void 0
|
|
753
764
|
});
|
|
@@ -761,6 +772,7 @@ async function createWorkspaceAgentServer(opts = {}) {
|
|
|
761
772
|
}
|
|
762
773
|
const app = await createAgentApp({
|
|
763
774
|
...opts,
|
|
775
|
+
mode: resolvedMode,
|
|
764
776
|
workspaceRoot,
|
|
765
777
|
extraTools: [
|
|
766
778
|
...opts.extraTools ?? [],
|
|
@@ -768,7 +780,7 @@ async function createWorkspaceAgentServer(opts = {}) {
|
|
|
768
780
|
...pluginCollection.agentOptions.extraTools ?? []
|
|
769
781
|
],
|
|
770
782
|
systemPromptAppend: [
|
|
771
|
-
|
|
783
|
+
workspaceFsCapability === "strong" ? buildWorkspaceContextPrompt() : void 0,
|
|
772
784
|
pluginCollection.agentOptions.systemPromptAppend
|
|
773
785
|
].filter(Boolean).join("\n\n") || void 0,
|
|
774
786
|
resourceLoaderOptions: pluginCollection.agentOptions.resourceLoaderOptions
|
package/dist/server.d.ts
CHANGED
|
@@ -21,9 +21,9 @@ interface ExecUiToolOptions {
|
|
|
21
21
|
* tool stat-checks the resolved path before queueing the UI command and
|
|
22
22
|
* returns an error to the agent if the file is missing or escapes the
|
|
23
23
|
* root — so the model gets immediate feedback instead of the frontend
|
|
24
|
-
* silently no-op'ing on a wrong path. When omitted
|
|
25
|
-
*
|
|
26
|
-
* filesystem
|
|
24
|
+
* silently no-op'ing on a wrong path. When omitted (for example, remote
|
|
25
|
+
* sandbox filesystems the host cannot stat), path syntax is still validated
|
|
26
|
+
* but existence is left to the frontend/remote filesystem.
|
|
27
27
|
*/
|
|
28
28
|
workspaceRoot?: string;
|
|
29
29
|
/**
|
package/dist/server.js
CHANGED
|
@@ -162,7 +162,7 @@ data: ${JSON.stringify({ v: UI_BRIDGE_PROTOCOL_VERSION })}
|
|
|
162
162
|
|
|
163
163
|
// src/server/ui-control/tools/uiTools.ts
|
|
164
164
|
import { access } from "fs/promises";
|
|
165
|
-
import { resolve, isAbsolute, relative } from "path";
|
|
165
|
+
import { resolve, isAbsolute, relative, win32 } from "path";
|
|
166
166
|
function makeError(message) {
|
|
167
167
|
return {
|
|
168
168
|
content: [{ type: "text", text: message }],
|
|
@@ -174,9 +174,15 @@ function getPathParam(kind, params) {
|
|
|
174
174
|
const raw = kind === "navigateToLine" ? params.file : params.path;
|
|
175
175
|
return typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
176
176
|
}
|
|
177
|
+
function isPathAbsolute(filePath) {
|
|
178
|
+
return isAbsolute(filePath) || win32.isAbsolute(filePath);
|
|
179
|
+
}
|
|
180
|
+
function isOutsideWorkspaceRel(rel) {
|
|
181
|
+
return rel === ".." || rel.startsWith("../") || rel.startsWith("..\\") || isPathAbsolute(rel);
|
|
182
|
+
}
|
|
177
183
|
function validatePathSyntax(relPath, workspaceRoot) {
|
|
178
184
|
const rootHint = workspaceRoot ? ` (${workspaceRoot})` : "";
|
|
179
|
-
if (
|
|
185
|
+
if (isPathAbsolute(relPath)) {
|
|
180
186
|
return {
|
|
181
187
|
ok: false,
|
|
182
188
|
reason: `path "${relPath}" is absolute \u2014 pass a path relative to the workspace root${rootHint}.`
|
|
@@ -198,7 +204,7 @@ async function validatePath(workspaceRoot, relPath) {
|
|
|
198
204
|
if (!syntax.ok) return syntax;
|
|
199
205
|
const resolved = resolve(workspaceRoot, relPath);
|
|
200
206
|
const rel = relative(workspaceRoot, resolved);
|
|
201
|
-
if (
|
|
207
|
+
if (isOutsideWorkspaceRel(rel)) {
|
|
202
208
|
return {
|
|
203
209
|
ok: false,
|
|
204
210
|
reason: `path "${relPath}" escapes the workspace root (${workspaceRoot}).`
|
|
@@ -301,13 +307,14 @@ function createExecUiTool(uiBridge, opts = {}) {
|
|
|
301
307
|
" auto-opens if collapsed. Path must be relative to the",
|
|
302
308
|
" workspace root (e.g. `src/foo.ts`, not `foo.ts` if it",
|
|
303
309
|
" lives under src/).",
|
|
304
|
-
" Recovery on file-not-found:
|
|
305
|
-
"
|
|
306
|
-
" exist. On that error,
|
|
307
|
-
" grep) to locate the file,
|
|
308
|
-
" openFile AGAIN using the EXACT path
|
|
309
|
-
" give up and don't switch to the read
|
|
310
|
-
" until openFile succeeds or no candidate
|
|
310
|
+
" Recovery on file-not-found: when the server has local",
|
|
311
|
+
" filesystem access, this tool stat-checks the path and",
|
|
312
|
+
" returns an error if it doesn't exist. On that error,",
|
|
313
|
+
" immediately call find (or grep) to locate the file,",
|
|
314
|
+
" then call exec_ui openFile AGAIN using the EXACT path",
|
|
315
|
+
" returned \u2014 don't give up and don't switch to the read",
|
|
316
|
+
" tool. Repeat until openFile succeeds or no candidate",
|
|
317
|
+
" is found.",
|
|
311
318
|
" Example: {kind:'openFile', params:{path:'README.md'}}",
|
|
312
319
|
"",
|
|
313
320
|
" openPanel params: { id: string, component: string,",
|
package/dist/workspace.css
CHANGED
package/dist/workspace.js
CHANGED
|
@@ -10,7 +10,7 @@ import { EmptyState as Ie, Toolbar as ot, Popover as me, PopoverTrigger as ge, P
|
|
|
10
10
|
import { Toaster as Ma, dismissToast as Da, toast as Ra } from "@hachej/boring-ui-kit";
|
|
11
11
|
import { c as H } from "./utils-B6yFEsav.js";
|
|
12
12
|
import { d as Re } from "./panel-DnvDNQac.js";
|
|
13
|
-
import { C as Fa, T as La, W as za, b as qa } from "./WorkspaceLoadingState-
|
|
13
|
+
import { C as Fa, T as La, W as za, b as qa } from "./WorkspaceLoadingState-BjZGQLS_.js";
|
|
14
14
|
import { C as Ba, c as Aa } from "./CodeEditor-DQqOn4xz.js";
|
|
15
15
|
import { FileTree as Ka } from "./FileTree-BVfqs3rR.js";
|
|
16
16
|
import { MarkdownEditor as ja } from "./MarkdownEditor-CcCDF65H.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hachej/boring-workspace",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
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.",
|
|
@@ -125,8 +125,8 @@
|
|
|
125
125
|
"tailwind-merge": "^2.0.0",
|
|
126
126
|
"zod": "^3.23.0",
|
|
127
127
|
"zustand": "^5.0.0",
|
|
128
|
-
"@hachej/boring-agent": "0.1.
|
|
129
|
-
"@hachej/boring-ui-kit": "0.1.
|
|
128
|
+
"@hachej/boring-agent": "0.1.13",
|
|
129
|
+
"@hachej/boring-ui-kit": "0.1.13"
|
|
130
130
|
},
|
|
131
131
|
"devDependencies": {
|
|
132
132
|
"@tailwindcss/postcss": "^4.0.0",
|