@hachej/boring-workspace 0.1.10 → 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/{CommandPalette-D5KPKtKA.js → CommandPalette-Dme9em28.js} +600 -599
- package/dist/{FileTree-CwC01Ijr.js → FileTree-BVfqs3rR.js} +1 -1
- package/dist/{MarkdownEditor-CB7nfhN9.js → MarkdownEditor-CcCDF65H.js} +1 -1
- package/dist/{WorkspaceLoadingState-J8XVhEyL.js → WorkspaceLoadingState-BjZGQLS_.js} +85 -85
- package/dist/app-front.js +2 -2
- package/dist/app-server.d.ts +3 -3
- package/dist/app-server.js +50 -19
- package/dist/server.d.ts +3 -3
- package/dist/server.js +42 -16
- package/dist/testing.js +1 -1
- package/dist/workspace.css +3 -3
- package/dist/workspace.d.ts +3 -1
- package/dist/workspace.js +718 -692
- package/docs/plans/ASK_USER_QUESTIONS_PLUGIN_SPEC.md +322 -0
- package/package.json +3 -3
|
@@ -2,7 +2,7 @@ import { jsx as i, jsxs as C } from "react/jsx-runtime";
|
|
|
2
2
|
import { useRef as w, useEffect as R, useMemo as P, useCallback as x, createContext as H, useContext as L } from "react";
|
|
3
3
|
import { Tree as q } from "react-arborist";
|
|
4
4
|
import { FolderOpenIcon as z, FolderIcon as B, ChevronRightIcon as K, Loader2Icon as E } from "lucide-react";
|
|
5
|
-
import { K as Y } from "./CommandPalette-
|
|
5
|
+
import { K as Y } from "./CommandPalette-Dme9em28.js";
|
|
6
6
|
import { Input as G } from "@hachej/boring-ui-kit";
|
|
7
7
|
import { c as v } from "./utils-B6yFEsav.js";
|
|
8
8
|
const T = /* @__PURE__ */ new Set(), A = H({
|
|
@@ -15,7 +15,7 @@ import { TableHeader as tt } from "@tiptap/extension-table-header";
|
|
|
15
15
|
import { TableCell as et } from "@tiptap/extension-table-cell";
|
|
16
16
|
import rt from "@tiptap/extension-image";
|
|
17
17
|
import { c as y } from "./utils-B6yFEsav.js";
|
|
18
|
-
import { an as U, ao as it } from "./CommandPalette-
|
|
18
|
+
import { an as U, ao as it } from "./CommandPalette-Dme9em28.js";
|
|
19
19
|
import { uploadFile as nt } from "@hachej/boring-agent/front";
|
|
20
20
|
import at from "@tiptap/extension-code-block-lowlight";
|
|
21
21
|
import { createLowlight as ot, common as lt } from "lowlight";
|
|
@@ -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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
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
|
-
import { aj as ke, q as Ye, ak as Qe, u as Xe, al as Ze } from "./CommandPalette-
|
|
5
|
-
import { T as He, C as qe, r as Ee, w as et, W as $e } from "./WorkspaceLoadingState-
|
|
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-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,16 +63,37 @@ 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
|
}
|
|
64
|
-
|
|
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
|
+
}
|
|
72
|
+
function validatePathSyntax(relPath, workspaceRoot) {
|
|
73
|
+
const rootHint = workspaceRoot ? ` (${workspaceRoot})` : "";
|
|
74
|
+
if (isPathAbsolute(relPath)) {
|
|
66
75
|
return {
|
|
67
76
|
ok: false,
|
|
68
|
-
reason: `path "${relPath}" is absolute \u2014 pass a path relative to the workspace root
|
|
77
|
+
reason: `path "${relPath}" is absolute \u2014 pass a path relative to the workspace root${rootHint}.`
|
|
69
78
|
};
|
|
70
79
|
}
|
|
80
|
+
if (relPath.includes("\0")) {
|
|
81
|
+
return { ok: false, reason: `path "${relPath}" contains a null byte.` };
|
|
82
|
+
}
|
|
83
|
+
if (relPath.split(/[\\/]+/).includes("..")) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
reason: `path "${relPath}" escapes the workspace root${rootHint}.`
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return { ok: true };
|
|
90
|
+
}
|
|
91
|
+
async function validatePath(workspaceRoot, relPath) {
|
|
92
|
+
const syntax = validatePathSyntax(relPath, workspaceRoot);
|
|
93
|
+
if (!syntax.ok) return syntax;
|
|
71
94
|
const resolved = resolve(workspaceRoot, relPath);
|
|
72
95
|
const rel = relative(workspaceRoot, resolved);
|
|
73
|
-
if (
|
|
96
|
+
if (isOutsideWorkspaceRel(rel)) {
|
|
74
97
|
return {
|
|
75
98
|
ok: false,
|
|
76
99
|
reason: `path "${relPath}" escapes the workspace root (${workspaceRoot}).`
|
|
@@ -173,13 +196,14 @@ function createExecUiTool(uiBridge, opts = {}) {
|
|
|
173
196
|
" auto-opens if collapsed. Path must be relative to the",
|
|
174
197
|
" workspace root (e.g. `src/foo.ts`, not `foo.ts` if it",
|
|
175
198
|
" lives under src/).",
|
|
176
|
-
" Recovery on file-not-found:
|
|
177
|
-
"
|
|
178
|
-
" exist. On that error,
|
|
179
|
-
" grep) to locate the file,
|
|
180
|
-
" openFile AGAIN using the EXACT path
|
|
181
|
-
" give up and don't switch to the read
|
|
182
|
-
" 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.",
|
|
183
207
|
" Example: {kind:'openFile', params:{path:'README.md'}}",
|
|
184
208
|
"",
|
|
185
209
|
" openPanel params: { id: string, component: string,",
|
|
@@ -263,16 +287,20 @@ function createExecUiTool(uiBridge, opts = {}) {
|
|
|
263
287
|
return makeError("openSurface: meta must be an object when provided");
|
|
264
288
|
}
|
|
265
289
|
}
|
|
266
|
-
if (
|
|
290
|
+
if (PATH_BEARING_KINDS.has(kind)) {
|
|
267
291
|
const relPath = getPathParam(kind, cmdParams);
|
|
268
292
|
if (!relPath) {
|
|
269
293
|
return makeError(
|
|
270
294
|
`${kind}: ${kind === "navigateToLine" ? "file" : "path"} param is required`
|
|
271
295
|
);
|
|
272
296
|
}
|
|
273
|
-
const
|
|
274
|
-
if (!
|
|
275
|
-
|
|
297
|
+
const syntax = validatePathSyntax(relPath, workspaceRoot);
|
|
298
|
+
if (!syntax.ok) return makeError(syntax.reason);
|
|
299
|
+
if (workspaceRoot) {
|
|
300
|
+
const check = await validatePath(workspaceRoot, relPath);
|
|
301
|
+
if (!check.ok) {
|
|
302
|
+
return makeError(check.reason);
|
|
303
|
+
}
|
|
276
304
|
}
|
|
277
305
|
}
|
|
278
306
|
try {
|
|
@@ -728,7 +756,9 @@ async function provisionWorkspaceAgentServer(opts) {
|
|
|
728
756
|
async function createWorkspaceAgentServer(opts = {}) {
|
|
729
757
|
const workspaceRoot = opts.workspaceRoot ?? process.cwd();
|
|
730
758
|
const bridge = createInMemoryBridge();
|
|
731
|
-
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";
|
|
732
762
|
const uiTools = createWorkspaceUiTools(bridge, {
|
|
733
763
|
workspaceRoot: validateUiPaths ? workspaceRoot : void 0
|
|
734
764
|
});
|
|
@@ -742,6 +772,7 @@ async function createWorkspaceAgentServer(opts = {}) {
|
|
|
742
772
|
}
|
|
743
773
|
const app = await createAgentApp({
|
|
744
774
|
...opts,
|
|
775
|
+
mode: resolvedMode,
|
|
745
776
|
workspaceRoot,
|
|
746
777
|
extraTools: [
|
|
747
778
|
...opts.extraTools ?? [],
|
|
@@ -749,7 +780,7 @@ async function createWorkspaceAgentServer(opts = {}) {
|
|
|
749
780
|
...pluginCollection.agentOptions.extraTools ?? []
|
|
750
781
|
],
|
|
751
782
|
systemPromptAppend: [
|
|
752
|
-
|
|
783
|
+
workspaceFsCapability === "strong" ? buildWorkspaceContextPrompt() : void 0,
|
|
753
784
|
pluginCollection.agentOptions.systemPromptAppend
|
|
754
785
|
].filter(Boolean).join("\n\n") || void 0,
|
|
755
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
|
/**
|