@tangle-network/sandbox-ui 0.95.1 → 0.97.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.
- package/dist/{WorkflowGraph-MPNVC5FE.js → WorkflowGraph-OPLQFAJK.js} +1 -1
- package/dist/chat.d.ts +27 -2
- package/dist/chat.js +2 -2
- package/dist/{chunk-GUULFESL.js → chunk-A4AABEX4.js} +463 -330
- package/dist/{chunk-O7MHUR4U.js → chunk-LHUBJPZR.js} +28 -1
- package/dist/{chunk-FWSBQLFG.js → chunk-WMVUJ5SA.js} +69 -34
- package/dist/dashboard.js +1 -1
- package/dist/globals.css +17 -8
- package/dist/index.js +2 -2
- package/dist/pages.js +1 -1
- package/dist/styles.css +17 -8
- package/dist/workbench.js +1 -1
- package/dist/workflows.js +2 -2
- package/package.json +1 -1
|
@@ -13,11 +13,12 @@ import {
|
|
|
13
13
|
PickerMenuSearch,
|
|
14
14
|
PickerMenuSection,
|
|
15
15
|
PickerMenuTag,
|
|
16
|
+
isTextChatModel,
|
|
16
17
|
pickerMenuBodyClass,
|
|
17
18
|
pickerMenuContentClass,
|
|
18
19
|
pickerMenuItemClass,
|
|
19
20
|
stripBrandPrefix
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-WMVUJ5SA.js";
|
|
21
22
|
import {
|
|
22
23
|
ModelBrandStack,
|
|
23
24
|
canonicalModelId,
|
|
@@ -190,18 +191,38 @@ import {
|
|
|
190
191
|
reasoningEffortsFor
|
|
191
192
|
} from "@tangle-network/agent-interface";
|
|
192
193
|
import * as DropdownMenu2 from "@radix-ui/react-dropdown-menu";
|
|
193
|
-
import { ChevronDown as ChevronDown3,
|
|
194
|
+
import { ChevronDown as ChevronDown3, SlidersHorizontal } from "lucide-react";
|
|
195
|
+
import * as React5 from "react";
|
|
196
|
+
|
|
197
|
+
// src/chat/harness-model-compat.ts
|
|
198
|
+
import {
|
|
199
|
+
harnessSupportsModel,
|
|
200
|
+
snapModelToHarness as snapModelIdToHarness
|
|
201
|
+
} from "@tangle-network/agent-interface";
|
|
202
|
+
import { modelProvider, snapHarnessToModel } from "@tangle-network/agent-interface";
|
|
203
|
+
function isModelCompatibleWithHarness(harness, modelId) {
|
|
204
|
+
return harnessSupportsModel(harness, modelId);
|
|
205
|
+
}
|
|
206
|
+
function snapModelToHarness(harness, modelId, models) {
|
|
207
|
+
return snapModelIdToHarness(harness, modelId, models.map(canonicalModelId));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/chat/informative-lock.tsx
|
|
211
|
+
import { Lock, Plus } from "lucide-react";
|
|
194
212
|
import * as React3 from "react";
|
|
195
213
|
|
|
196
214
|
// src/lib/use-click-outside.ts
|
|
197
215
|
import * as React from "react";
|
|
198
|
-
function useClickOutside(onOutside) {
|
|
216
|
+
function useClickOutside(onOutside, extras) {
|
|
199
217
|
const ref = React.useRef(null);
|
|
218
|
+
const extrasRef = React.useRef(extras);
|
|
219
|
+
extrasRef.current = extras;
|
|
200
220
|
React.useEffect(() => {
|
|
201
221
|
function handler(event) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
222
|
+
const target = event.target;
|
|
223
|
+
if (!ref.current || ref.current.contains(target)) return;
|
|
224
|
+
if (extrasRef.current?.some((extra) => extra.current?.contains(target))) return;
|
|
225
|
+
onOutside();
|
|
205
226
|
}
|
|
206
227
|
document.addEventListener("mousedown", handler);
|
|
207
228
|
return () => document.removeEventListener("mousedown", handler);
|
|
@@ -209,23 +230,178 @@ function useClickOutside(onOutside) {
|
|
|
209
230
|
return ref;
|
|
210
231
|
}
|
|
211
232
|
|
|
212
|
-
// src/chat/
|
|
213
|
-
import
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
233
|
+
// src/chat/anchored-popover.tsx
|
|
234
|
+
import * as React2 from "react";
|
|
235
|
+
import { createPortal } from "react-dom";
|
|
236
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
237
|
+
var AnchoredPopover = React2.forwardRef(
|
|
238
|
+
function AnchoredPopover2({ anchorRef, side, children, className, style, ...rest }, forwardedRef) {
|
|
239
|
+
const innerRef = React2.useRef(null);
|
|
240
|
+
const setRefs = (node) => {
|
|
241
|
+
innerRef.current = node;
|
|
242
|
+
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
243
|
+
else if (forwardedRef) forwardedRef.current = node;
|
|
244
|
+
};
|
|
245
|
+
const [position, setPosition] = React2.useState(null);
|
|
246
|
+
const place = React2.useCallback(() => {
|
|
247
|
+
const anchor = anchorRef.current;
|
|
248
|
+
if (!anchor) return;
|
|
249
|
+
const rect = anchor.getBoundingClientRect();
|
|
250
|
+
const width = innerRef.current?.offsetWidth ?? 0;
|
|
251
|
+
const margin = 8;
|
|
252
|
+
const left = Math.max(
|
|
253
|
+
margin,
|
|
254
|
+
Math.min(rect.left, window.innerWidth - width - margin)
|
|
255
|
+
);
|
|
256
|
+
setPosition(
|
|
257
|
+
side === "top" ? { left, bottom: window.innerHeight - rect.top + margin } : { left, top: rect.bottom + margin }
|
|
258
|
+
);
|
|
259
|
+
}, [anchorRef, side]);
|
|
260
|
+
React2.useLayoutEffect(() => {
|
|
261
|
+
place();
|
|
262
|
+
window.addEventListener("resize", place);
|
|
263
|
+
window.addEventListener("scroll", place, true);
|
|
264
|
+
return () => {
|
|
265
|
+
window.removeEventListener("resize", place);
|
|
266
|
+
window.removeEventListener("scroll", place, true);
|
|
267
|
+
};
|
|
268
|
+
}, [place]);
|
|
269
|
+
return createPortal(
|
|
270
|
+
/* @__PURE__ */ jsx2(
|
|
271
|
+
"div",
|
|
272
|
+
{
|
|
273
|
+
...rest,
|
|
274
|
+
ref: setRefs,
|
|
275
|
+
className: cn("fixed z-50", className),
|
|
276
|
+
style: {
|
|
277
|
+
...style,
|
|
278
|
+
pointerEvents: "auto",
|
|
279
|
+
...position ?? { visibility: "hidden", left: 0, top: 0 }
|
|
280
|
+
},
|
|
281
|
+
children
|
|
282
|
+
}
|
|
283
|
+
),
|
|
284
|
+
document.body
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
// src/chat/informative-lock.tsx
|
|
290
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
291
|
+
function InformativeLock({
|
|
292
|
+
children,
|
|
293
|
+
ariaLabel,
|
|
294
|
+
lockTitle,
|
|
295
|
+
lockBody,
|
|
296
|
+
newChatLabel,
|
|
297
|
+
onNewChat,
|
|
298
|
+
className,
|
|
299
|
+
triggerClassName,
|
|
300
|
+
popoverClassName,
|
|
301
|
+
side = "top"
|
|
302
|
+
}) {
|
|
303
|
+
const [open, setOpen] = React3.useState(false);
|
|
304
|
+
const closeTimer = React3.useRef(null);
|
|
305
|
+
const popoverRef = React3.useRef(null);
|
|
306
|
+
const ref = useClickOutside(() => setOpen(false), [popoverRef]);
|
|
307
|
+
const cancelClose = React3.useCallback(() => {
|
|
308
|
+
if (closeTimer.current) {
|
|
309
|
+
clearTimeout(closeTimer.current);
|
|
310
|
+
closeTimer.current = null;
|
|
311
|
+
}
|
|
312
|
+
}, []);
|
|
313
|
+
const scheduleClose = React3.useCallback(() => {
|
|
314
|
+
cancelClose();
|
|
315
|
+
closeTimer.current = setTimeout(() => setOpen(false), 150);
|
|
316
|
+
}, [cancelClose]);
|
|
317
|
+
React3.useEffect(() => cancelClose, [cancelClose]);
|
|
318
|
+
return /* @__PURE__ */ jsxs2(
|
|
319
|
+
"div",
|
|
320
|
+
{
|
|
321
|
+
ref,
|
|
322
|
+
className: cn("relative inline-flex", className),
|
|
323
|
+
onMouseEnter: () => {
|
|
324
|
+
cancelClose();
|
|
325
|
+
setOpen(true);
|
|
326
|
+
},
|
|
327
|
+
onMouseLeave: scheduleClose,
|
|
328
|
+
onKeyDown: (event) => {
|
|
329
|
+
if (event.key === "Escape") setOpen(false);
|
|
330
|
+
},
|
|
331
|
+
children: [
|
|
332
|
+
/* @__PURE__ */ jsx3(
|
|
333
|
+
"button",
|
|
334
|
+
{
|
|
335
|
+
type: "button",
|
|
336
|
+
onClick: () => setOpen(true),
|
|
337
|
+
"data-state": open ? "open" : "closed",
|
|
338
|
+
"aria-label": ariaLabel,
|
|
339
|
+
"aria-haspopup": "dialog",
|
|
340
|
+
"aria-expanded": open,
|
|
341
|
+
className: cn(
|
|
342
|
+
"inline-flex h-8 items-center gap-1.5 rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container px-2.5 opacity-60",
|
|
343
|
+
"text-xs font-medium text-foreground shadow-sm transition-colors",
|
|
344
|
+
"hover:border-[var(--md3-outline-variant)] hover:bg-surface-container-high focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
345
|
+
"data-[state=open]:border-[var(--md3-outline-variant)] data-[state=open]:bg-surface-container-high",
|
|
346
|
+
triggerClassName
|
|
347
|
+
),
|
|
348
|
+
children
|
|
349
|
+
}
|
|
350
|
+
),
|
|
351
|
+
open && /* @__PURE__ */ jsxs2(
|
|
352
|
+
AnchoredPopover,
|
|
353
|
+
{
|
|
354
|
+
ref: popoverRef,
|
|
355
|
+
anchorRef: ref,
|
|
356
|
+
side,
|
|
357
|
+
role: "dialog",
|
|
358
|
+
onMouseEnter: () => {
|
|
359
|
+
cancelClose();
|
|
360
|
+
setOpen(true);
|
|
361
|
+
},
|
|
362
|
+
onMouseLeave: scheduleClose,
|
|
363
|
+
className: cn(
|
|
364
|
+
"w-72 rounded-[var(--radius-md)] border border-[var(--md3-outline-variant)] bg-surface-container-highest p-3",
|
|
365
|
+
"shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]",
|
|
366
|
+
popoverClassName
|
|
367
|
+
),
|
|
368
|
+
children: [
|
|
369
|
+
/* @__PURE__ */ jsxs2("p", { className: "flex items-start gap-2 text-sm font-medium text-foreground", children: [
|
|
370
|
+
/* @__PURE__ */ jsx3(Lock, { className: "mt-0.5 h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
371
|
+
/* @__PURE__ */ jsx3("span", { children: lockTitle })
|
|
372
|
+
] }),
|
|
373
|
+
/* @__PURE__ */ jsx3("p", { className: "mt-1.5 text-xs text-muted-foreground", children: lockBody }),
|
|
374
|
+
/* @__PURE__ */ jsxs2(
|
|
375
|
+
"button",
|
|
376
|
+
{
|
|
377
|
+
type: "button",
|
|
378
|
+
onClick: () => {
|
|
379
|
+
setOpen(false);
|
|
380
|
+
onNewChat();
|
|
381
|
+
},
|
|
382
|
+
className: cn(
|
|
383
|
+
"mt-3 flex w-full items-center justify-center gap-1.5 rounded-md px-2.5 py-2 text-sm font-medium text-foreground",
|
|
384
|
+
"bg-primary/10 ring-1 ring-inset ring-primary/25 transition-colors",
|
|
385
|
+
"hover:bg-primary/15 focus:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
386
|
+
),
|
|
387
|
+
children: [
|
|
388
|
+
/* @__PURE__ */ jsx3(Plus, { className: "h-4 w-4" }),
|
|
389
|
+
newChatLabel
|
|
390
|
+
]
|
|
391
|
+
}
|
|
392
|
+
)
|
|
393
|
+
]
|
|
394
|
+
}
|
|
395
|
+
)
|
|
396
|
+
]
|
|
397
|
+
}
|
|
398
|
+
);
|
|
223
399
|
}
|
|
224
400
|
|
|
225
401
|
// src/chat/agent-profile-picker.tsx
|
|
226
|
-
import { Bot, Check, ChevronDown as ChevronDown2, Pencil, Plus, Trash2 } from "lucide-react";
|
|
227
|
-
import * as
|
|
228
|
-
import { jsx as
|
|
402
|
+
import { Bot, Check, ChevronDown as ChevronDown2, Pencil, Plus as Plus2, Trash2 } from "lucide-react";
|
|
403
|
+
import * as React4 from "react";
|
|
404
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
229
405
|
function profileSubtitle(profile) {
|
|
230
406
|
if (profile.description) return profile.description;
|
|
231
407
|
const count = profile.capabilities?.length ?? 0;
|
|
@@ -240,21 +416,33 @@ function AgentProfilePicker({
|
|
|
240
416
|
onUpdate,
|
|
241
417
|
onDelete,
|
|
242
418
|
disabled,
|
|
419
|
+
locked,
|
|
420
|
+
lockReason,
|
|
421
|
+
onNewChat,
|
|
243
422
|
className,
|
|
423
|
+
triggerClassName,
|
|
424
|
+
popoverClassName,
|
|
244
425
|
side = "top"
|
|
245
426
|
}) {
|
|
246
|
-
const [open, setOpen] =
|
|
247
|
-
const [composing, setComposing] =
|
|
427
|
+
const [open, setOpen] = React4.useState(false);
|
|
428
|
+
const [composing, setComposing] = React4.useState(
|
|
248
429
|
null
|
|
249
430
|
);
|
|
431
|
+
const popoverRef = React4.useRef(null);
|
|
250
432
|
const ref = useClickOutside(() => {
|
|
251
433
|
setOpen(false);
|
|
252
434
|
setComposing(null);
|
|
253
|
-
});
|
|
435
|
+
}, [popoverRef]);
|
|
254
436
|
const canAuthor = Boolean(capabilities && (onCreate || onUpdate));
|
|
255
437
|
const builtins = profiles.filter((profile) => profile.builtin);
|
|
256
438
|
const custom = profiles.filter((profile) => !profile.builtin);
|
|
257
439
|
const selected = profiles.find((profile) => profile.id === value);
|
|
440
|
+
const selectedName = selected?.name ?? value;
|
|
441
|
+
React4.useEffect(() => {
|
|
442
|
+
if (!locked) return;
|
|
443
|
+
setOpen(false);
|
|
444
|
+
setComposing(null);
|
|
445
|
+
}, [locked]);
|
|
258
446
|
function select(id) {
|
|
259
447
|
onChange(id);
|
|
260
448
|
setOpen(false);
|
|
@@ -264,38 +452,64 @@ function AgentProfilePicker({
|
|
|
264
452
|
else await onCreate?.(draft);
|
|
265
453
|
setComposing(null);
|
|
266
454
|
}
|
|
267
|
-
|
|
268
|
-
/* @__PURE__ */
|
|
455
|
+
if (locked && onNewChat) {
|
|
456
|
+
return /* @__PURE__ */ jsxs3(
|
|
457
|
+
InformativeLock,
|
|
458
|
+
{
|
|
459
|
+
ariaLabel: "Agent profile (locked)",
|
|
460
|
+
lockTitle: `Profile fixed to ${selectedName} for this conversation.`,
|
|
461
|
+
lockBody: "Conversations stay on one profile.",
|
|
462
|
+
newChatLabel: "New chat to switch profile",
|
|
463
|
+
onNewChat,
|
|
464
|
+
className,
|
|
465
|
+
triggerClassName,
|
|
466
|
+
popoverClassName,
|
|
467
|
+
side,
|
|
468
|
+
children: [
|
|
469
|
+
/* @__PURE__ */ jsx4(Bot, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
470
|
+
/* @__PURE__ */ jsx4("span", { className: "max-w-[140px] truncate", children: selectedName })
|
|
471
|
+
]
|
|
472
|
+
}
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
return /* @__PURE__ */ jsxs3("div", { ref, className: cn("relative inline-flex", className), children: [
|
|
476
|
+
/* @__PURE__ */ jsxs3(
|
|
269
477
|
"button",
|
|
270
478
|
{
|
|
271
479
|
type: "button",
|
|
272
|
-
disabled,
|
|
480
|
+
disabled: disabled || locked,
|
|
481
|
+
title: locked ? lockReason : void 0,
|
|
273
482
|
onClick: () => setOpen((v) => !v),
|
|
274
483
|
className: cn(
|
|
275
484
|
"inline-flex h-8 items-center gap-1.5 rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container px-2.5",
|
|
276
485
|
"text-xs font-medium text-foreground shadow-sm transition-colors",
|
|
277
486
|
"hover:border-[var(--md3-outline-variant)] hover:bg-surface-container-high focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
278
487
|
"data-[state=open]:border-[var(--md3-outline-variant)] data-[state=open]:bg-surface-container-high",
|
|
279
|
-
"disabled:cursor-not-allowed disabled:opacity-60"
|
|
488
|
+
"disabled:cursor-not-allowed disabled:opacity-60",
|
|
489
|
+
triggerClassName
|
|
280
490
|
),
|
|
281
491
|
"data-state": open ? "open" : "closed",
|
|
282
492
|
"aria-label": "Agent profile",
|
|
283
493
|
children: [
|
|
284
|
-
/* @__PURE__ */
|
|
285
|
-
/* @__PURE__ */
|
|
286
|
-
/* @__PURE__ */
|
|
494
|
+
/* @__PURE__ */ jsx4(Bot, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
495
|
+
/* @__PURE__ */ jsx4("span", { className: "max-w-[140px] truncate", children: selectedName }),
|
|
496
|
+
!locked && /* @__PURE__ */ jsx4(ChevronDown2, { className: "ml-auto h-3.5 w-3.5 shrink-0 text-muted-foreground" })
|
|
287
497
|
]
|
|
288
498
|
}
|
|
289
499
|
),
|
|
290
|
-
open && /* @__PURE__ */
|
|
291
|
-
|
|
500
|
+
open && !locked && /* @__PURE__ */ jsx4(
|
|
501
|
+
AnchoredPopover,
|
|
292
502
|
{
|
|
503
|
+
ref: popoverRef,
|
|
504
|
+
anchorRef: ref,
|
|
505
|
+
side,
|
|
293
506
|
className: cn(
|
|
294
|
-
"
|
|
507
|
+
"w-[min(320px,calc(100vw-2rem))] overflow-hidden rounded-[var(--radius-md)] border border-[var(--md3-outline-variant)] bg-surface-container-highest p-1",
|
|
295
508
|
"shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]",
|
|
296
|
-
|
|
509
|
+
popoverClassName
|
|
297
510
|
),
|
|
298
|
-
|
|
511
|
+
"data-testid": "agent-profile-popover",
|
|
512
|
+
children: composing ? /* @__PURE__ */ jsx4(
|
|
299
513
|
ProfileForm,
|
|
300
514
|
{
|
|
301
515
|
capabilities: capabilities ?? [],
|
|
@@ -303,9 +517,9 @@ function AgentProfilePicker({
|
|
|
303
517
|
onCancel: () => setComposing(null),
|
|
304
518
|
onSave: save
|
|
305
519
|
}
|
|
306
|
-
) : /* @__PURE__ */
|
|
307
|
-
/* @__PURE__ */
|
|
308
|
-
builtins.map((profile) => /* @__PURE__ */
|
|
520
|
+
) : /* @__PURE__ */ jsxs3("div", { className: "max-h-[min(60vh,420px)] overflow-y-auto", children: [
|
|
521
|
+
/* @__PURE__ */ jsx4(SectionHeader, { children: "Modes" }),
|
|
522
|
+
builtins.map((profile) => /* @__PURE__ */ jsx4(
|
|
309
523
|
ProfileRow,
|
|
310
524
|
{
|
|
311
525
|
active: profile.id === value,
|
|
@@ -315,8 +529,8 @@ function AgentProfilePicker({
|
|
|
315
529
|
},
|
|
316
530
|
profile.id
|
|
317
531
|
)),
|
|
318
|
-
custom.length > 0 && /* @__PURE__ */
|
|
319
|
-
custom.map((profile) => /* @__PURE__ */
|
|
532
|
+
custom.length > 0 && /* @__PURE__ */ jsx4(SectionHeader, { children: "Your agents" }),
|
|
533
|
+
custom.map((profile) => /* @__PURE__ */ jsx4(
|
|
320
534
|
ProfileRow,
|
|
321
535
|
{
|
|
322
536
|
active: profile.id === value,
|
|
@@ -328,14 +542,14 @@ function AgentProfilePicker({
|
|
|
328
542
|
},
|
|
329
543
|
profile.id
|
|
330
544
|
)),
|
|
331
|
-
canAuthor && /* @__PURE__ */
|
|
545
|
+
canAuthor && /* @__PURE__ */ jsxs3(
|
|
332
546
|
"button",
|
|
333
547
|
{
|
|
334
548
|
type: "button",
|
|
335
549
|
onClick: () => setComposing("new"),
|
|
336
550
|
className: "mt-1 flex w-full items-center gap-2 rounded-md px-2.5 py-2 text-left text-sm text-[var(--accent-text)] transition-colors hover:bg-accent/40",
|
|
337
551
|
children: [
|
|
338
|
-
/* @__PURE__ */
|
|
552
|
+
/* @__PURE__ */ jsx4(Plus2, { className: "h-4 w-4" }),
|
|
339
553
|
" New agent\u2026"
|
|
340
554
|
]
|
|
341
555
|
}
|
|
@@ -346,7 +560,7 @@ function AgentProfilePicker({
|
|
|
346
560
|
] });
|
|
347
561
|
}
|
|
348
562
|
function SectionHeader({ children }) {
|
|
349
|
-
return /* @__PURE__ */
|
|
563
|
+
return /* @__PURE__ */ jsx4("div", { className: "px-2.5 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/70", children });
|
|
350
564
|
}
|
|
351
565
|
function ProfileRow({
|
|
352
566
|
active,
|
|
@@ -356,7 +570,7 @@ function ProfileRow({
|
|
|
356
570
|
onEdit,
|
|
357
571
|
onDelete
|
|
358
572
|
}) {
|
|
359
|
-
return /* @__PURE__ */
|
|
573
|
+
return /* @__PURE__ */ jsxs3(
|
|
360
574
|
"div",
|
|
361
575
|
{
|
|
362
576
|
className: cn(
|
|
@@ -364,40 +578,40 @@ function ProfileRow({
|
|
|
364
578
|
active ? "bg-[var(--accent-surface-soft)] text-[var(--accent-text)]" : "hover:bg-accent/40"
|
|
365
579
|
),
|
|
366
580
|
children: [
|
|
367
|
-
/* @__PURE__ */
|
|
581
|
+
/* @__PURE__ */ jsxs3(
|
|
368
582
|
"button",
|
|
369
583
|
{
|
|
370
584
|
type: "button",
|
|
371
585
|
onClick: onSelect,
|
|
372
586
|
className: "flex min-w-0 flex-1 items-center gap-2 text-left",
|
|
373
587
|
children: [
|
|
374
|
-
/* @__PURE__ */
|
|
375
|
-
/* @__PURE__ */
|
|
376
|
-
/* @__PURE__ */
|
|
377
|
-
/* @__PURE__ */
|
|
588
|
+
/* @__PURE__ */ jsx4("span", { className: "flex h-4 w-4 shrink-0 items-center justify-center", children: active && /* @__PURE__ */ jsx4(Check, { className: "h-3.5 w-3.5" }) }),
|
|
589
|
+
/* @__PURE__ */ jsxs3("span", { className: "min-w-0", children: [
|
|
590
|
+
/* @__PURE__ */ jsx4("span", { className: "block truncate font-medium", children: title }),
|
|
591
|
+
/* @__PURE__ */ jsx4("span", { className: "block truncate text-xs text-muted-foreground", children: subtitle })
|
|
378
592
|
] })
|
|
379
593
|
]
|
|
380
594
|
}
|
|
381
595
|
),
|
|
382
|
-
(onEdit || onDelete) && /* @__PURE__ */
|
|
383
|
-
onEdit && /* @__PURE__ */
|
|
596
|
+
(onEdit || onDelete) && /* @__PURE__ */ jsxs3("span", { className: "flex shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100", children: [
|
|
597
|
+
onEdit && /* @__PURE__ */ jsx4(
|
|
384
598
|
"button",
|
|
385
599
|
{
|
|
386
600
|
type: "button",
|
|
387
601
|
onClick: onEdit,
|
|
388
602
|
title: "Edit",
|
|
389
603
|
className: "rounded p-1 text-muted-foreground hover:text-foreground",
|
|
390
|
-
children: /* @__PURE__ */
|
|
604
|
+
children: /* @__PURE__ */ jsx4(Pencil, { className: "h-3 w-3" })
|
|
391
605
|
}
|
|
392
606
|
),
|
|
393
|
-
onDelete && /* @__PURE__ */
|
|
607
|
+
onDelete && /* @__PURE__ */ jsx4(
|
|
394
608
|
"button",
|
|
395
609
|
{
|
|
396
610
|
type: "button",
|
|
397
611
|
onClick: onDelete,
|
|
398
612
|
title: "Delete",
|
|
399
613
|
className: "rounded p-1 text-muted-foreground hover:text-[var(--status-error,#ff4d6d)]",
|
|
400
|
-
children: /* @__PURE__ */
|
|
614
|
+
children: /* @__PURE__ */ jsx4(Trash2, { className: "h-3 w-3" })
|
|
401
615
|
}
|
|
402
616
|
)
|
|
403
617
|
] })
|
|
@@ -411,16 +625,16 @@ function ProfileForm({
|
|
|
411
625
|
onCancel,
|
|
412
626
|
onSave
|
|
413
627
|
}) {
|
|
414
|
-
const [name, setName] =
|
|
415
|
-
const [caps, setCaps] =
|
|
628
|
+
const [name, setName] = React4.useState(initial?.name ?? "");
|
|
629
|
+
const [caps, setCaps] = React4.useState(
|
|
416
630
|
initial?.capabilities ? [...initial.capabilities] : capabilities.map((c) => c.id)
|
|
417
631
|
);
|
|
418
|
-
const [instructions, setInstructions] =
|
|
632
|
+
const [instructions, setInstructions] = React4.useState(initial?.instructions ?? "");
|
|
419
633
|
const toggle = (id) => setCaps(
|
|
420
634
|
(prev) => prev.includes(id) ? prev.filter((c) => c !== id) : [...prev, id]
|
|
421
635
|
);
|
|
422
|
-
return /* @__PURE__ */
|
|
423
|
-
/* @__PURE__ */
|
|
636
|
+
return /* @__PURE__ */ jsxs3("div", { className: "space-y-3 p-2.5", children: [
|
|
637
|
+
/* @__PURE__ */ jsx4(
|
|
424
638
|
"input",
|
|
425
639
|
{
|
|
426
640
|
autoFocus: true,
|
|
@@ -430,14 +644,14 @@ function ProfileForm({
|
|
|
430
644
|
className: "w-full rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container px-3 py-2 text-sm outline-none focus:border-primary"
|
|
431
645
|
}
|
|
432
646
|
),
|
|
433
|
-
capabilities.length > 0 && /* @__PURE__ */
|
|
434
|
-
/* @__PURE__ */
|
|
435
|
-
/* @__PURE__ */
|
|
647
|
+
capabilities.length > 0 && /* @__PURE__ */ jsxs3("div", { children: [
|
|
648
|
+
/* @__PURE__ */ jsx4("p", { className: "mb-1.5 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/70", children: "Tools" }),
|
|
649
|
+
/* @__PURE__ */ jsx4("div", { className: "space-y-0.5", children: capabilities.map((cap) => /* @__PURE__ */ jsxs3(
|
|
436
650
|
"label",
|
|
437
651
|
{
|
|
438
652
|
className: "flex cursor-pointer items-start gap-2 rounded-md px-2 py-1.5 hover:bg-accent/40",
|
|
439
653
|
children: [
|
|
440
|
-
/* @__PURE__ */
|
|
654
|
+
/* @__PURE__ */ jsx4(
|
|
441
655
|
"input",
|
|
442
656
|
{
|
|
443
657
|
type: "checkbox",
|
|
@@ -446,16 +660,16 @@ function ProfileForm({
|
|
|
446
660
|
className: "mt-0.5"
|
|
447
661
|
}
|
|
448
662
|
),
|
|
449
|
-
/* @__PURE__ */
|
|
450
|
-
/* @__PURE__ */
|
|
451
|
-
cap.description && /* @__PURE__ */
|
|
663
|
+
/* @__PURE__ */ jsxs3("span", { className: "min-w-0", children: [
|
|
664
|
+
/* @__PURE__ */ jsx4("span", { className: "block text-sm font-medium", children: cap.label }),
|
|
665
|
+
cap.description && /* @__PURE__ */ jsx4("span", { className: "block text-xs text-muted-foreground", children: cap.description })
|
|
452
666
|
] })
|
|
453
667
|
]
|
|
454
668
|
},
|
|
455
669
|
cap.id
|
|
456
670
|
)) })
|
|
457
671
|
] }),
|
|
458
|
-
/* @__PURE__ */
|
|
672
|
+
/* @__PURE__ */ jsx4(
|
|
459
673
|
"textarea",
|
|
460
674
|
{
|
|
461
675
|
value: instructions,
|
|
@@ -465,8 +679,8 @@ function ProfileForm({
|
|
|
465
679
|
className: "w-full resize-none rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container px-3 py-2 text-sm outline-none focus:border-primary"
|
|
466
680
|
}
|
|
467
681
|
),
|
|
468
|
-
/* @__PURE__ */
|
|
469
|
-
/* @__PURE__ */
|
|
682
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex justify-end gap-2", children: [
|
|
683
|
+
/* @__PURE__ */ jsx4(
|
|
470
684
|
"button",
|
|
471
685
|
{
|
|
472
686
|
type: "button",
|
|
@@ -475,7 +689,7 @@ function ProfileForm({
|
|
|
475
689
|
children: "Cancel"
|
|
476
690
|
}
|
|
477
691
|
),
|
|
478
|
-
/* @__PURE__ */
|
|
692
|
+
/* @__PURE__ */ jsx4(
|
|
479
693
|
"button",
|
|
480
694
|
{
|
|
481
695
|
type: "button",
|
|
@@ -495,7 +709,7 @@ function ProfileForm({
|
|
|
495
709
|
}
|
|
496
710
|
|
|
497
711
|
// src/chat/agent-session-controls.tsx
|
|
498
|
-
import { Fragment as Fragment2, jsx as
|
|
712
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
499
713
|
function harnessAutonomyNote(harness) {
|
|
500
714
|
const ownModel = !harnessHonorsModel(harness);
|
|
501
715
|
const ownEffort = !harnessHonorsEffort(harness);
|
|
@@ -519,106 +733,6 @@ function harnessGroup(option) {
|
|
|
519
733
|
return harnessAutonomyNote(option.type) === null ? "steerable" : "fixed";
|
|
520
734
|
}
|
|
521
735
|
var HARNESS_SEARCH_THRESHOLD = 7;
|
|
522
|
-
function InformativeLock({
|
|
523
|
-
type,
|
|
524
|
-
label,
|
|
525
|
-
lockTitle,
|
|
526
|
-
lockBody,
|
|
527
|
-
newChatLabel,
|
|
528
|
-
onNewChat
|
|
529
|
-
}) {
|
|
530
|
-
const [open, setOpen] = React3.useState(false);
|
|
531
|
-
const closeTimer = React3.useRef(null);
|
|
532
|
-
const ref = useClickOutside(() => setOpen(false));
|
|
533
|
-
const cancelClose = React3.useCallback(() => {
|
|
534
|
-
if (closeTimer.current) {
|
|
535
|
-
clearTimeout(closeTimer.current);
|
|
536
|
-
closeTimer.current = null;
|
|
537
|
-
}
|
|
538
|
-
}, []);
|
|
539
|
-
const scheduleClose = React3.useCallback(() => {
|
|
540
|
-
cancelClose();
|
|
541
|
-
closeTimer.current = setTimeout(() => setOpen(false), 150);
|
|
542
|
-
}, [cancelClose]);
|
|
543
|
-
React3.useEffect(() => cancelClose, [cancelClose]);
|
|
544
|
-
return /* @__PURE__ */ jsxs3(
|
|
545
|
-
"div",
|
|
546
|
-
{
|
|
547
|
-
ref,
|
|
548
|
-
className: "relative inline-flex",
|
|
549
|
-
onMouseEnter: () => {
|
|
550
|
-
cancelClose();
|
|
551
|
-
setOpen(true);
|
|
552
|
-
},
|
|
553
|
-
onMouseLeave: scheduleClose,
|
|
554
|
-
onKeyDown: (event) => {
|
|
555
|
-
if (event.key === "Escape") setOpen(false);
|
|
556
|
-
},
|
|
557
|
-
children: [
|
|
558
|
-
/* @__PURE__ */ jsxs3(
|
|
559
|
-
"button",
|
|
560
|
-
{
|
|
561
|
-
type: "button",
|
|
562
|
-
onClick: () => setOpen(true),
|
|
563
|
-
"data-state": open ? "open" : "closed",
|
|
564
|
-
"aria-label": "Agent harness (locked)",
|
|
565
|
-
"aria-haspopup": "dialog",
|
|
566
|
-
"aria-expanded": open,
|
|
567
|
-
className: cn(
|
|
568
|
-
// Dimmed to read as locked (the harness is bound to this session),
|
|
569
|
-
// matching the disabled model picker — the logo stays so the chip is
|
|
570
|
-
// still recognizably this harness; the popover explains the lock.
|
|
571
|
-
"inline-flex h-8 items-center gap-1.5 rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container px-2.5 opacity-60",
|
|
572
|
-
"text-xs font-medium text-foreground shadow-sm transition-colors",
|
|
573
|
-
"hover:border-[var(--md3-outline-variant)] hover:bg-surface-container-high focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
574
|
-
"data-[state=open]:border-[var(--md3-outline-variant)] data-[state=open]:bg-surface-container-high"
|
|
575
|
-
),
|
|
576
|
-
children: [
|
|
577
|
-
/* @__PURE__ */ jsx3(HarnessLogo, { type, size: 16 }),
|
|
578
|
-
/* @__PURE__ */ jsx3("span", { children: label })
|
|
579
|
-
]
|
|
580
|
-
}
|
|
581
|
-
),
|
|
582
|
-
open && /* @__PURE__ */ jsxs3(
|
|
583
|
-
"div",
|
|
584
|
-
{
|
|
585
|
-
role: "dialog",
|
|
586
|
-
className: cn(
|
|
587
|
-
"absolute bottom-full left-0 z-50 mb-2 w-72 rounded-[var(--radius-md)] border border-[var(--md3-outline-variant)] bg-surface-container-highest p-3",
|
|
588
|
-
"shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]"
|
|
589
|
-
),
|
|
590
|
-
children: [
|
|
591
|
-
/* @__PURE__ */ jsxs3("p", { className: "flex items-start gap-2 text-sm font-medium text-foreground", children: [
|
|
592
|
-
/* @__PURE__ */ jsx3(Lock, { className: "mt-0.5 h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
593
|
-
/* @__PURE__ */ jsx3("span", { children: lockTitle ?? `Agent fixed to ${label} for this conversation.` })
|
|
594
|
-
] }),
|
|
595
|
-
/* @__PURE__ */ jsx3("p", { className: "mt-1.5 text-xs text-muted-foreground", children: lockBody ?? "Conversations stay on one agent." }),
|
|
596
|
-
/* @__PURE__ */ jsxs3(
|
|
597
|
-
"button",
|
|
598
|
-
{
|
|
599
|
-
type: "button",
|
|
600
|
-
onClick: () => {
|
|
601
|
-
setOpen(false);
|
|
602
|
-
onNewChat();
|
|
603
|
-
},
|
|
604
|
-
className: cn(
|
|
605
|
-
"mt-3 flex w-full items-center justify-center gap-1.5 rounded-md px-2.5 py-2 text-sm font-medium text-foreground",
|
|
606
|
-
"bg-primary/10 ring-1 ring-inset ring-primary/25 transition-colors",
|
|
607
|
-
"hover:bg-primary/15 focus:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
608
|
-
),
|
|
609
|
-
children: [
|
|
610
|
-
/* @__PURE__ */ jsx3(Plus2, { className: "h-4 w-4" }),
|
|
611
|
-
newChatLabel ?? "New chat to switch agent"
|
|
612
|
-
]
|
|
613
|
-
}
|
|
614
|
-
)
|
|
615
|
-
]
|
|
616
|
-
}
|
|
617
|
-
)
|
|
618
|
-
]
|
|
619
|
-
}
|
|
620
|
-
);
|
|
621
|
-
}
|
|
622
736
|
function HarnessDropdown({
|
|
623
737
|
value,
|
|
624
738
|
onChange,
|
|
@@ -640,16 +754,16 @@ function HarnessDropdown({
|
|
|
640
754
|
);
|
|
641
755
|
const options = HARNESS_OPTIONS.filter((h) => allowed.has(h.type));
|
|
642
756
|
const selected = options.find((option) => option.type === value);
|
|
643
|
-
const [query, setQuery] =
|
|
757
|
+
const [query, setQuery] = React5.useState("");
|
|
644
758
|
const showSearch = options.length > HARNESS_SEARCH_THRESHOLD;
|
|
645
|
-
const filtered =
|
|
759
|
+
const filtered = React5.useMemo(() => {
|
|
646
760
|
const q = query.trim().toLowerCase();
|
|
647
761
|
if (!q) return options;
|
|
648
762
|
return options.filter(
|
|
649
763
|
(o) => o.label.toLowerCase().includes(q) || o.type.toLowerCase().includes(q) || (o.description?.toLowerCase() ?? "").includes(q)
|
|
650
764
|
);
|
|
651
765
|
}, [options, query]);
|
|
652
|
-
const sections =
|
|
766
|
+
const sections = React5.useMemo(() => {
|
|
653
767
|
const byGroup = /* @__PURE__ */ new Map();
|
|
654
768
|
for (const option of filtered) {
|
|
655
769
|
const key = harnessGroup(option);
|
|
@@ -664,26 +778,31 @@ function HarnessDropdown({
|
|
|
664
778
|
})).filter((section) => section.items.length > 0);
|
|
665
779
|
}, [filtered]);
|
|
666
780
|
if (locked && onNewChat) {
|
|
667
|
-
|
|
781
|
+
const label = selected?.label ?? value;
|
|
782
|
+
return /* @__PURE__ */ jsxs4(
|
|
668
783
|
InformativeLock,
|
|
669
784
|
{
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
785
|
+
ariaLabel: "Agent harness (locked)",
|
|
786
|
+
lockTitle: lockTitle ?? `Agent fixed to ${label} for this conversation.`,
|
|
787
|
+
lockBody: lockBody ?? "Conversations stay on one agent.",
|
|
788
|
+
newChatLabel: newChatLabel ?? "New chat to switch agent",
|
|
789
|
+
onNewChat,
|
|
790
|
+
triggerClassName,
|
|
791
|
+
children: [
|
|
792
|
+
/* @__PURE__ */ jsx5(HarnessLogo, { type: value, size: 16 }),
|
|
793
|
+
/* @__PURE__ */ jsx5("span", { children: label })
|
|
794
|
+
]
|
|
676
795
|
}
|
|
677
796
|
);
|
|
678
797
|
}
|
|
679
|
-
return /* @__PURE__ */
|
|
798
|
+
return /* @__PURE__ */ jsxs4(
|
|
680
799
|
DropdownMenu2.Root,
|
|
681
800
|
{
|
|
682
801
|
onOpenChange: (nextOpen) => {
|
|
683
802
|
if (!nextOpen) setQuery("");
|
|
684
803
|
},
|
|
685
804
|
children: [
|
|
686
|
-
/* @__PURE__ */
|
|
805
|
+
/* @__PURE__ */ jsx5(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs4(
|
|
687
806
|
"button",
|
|
688
807
|
{
|
|
689
808
|
type: "button",
|
|
@@ -699,13 +818,13 @@ function HarnessDropdown({
|
|
|
699
818
|
),
|
|
700
819
|
"aria-label": "Agent harness",
|
|
701
820
|
children: [
|
|
702
|
-
/* @__PURE__ */
|
|
703
|
-
/* @__PURE__ */
|
|
704
|
-
!locked && /* @__PURE__ */
|
|
821
|
+
/* @__PURE__ */ jsx5(HarnessLogo, { type: value, size: 16, className: "shrink-0" }),
|
|
822
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate", children: selected?.label ?? value }),
|
|
823
|
+
!locked && /* @__PURE__ */ jsx5(ChevronDown3, { className: "ml-auto h-3.5 w-3.5 shrink-0 text-muted-foreground" })
|
|
705
824
|
]
|
|
706
825
|
}
|
|
707
826
|
) }),
|
|
708
|
-
/* @__PURE__ */
|
|
827
|
+
/* @__PURE__ */ jsx5(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsxs4(
|
|
709
828
|
DropdownMenu2.Content,
|
|
710
829
|
{
|
|
711
830
|
side,
|
|
@@ -715,7 +834,7 @@ function HarnessDropdown({
|
|
|
715
834
|
sideOffset: 6,
|
|
716
835
|
className: pickerMenuContentClass,
|
|
717
836
|
children: [
|
|
718
|
-
showSearch && /* @__PURE__ */
|
|
837
|
+
showSearch && /* @__PURE__ */ jsx5(
|
|
719
838
|
PickerMenuSearch,
|
|
720
839
|
{
|
|
721
840
|
value: query,
|
|
@@ -723,7 +842,7 @@ function HarnessDropdown({
|
|
|
723
842
|
placeholder: "Search agents..."
|
|
724
843
|
}
|
|
725
844
|
),
|
|
726
|
-
/* @__PURE__ */
|
|
845
|
+
/* @__PURE__ */ jsx5("div", { className: pickerMenuBodyClass, children: sections.length === 0 ? /* @__PURE__ */ jsx5("div", { className: "px-3 py-8 text-center text-xs text-muted-foreground", children: "No agents match." }) : sections.map((section) => /* @__PURE__ */ jsx5(PickerMenuSection, { label: section.label, children: section.items.map((option) => /* @__PURE__ */ jsxs4(
|
|
727
846
|
DropdownMenu2.Item,
|
|
728
847
|
{
|
|
729
848
|
onSelect: (event) => {
|
|
@@ -734,7 +853,7 @@ function HarnessDropdown({
|
|
|
734
853
|
active: option.type === value
|
|
735
854
|
}),
|
|
736
855
|
children: [
|
|
737
|
-
/* @__PURE__ */
|
|
856
|
+
/* @__PURE__ */ jsx5(
|
|
738
857
|
HarnessLogo,
|
|
739
858
|
{
|
|
740
859
|
type: option.type,
|
|
@@ -742,18 +861,18 @@ function HarnessDropdown({
|
|
|
742
861
|
className: "mt-0.5"
|
|
743
862
|
}
|
|
744
863
|
),
|
|
745
|
-
/* @__PURE__ */
|
|
746
|
-
/* @__PURE__ */
|
|
747
|
-
/* @__PURE__ */
|
|
748
|
-
harnessAutonomyNote(option.type) && /* @__PURE__ */
|
|
864
|
+
/* @__PURE__ */ jsxs4("div", { className: "min-w-0 flex-1", children: [
|
|
865
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5", children: [
|
|
866
|
+
/* @__PURE__ */ jsx5("span", { className: "min-w-0 truncate text-sm font-medium", children: option.label }),
|
|
867
|
+
harnessAutonomyNote(option.type) && /* @__PURE__ */ jsx5(PickerMenuTag, { children: harnessAutonomyNote(option.type) })
|
|
749
868
|
] }),
|
|
750
|
-
/* @__PURE__ */
|
|
869
|
+
/* @__PURE__ */ jsx5(PickerMenuMeta, { parts: [option.description] })
|
|
751
870
|
] })
|
|
752
871
|
]
|
|
753
872
|
},
|
|
754
873
|
option.type
|
|
755
874
|
)) }, section.key)) }),
|
|
756
|
-
showSearch && /* @__PURE__ */
|
|
875
|
+
showSearch && /* @__PURE__ */ jsxs4(PickerMenuFooter, { children: [
|
|
757
876
|
filtered.length,
|
|
758
877
|
" of ",
|
|
759
878
|
options.length,
|
|
@@ -826,20 +945,27 @@ function AgentSessionControls({
|
|
|
826
945
|
}
|
|
827
946
|
if (nextHarness) clampEffort(nextHarness, nextModelId);
|
|
828
947
|
};
|
|
829
|
-
const
|
|
948
|
+
const chatModels = model && context === "chat" && model.modalities === void 0 ? model.models.filter(isTextChatModel) : model?.models;
|
|
949
|
+
const visibleModels = model && restrictModelsToHarness && harness ? (chatModels ?? []).filter(
|
|
830
950
|
(entry) => isModelCompatibleWithHarness(
|
|
831
951
|
harness.value,
|
|
832
952
|
canonicalModelId(entry)
|
|
833
953
|
)
|
|
834
|
-
) :
|
|
954
|
+
) : chatModels;
|
|
835
955
|
const harnessAvailable = harness?.available ?? (context === "chat" ? chatCapableHarnesses : void 0);
|
|
836
956
|
const collapsed = layout === "gear" || layout === "combined";
|
|
837
957
|
const menuSide = collapsed ? "left" : "bottom";
|
|
838
958
|
const menuAlign = collapsed ? "end" : "start";
|
|
839
959
|
const collapsedTriggerClass = layout === "combined" ? "w-full bg-transparent shadow-none hover:bg-muted/60 data-[state=open]:bg-muted/60" : collapsed ? "w-full" : void 0;
|
|
960
|
+
const secondaryTriggerClass = collapsed ? collapsedTriggerClass : cn(
|
|
961
|
+
"border-transparent bg-transparent text-muted-foreground shadow-none",
|
|
962
|
+
"hover:border-transparent hover:bg-muted/50 hover:text-foreground",
|
|
963
|
+
"data-[state=open]:border-transparent data-[state=open]:bg-muted/50 data-[state=open]:text-foreground"
|
|
964
|
+
);
|
|
965
|
+
const modelTriggerClass = collapsed ? cn(collapsedTriggerClass, "h-8 rounded-lg px-2.5 text-xs") : void 0;
|
|
840
966
|
const inlineForceDown = menuPlacement === "down" && layout === "inline";
|
|
841
967
|
const avoidCollisions = inlineForceDown ? false : void 0;
|
|
842
|
-
const harnessNode = harness && /* @__PURE__ */
|
|
968
|
+
const harnessNode = harness && /* @__PURE__ */ jsx5(
|
|
843
969
|
HarnessDropdown,
|
|
844
970
|
{
|
|
845
971
|
...harness,
|
|
@@ -848,10 +974,10 @@ function AgentSessionControls({
|
|
|
848
974
|
side: menuSide,
|
|
849
975
|
align: menuAlign,
|
|
850
976
|
avoidCollisions,
|
|
851
|
-
triggerClassName:
|
|
977
|
+
triggerClassName: secondaryTriggerClass
|
|
852
978
|
}
|
|
853
979
|
);
|
|
854
|
-
const profileNode = profile && /* @__PURE__ */
|
|
980
|
+
const profileNode = profile && /* @__PURE__ */ jsx5(
|
|
855
981
|
AgentProfilePicker,
|
|
856
982
|
{
|
|
857
983
|
value: profile.value,
|
|
@@ -862,10 +988,15 @@ function AgentSessionControls({
|
|
|
862
988
|
onUpdate: profile.onUpdate,
|
|
863
989
|
onDelete: profile.onDelete,
|
|
864
990
|
disabled: profile.disabled,
|
|
865
|
-
|
|
991
|
+
locked: profile.locked,
|
|
992
|
+
lockReason: profile.lockReason,
|
|
993
|
+
onNewChat: profile.onNewChat,
|
|
994
|
+
side: inlineForceDown || collapsed ? "bottom" : "top",
|
|
995
|
+
triggerClassName: secondaryTriggerClass,
|
|
996
|
+
popoverClassName: collapsed ? "w-full" : void 0
|
|
866
997
|
}
|
|
867
998
|
);
|
|
868
|
-
const modelNode = model && /* @__PURE__ */
|
|
999
|
+
const modelNode = model && /* @__PURE__ */ jsx5(
|
|
869
1000
|
ModelPicker,
|
|
870
1001
|
{
|
|
871
1002
|
variant: "pill",
|
|
@@ -876,15 +1007,17 @@ function AgentSessionControls({
|
|
|
876
1007
|
loading: model.loading,
|
|
877
1008
|
popular: model.popular,
|
|
878
1009
|
recents: model.recents,
|
|
1010
|
+
modalities: model.modalities,
|
|
1011
|
+
excludeProviders: model.excludeProviders,
|
|
879
1012
|
disabled: model.disabled || (visibleModels ?? []).length === 0 || !selectorHonorsModel,
|
|
880
1013
|
side: collapsed ? void 0 : "bottom",
|
|
881
1014
|
avoidCollisions,
|
|
882
|
-
triggerClassName:
|
|
1015
|
+
triggerClassName: modelTriggerClass
|
|
883
1016
|
}
|
|
884
1017
|
);
|
|
885
1018
|
const modelReasoning = modelReasoningCapability(model?.models, model?.value);
|
|
886
1019
|
const reasoningOptions = (harness && HARNESS_REASONING_OPTIONS[harness.value]) ?? reasoning?.options;
|
|
887
|
-
const reasoningNode = reasoning && /* @__PURE__ */
|
|
1020
|
+
const reasoningNode = reasoning && /* @__PURE__ */ jsx5(
|
|
888
1021
|
ReasoningLevelPicker,
|
|
889
1022
|
{
|
|
890
1023
|
value: reasoning.value,
|
|
@@ -894,11 +1027,11 @@ function AgentSessionControls({
|
|
|
894
1027
|
available: harness ? reasoningEffortsFor(harness.value, modelReasoning) : reasoning.available,
|
|
895
1028
|
side: collapsed ? void 0 : "bottom",
|
|
896
1029
|
avoidCollisions,
|
|
897
|
-
triggerClassName:
|
|
1030
|
+
triggerClassName: secondaryTriggerClass
|
|
898
1031
|
}
|
|
899
1032
|
);
|
|
900
1033
|
if (layout === "gear") {
|
|
901
|
-
return /* @__PURE__ */
|
|
1034
|
+
return /* @__PURE__ */ jsx5(
|
|
902
1035
|
GearControls,
|
|
903
1036
|
{
|
|
904
1037
|
className,
|
|
@@ -917,8 +1050,8 @@ function AgentSessionControls({
|
|
|
917
1050
|
segments.push({
|
|
918
1051
|
key: "harness",
|
|
919
1052
|
label: harnessLabel,
|
|
920
|
-
node: /* @__PURE__ */
|
|
921
|
-
/* @__PURE__ */
|
|
1053
|
+
node: /* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-1.5", children: [
|
|
1054
|
+
/* @__PURE__ */ jsx5(HarnessLogo, { type: harness.value, size: 16, className: "shrink-0" }),
|
|
922
1055
|
harnessLabel
|
|
923
1056
|
] })
|
|
924
1057
|
});
|
|
@@ -935,8 +1068,8 @@ function AgentSessionControls({
|
|
|
935
1068
|
segments.push({
|
|
936
1069
|
key: "model",
|
|
937
1070
|
label: modelLabel,
|
|
938
|
-
node: /* @__PURE__ */
|
|
939
|
-
identity && /* @__PURE__ */
|
|
1071
|
+
node: /* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-1.5", children: [
|
|
1072
|
+
identity && /* @__PURE__ */ jsx5(ModelBrandStack, { identity, size: "sm" }),
|
|
940
1073
|
modelLabel
|
|
941
1074
|
] })
|
|
942
1075
|
});
|
|
@@ -948,14 +1081,14 @@ function AgentSessionControls({
|
|
|
948
1081
|
segments.push({
|
|
949
1082
|
key: "effort",
|
|
950
1083
|
label: effortLabel,
|
|
951
|
-
node: /* @__PURE__ */
|
|
952
|
-
/* @__PURE__ */
|
|
1084
|
+
node: /* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-1.5", children: [
|
|
1085
|
+
/* @__PURE__ */ jsx5("span", { className: "flex w-3.5 shrink-0 justify-center", children: /* @__PURE__ */ jsx5(ReasoningGlyph, { level: reasoning.value }) }),
|
|
953
1086
|
effortLabel
|
|
954
1087
|
] })
|
|
955
1088
|
});
|
|
956
1089
|
}
|
|
957
|
-
const summary = /* @__PURE__ */
|
|
958
|
-
index > 0 && /* @__PURE__ */
|
|
1090
|
+
const summary = /* @__PURE__ */ jsx5("span", { className: "flex items-center gap-1.5", children: segments.map((segment, index) => /* @__PURE__ */ jsxs4(React5.Fragment, { children: [
|
|
1091
|
+
index > 0 && /* @__PURE__ */ jsx5(
|
|
959
1092
|
"span",
|
|
960
1093
|
{
|
|
961
1094
|
className: "text-base leading-none text-muted-foreground/60",
|
|
@@ -965,7 +1098,7 @@ function AgentSessionControls({
|
|
|
965
1098
|
),
|
|
966
1099
|
segment.node
|
|
967
1100
|
] }, segment.key)) });
|
|
968
|
-
return /* @__PURE__ */
|
|
1101
|
+
return /* @__PURE__ */ jsx5(
|
|
969
1102
|
SummaryControls,
|
|
970
1103
|
{
|
|
971
1104
|
className,
|
|
@@ -980,7 +1113,7 @@ function AgentSessionControls({
|
|
|
980
1113
|
}
|
|
981
1114
|
);
|
|
982
1115
|
}
|
|
983
|
-
return /* @__PURE__ */
|
|
1116
|
+
return /* @__PURE__ */ jsxs4(
|
|
984
1117
|
"div",
|
|
985
1118
|
{
|
|
986
1119
|
className: cn("flex flex-wrap items-center gap-2", className),
|
|
@@ -990,7 +1123,7 @@ function AgentSessionControls({
|
|
|
990
1123
|
harnessNode,
|
|
991
1124
|
modelNode,
|
|
992
1125
|
reasoningNode,
|
|
993
|
-
trailing && /* @__PURE__ */
|
|
1126
|
+
trailing && /* @__PURE__ */ jsx5("div", { className: "ml-auto flex items-center gap-2", children: trailing })
|
|
994
1127
|
]
|
|
995
1128
|
}
|
|
996
1129
|
);
|
|
@@ -1003,11 +1136,11 @@ function GearControls({
|
|
|
1003
1136
|
reasoningNode,
|
|
1004
1137
|
trailing
|
|
1005
1138
|
}) {
|
|
1006
|
-
return /* @__PURE__ */
|
|
1139
|
+
return /* @__PURE__ */ jsx5(
|
|
1007
1140
|
CollapsibleControls,
|
|
1008
1141
|
{
|
|
1009
1142
|
className,
|
|
1010
|
-
trigger: /* @__PURE__ */
|
|
1143
|
+
trigger: /* @__PURE__ */ jsx5(SlidersHorizontal, { className: "h-4 w-4 text-muted-foreground" }),
|
|
1011
1144
|
triggerClassName: cn(
|
|
1012
1145
|
"inline-flex h-8 w-8 items-center justify-center rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container",
|
|
1013
1146
|
"text-foreground shadow-sm transition-colors",
|
|
@@ -1031,8 +1164,8 @@ function GearSection({
|
|
|
1031
1164
|
label,
|
|
1032
1165
|
children
|
|
1033
1166
|
}) {
|
|
1034
|
-
return /* @__PURE__ */
|
|
1035
|
-
/* @__PURE__ */
|
|
1167
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-1", children: [
|
|
1168
|
+
/* @__PURE__ */ jsx5("span", { className: "px-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground/70", children: label }),
|
|
1036
1169
|
children
|
|
1037
1170
|
] });
|
|
1038
1171
|
}
|
|
@@ -1047,13 +1180,13 @@ function SummaryControls({
|
|
|
1047
1180
|
reasoningNode,
|
|
1048
1181
|
trailing
|
|
1049
1182
|
}) {
|
|
1050
|
-
return /* @__PURE__ */
|
|
1183
|
+
return /* @__PURE__ */ jsx5(
|
|
1051
1184
|
CollapsibleControls,
|
|
1052
1185
|
{
|
|
1053
1186
|
className,
|
|
1054
|
-
trigger: /* @__PURE__ */
|
|
1187
|
+
trigger: /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1055
1188
|
summary,
|
|
1056
|
-
/* @__PURE__ */
|
|
1189
|
+
/* @__PURE__ */ jsx5(ChevronDown3, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })
|
|
1057
1190
|
] }),
|
|
1058
1191
|
triggerTitle: title,
|
|
1059
1192
|
triggerClassName: cn(
|
|
@@ -1088,15 +1221,15 @@ function CollapsibleControls({
|
|
|
1088
1221
|
reasoningNode,
|
|
1089
1222
|
trailing
|
|
1090
1223
|
}) {
|
|
1091
|
-
return /* @__PURE__ */
|
|
1224
|
+
return /* @__PURE__ */ jsxs4(
|
|
1092
1225
|
"div",
|
|
1093
1226
|
{
|
|
1094
1227
|
className: cn("flex items-center gap-2", className),
|
|
1095
1228
|
"data-testid": "agent-session-controls",
|
|
1096
1229
|
children: [
|
|
1097
|
-
trailing && /* @__PURE__ */
|
|
1098
|
-
/* @__PURE__ */
|
|
1099
|
-
/* @__PURE__ */
|
|
1230
|
+
trailing && /* @__PURE__ */ jsx5("div", { className: "flex items-center gap-2", children: trailing }),
|
|
1231
|
+
/* @__PURE__ */ jsxs4(DropdownMenu2.Root, { children: [
|
|
1232
|
+
/* @__PURE__ */ jsx5(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx5(
|
|
1100
1233
|
"button",
|
|
1101
1234
|
{
|
|
1102
1235
|
type: "button",
|
|
@@ -1106,7 +1239,7 @@ function CollapsibleControls({
|
|
|
1106
1239
|
children: trigger
|
|
1107
1240
|
}
|
|
1108
1241
|
) }),
|
|
1109
|
-
/* @__PURE__ */
|
|
1242
|
+
/* @__PURE__ */ jsx5(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsxs4(
|
|
1110
1243
|
DropdownMenu2.Content,
|
|
1111
1244
|
{
|
|
1112
1245
|
side: contentSide,
|
|
@@ -1128,10 +1261,10 @@ function CollapsibleControls({
|
|
|
1128
1261
|
contentClassName
|
|
1129
1262
|
),
|
|
1130
1263
|
children: [
|
|
1131
|
-
profileNode && /* @__PURE__ */
|
|
1132
|
-
harnessNode && /* @__PURE__ */
|
|
1133
|
-
modelNode && /* @__PURE__ */
|
|
1134
|
-
reasoningNode && /* @__PURE__ */
|
|
1264
|
+
profileNode && /* @__PURE__ */ jsx5(GearSection, { label: "Agent", children: profileNode }),
|
|
1265
|
+
harnessNode && /* @__PURE__ */ jsx5(GearSection, { label: "Harness", children: harnessNode }),
|
|
1266
|
+
modelNode && /* @__PURE__ */ jsx5(GearSection, { label: "Model", children: modelNode }),
|
|
1267
|
+
reasoningNode && /* @__PURE__ */ jsx5(GearSection, { label: "Effort", children: reasoningNode })
|
|
1135
1268
|
]
|
|
1136
1269
|
}
|
|
1137
1270
|
) })
|
|
@@ -1152,7 +1285,7 @@ import {
|
|
|
1152
1285
|
Upload,
|
|
1153
1286
|
X
|
|
1154
1287
|
} from "lucide-react";
|
|
1155
|
-
import * as
|
|
1288
|
+
import * as React6 from "react";
|
|
1156
1289
|
|
|
1157
1290
|
// src/chat/attachment-validation.ts
|
|
1158
1291
|
function isAcceptedType(file, accept) {
|
|
@@ -1206,7 +1339,7 @@ function validateComposerFiles(files, config) {
|
|
|
1206
1339
|
}
|
|
1207
1340
|
|
|
1208
1341
|
// src/chat/agent-composer.tsx
|
|
1209
|
-
import { Fragment as Fragment3, jsx as
|
|
1342
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1210
1343
|
var IMAGE_EXTENSION_BY_MIME = {
|
|
1211
1344
|
"image/png": "png",
|
|
1212
1345
|
"image/jpeg": "jpg",
|
|
@@ -1225,7 +1358,7 @@ function imageExtension(file) {
|
|
|
1225
1358
|
const fromName = /\.([a-z0-9]+)$/i.exec(file.name)?.[1];
|
|
1226
1359
|
return fromName?.toLowerCase() ?? "png";
|
|
1227
1360
|
}
|
|
1228
|
-
var MentionEditor =
|
|
1361
|
+
var MentionEditor = React6.lazy(() => import("./mention-editor-3Q6MYOIU.js"));
|
|
1229
1362
|
function AgentComposer({
|
|
1230
1363
|
value,
|
|
1231
1364
|
onChange,
|
|
@@ -1260,24 +1393,24 @@ function AgentComposer({
|
|
|
1260
1393
|
sendLabel = "Send",
|
|
1261
1394
|
autoFocus
|
|
1262
1395
|
}) {
|
|
1263
|
-
const textareaRef =
|
|
1264
|
-
const richFocusRef =
|
|
1265
|
-
const fileInputRef =
|
|
1266
|
-
const folderInputRef =
|
|
1267
|
-
const [dragOver, setDragOver] =
|
|
1268
|
-
const dragDepth =
|
|
1269
|
-
const pastedImageCount =
|
|
1270
|
-
const resize =
|
|
1396
|
+
const textareaRef = React6.useRef(null);
|
|
1397
|
+
const richFocusRef = React6.useRef(null);
|
|
1398
|
+
const fileInputRef = React6.useRef(null);
|
|
1399
|
+
const folderInputRef = React6.useRef(null);
|
|
1400
|
+
const [dragOver, setDragOver] = React6.useState(false);
|
|
1401
|
+
const dragDepth = React6.useRef(0);
|
|
1402
|
+
const pastedImageCount = React6.useRef(0);
|
|
1403
|
+
const resize = React6.useCallback(
|
|
1271
1404
|
(el) => {
|
|
1272
1405
|
el.style.height = "auto";
|
|
1273
1406
|
el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;
|
|
1274
1407
|
},
|
|
1275
1408
|
[maxHeight]
|
|
1276
1409
|
);
|
|
1277
|
-
|
|
1410
|
+
React6.useEffect(() => {
|
|
1278
1411
|
if (textareaRef.current) resize(textareaRef.current);
|
|
1279
1412
|
}, [value, resize]);
|
|
1280
|
-
|
|
1413
|
+
React6.useEffect(() => {
|
|
1281
1414
|
if (!focusShortcut || disabled) return;
|
|
1282
1415
|
function onKeyDown(event) {
|
|
1283
1416
|
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "l") {
|
|
@@ -1294,7 +1427,7 @@ function AgentComposer({
|
|
|
1294
1427
|
if (!canSend) return;
|
|
1295
1428
|
onSubmit();
|
|
1296
1429
|
};
|
|
1297
|
-
const registerRichFocus =
|
|
1430
|
+
const registerRichFocus = React6.useCallback((focus) => {
|
|
1298
1431
|
richFocusRef.current = focus;
|
|
1299
1432
|
}, []);
|
|
1300
1433
|
const dropEnabled = Boolean(onAttach);
|
|
@@ -1369,13 +1502,13 @@ function AgentComposer({
|
|
|
1369
1502
|
"hover:bg-surface-container-highest hover:text-foreground focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
1370
1503
|
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
1371
1504
|
);
|
|
1372
|
-
return /* @__PURE__ */
|
|
1373
|
-
dragOver && /* @__PURE__ */
|
|
1374
|
-
/* @__PURE__ */
|
|
1375
|
-
/* @__PURE__ */
|
|
1376
|
-
/* @__PURE__ */
|
|
1505
|
+
return /* @__PURE__ */ jsxs5("div", { className: cn("relative", className), children: [
|
|
1506
|
+
dragOver && /* @__PURE__ */ jsx6("div", { className: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-2xl border-2 border-dashed border-primary/50 bg-surface-container-high/95", children: /* @__PURE__ */ jsxs5("div", { className: "text-center", children: [
|
|
1507
|
+
/* @__PURE__ */ jsx6("span", { className: "mx-auto mb-2 flex size-11 items-center justify-center rounded-xl bg-primary/10 text-primary", children: /* @__PURE__ */ jsx6(Upload, { className: "size-5" }) }),
|
|
1508
|
+
/* @__PURE__ */ jsx6("p", { className: "font-semibold text-foreground text-sm", children: dropTitle }),
|
|
1509
|
+
/* @__PURE__ */ jsx6("p", { className: "mt-0.5 text-muted-foreground text-xs", children: dropDescription })
|
|
1377
1510
|
] }) }),
|
|
1378
|
-
/* @__PURE__ */
|
|
1511
|
+
/* @__PURE__ */ jsxs5(
|
|
1379
1512
|
"div",
|
|
1380
1513
|
{
|
|
1381
1514
|
"data-testid": "agent-composer",
|
|
@@ -1389,10 +1522,10 @@ function AgentComposer({
|
|
|
1389
1522
|
disabled && "opacity-60"
|
|
1390
1523
|
),
|
|
1391
1524
|
children: [
|
|
1392
|
-
attachments.length > 0 && /* @__PURE__ */
|
|
1525
|
+
attachments.length > 0 && /* @__PURE__ */ jsx6("div", { className: "flex flex-wrap gap-1.5", children: [...folderChips, ...fileChips].map((file) => {
|
|
1393
1526
|
const isError = file.status === "error";
|
|
1394
1527
|
const isPending = file.status === "pending";
|
|
1395
|
-
return /* @__PURE__ */
|
|
1528
|
+
return /* @__PURE__ */ jsxs5(
|
|
1396
1529
|
"span",
|
|
1397
1530
|
{
|
|
1398
1531
|
title: isError ? file.errorMessage : void 0,
|
|
@@ -1402,40 +1535,40 @@ function AgentComposer({
|
|
|
1402
1535
|
isPending && "opacity-60"
|
|
1403
1536
|
),
|
|
1404
1537
|
children: [
|
|
1405
|
-
file.kind !== "folder" && file.previewUrl ? /* @__PURE__ */
|
|
1538
|
+
file.kind !== "folder" && file.previewUrl ? /* @__PURE__ */ jsx6(
|
|
1406
1539
|
"img",
|
|
1407
1540
|
{
|
|
1408
1541
|
src: file.previewUrl,
|
|
1409
1542
|
alt: "",
|
|
1410
1543
|
className: "size-8 rounded object-cover"
|
|
1411
1544
|
}
|
|
1412
|
-
) : file.kind === "folder" ? /* @__PURE__ */
|
|
1413
|
-
/* @__PURE__ */
|
|
1414
|
-
file.fileCount !== void 0 && /* @__PURE__ */
|
|
1545
|
+
) : file.kind === "folder" ? /* @__PURE__ */ jsx6(Folder, { className: "size-3 shrink-0" }) : /* @__PURE__ */ jsx6(Paperclip, { className: "size-3 shrink-0" }),
|
|
1546
|
+
/* @__PURE__ */ jsx6("span", { className: "max-w-[150px] truncate", children: file.name }),
|
|
1547
|
+
file.fileCount !== void 0 && /* @__PURE__ */ jsxs5("span", { className: "text-muted-foreground", children: [
|
|
1415
1548
|
"(",
|
|
1416
1549
|
file.fileCount,
|
|
1417
1550
|
")"
|
|
1418
1551
|
] }),
|
|
1419
|
-
file.status === "uploading" && /* @__PURE__ */
|
|
1420
|
-
isError && file.errorMessage && /* @__PURE__ */
|
|
1421
|
-
isError && onRetryFile && /* @__PURE__ */
|
|
1552
|
+
file.status === "uploading" && /* @__PURE__ */ jsx6(Loader2, { className: "size-3 animate-spin" }),
|
|
1553
|
+
isError && file.errorMessage && /* @__PURE__ */ jsx6("span", { className: "max-w-[150px] truncate text-[var(--status-error,#ff4d6d)]/80", children: file.errorMessage }),
|
|
1554
|
+
isError && onRetryFile && /* @__PURE__ */ jsx6(
|
|
1422
1555
|
"button",
|
|
1423
1556
|
{
|
|
1424
1557
|
type: "button",
|
|
1425
1558
|
"aria-label": `Retry upload ${file.name}`,
|
|
1426
1559
|
onClick: () => onRetryFile(file.id),
|
|
1427
1560
|
className: "rounded p-0.5 text-muted-foreground transition-colors hover:text-foreground focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
1428
|
-
children: /* @__PURE__ */
|
|
1561
|
+
children: /* @__PURE__ */ jsx6(RotateCcw, { className: "size-3" })
|
|
1429
1562
|
}
|
|
1430
1563
|
),
|
|
1431
|
-
onRemoveFile && /* @__PURE__ */
|
|
1564
|
+
onRemoveFile && /* @__PURE__ */ jsx6(
|
|
1432
1565
|
"button",
|
|
1433
1566
|
{
|
|
1434
1567
|
type: "button",
|
|
1435
1568
|
"aria-label": `Remove ${file.name}`,
|
|
1436
1569
|
onClick: () => onRemoveFile(file.id),
|
|
1437
1570
|
className: "rounded p-0.5 text-muted-foreground transition-colors hover:text-foreground focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
1438
|
-
children: /* @__PURE__ */
|
|
1571
|
+
children: /* @__PURE__ */ jsx6(X, { className: "size-3" })
|
|
1439
1572
|
}
|
|
1440
1573
|
)
|
|
1441
1574
|
]
|
|
@@ -1443,10 +1576,10 @@ function AgentComposer({
|
|
|
1443
1576
|
file.id
|
|
1444
1577
|
);
|
|
1445
1578
|
}) }),
|
|
1446
|
-
mention ? /* @__PURE__ */
|
|
1447
|
-
|
|
1579
|
+
mention ? /* @__PURE__ */ jsx6(
|
|
1580
|
+
React6.Suspense,
|
|
1448
1581
|
{
|
|
1449
|
-
fallback: /* @__PURE__ */
|
|
1582
|
+
fallback: /* @__PURE__ */ jsx6(
|
|
1450
1583
|
"textarea",
|
|
1451
1584
|
{
|
|
1452
1585
|
rows: minRows,
|
|
@@ -1460,7 +1593,7 @@ function AgentComposer({
|
|
|
1460
1593
|
)
|
|
1461
1594
|
}
|
|
1462
1595
|
),
|
|
1463
|
-
children: /* @__PURE__ */
|
|
1596
|
+
children: /* @__PURE__ */ jsx6(
|
|
1464
1597
|
MentionEditor,
|
|
1465
1598
|
{
|
|
1466
1599
|
value,
|
|
@@ -1477,7 +1610,7 @@ function AgentComposer({
|
|
|
1477
1610
|
}
|
|
1478
1611
|
)
|
|
1479
1612
|
}
|
|
1480
|
-
) : /* @__PURE__ */
|
|
1613
|
+
) : /* @__PURE__ */ jsx6(
|
|
1481
1614
|
"textarea",
|
|
1482
1615
|
{
|
|
1483
1616
|
ref: textareaRef,
|
|
@@ -1502,9 +1635,9 @@ function AgentComposer({
|
|
|
1502
1635
|
)
|
|
1503
1636
|
}
|
|
1504
1637
|
),
|
|
1505
|
-
/* @__PURE__ */
|
|
1506
|
-
onAttach && /* @__PURE__ */
|
|
1507
|
-
/* @__PURE__ */
|
|
1638
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-end gap-2", children: [
|
|
1639
|
+
onAttach && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1640
|
+
/* @__PURE__ */ jsx6(
|
|
1508
1641
|
"button",
|
|
1509
1642
|
{
|
|
1510
1643
|
type: "button",
|
|
@@ -1513,10 +1646,10 @@ function AgentComposer({
|
|
|
1513
1646
|
"aria-label": "Attach files",
|
|
1514
1647
|
title: "Attach files",
|
|
1515
1648
|
className: attachButtonClass,
|
|
1516
|
-
children: /* @__PURE__ */
|
|
1649
|
+
children: /* @__PURE__ */ jsx6(Paperclip, { className: "size-4" })
|
|
1517
1650
|
}
|
|
1518
1651
|
),
|
|
1519
|
-
/* @__PURE__ */
|
|
1652
|
+
/* @__PURE__ */ jsx6(
|
|
1520
1653
|
"input",
|
|
1521
1654
|
{
|
|
1522
1655
|
ref: fileInputRef,
|
|
@@ -1532,8 +1665,8 @@ function AgentComposer({
|
|
|
1532
1665
|
}
|
|
1533
1666
|
)
|
|
1534
1667
|
] }),
|
|
1535
|
-
onAttachFolder && /* @__PURE__ */
|
|
1536
|
-
/* @__PURE__ */
|
|
1668
|
+
onAttachFolder && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1669
|
+
/* @__PURE__ */ jsx6(
|
|
1537
1670
|
"button",
|
|
1538
1671
|
{
|
|
1539
1672
|
type: "button",
|
|
@@ -1542,10 +1675,10 @@ function AgentComposer({
|
|
|
1542
1675
|
"aria-label": "Attach folder",
|
|
1543
1676
|
title: "Attach folder",
|
|
1544
1677
|
className: attachButtonClass,
|
|
1545
|
-
children: /* @__PURE__ */
|
|
1678
|
+
children: /* @__PURE__ */ jsx6(Folder, { className: "size-4" })
|
|
1546
1679
|
}
|
|
1547
1680
|
),
|
|
1548
|
-
/* @__PURE__ */
|
|
1681
|
+
/* @__PURE__ */ jsx6(
|
|
1549
1682
|
"input",
|
|
1550
1683
|
{
|
|
1551
1684
|
ref: folderInputRef,
|
|
@@ -1561,8 +1694,8 @@ function AgentComposer({
|
|
|
1561
1694
|
}
|
|
1562
1695
|
)
|
|
1563
1696
|
] }),
|
|
1564
|
-
/* @__PURE__ */
|
|
1565
|
-
controls ?? /* @__PURE__ */
|
|
1697
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 flex-1 items-center gap-2 overflow-x-auto overscroll-x-contain [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: [
|
|
1698
|
+
controls ?? /* @__PURE__ */ jsx6(
|
|
1566
1699
|
AgentSessionControls,
|
|
1567
1700
|
{
|
|
1568
1701
|
context,
|
|
@@ -1572,9 +1705,9 @@ function AgentComposer({
|
|
|
1572
1705
|
reasoning
|
|
1573
1706
|
}
|
|
1574
1707
|
),
|
|
1575
|
-
trailing && /* @__PURE__ */
|
|
1708
|
+
trailing && /* @__PURE__ */ jsx6("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: trailing })
|
|
1576
1709
|
] }),
|
|
1577
|
-
busy && onCancel ? /* @__PURE__ */
|
|
1710
|
+
busy && onCancel ? /* @__PURE__ */ jsx6(
|
|
1578
1711
|
"button",
|
|
1579
1712
|
{
|
|
1580
1713
|
type: "button",
|
|
@@ -1585,9 +1718,9 @@ function AgentComposer({
|
|
|
1585
1718
|
"bg-[var(--status-error,#ff4d6d)]/15 text-[var(--status-error,#ff4d6d)] transition-colors",
|
|
1586
1719
|
"hover:bg-[var(--status-error,#ff4d6d)]/25"
|
|
1587
1720
|
),
|
|
1588
|
-
children: /* @__PURE__ */
|
|
1721
|
+
children: /* @__PURE__ */ jsx6(Square, { className: "size-3.5 fill-current" })
|
|
1589
1722
|
}
|
|
1590
|
-
) : /* @__PURE__ */
|
|
1723
|
+
) : /* @__PURE__ */ jsx6(
|
|
1591
1724
|
"button",
|
|
1592
1725
|
{
|
|
1593
1726
|
type: "button",
|
|
@@ -1598,26 +1731,26 @@ function AgentComposer({
|
|
|
1598
1731
|
"flex size-9 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground",
|
|
1599
1732
|
"transition-opacity hover:opacity-90 disabled:opacity-40"
|
|
1600
1733
|
),
|
|
1601
|
-
children: busy ? /* @__PURE__ */
|
|
1734
|
+
children: busy ? /* @__PURE__ */ jsx6(Loader2, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsx6(ArrowUp, { className: "size-4" })
|
|
1602
1735
|
}
|
|
1603
1736
|
)
|
|
1604
1737
|
] })
|
|
1605
1738
|
]
|
|
1606
1739
|
}
|
|
1607
1740
|
),
|
|
1608
|
-
focusShortcut && /* @__PURE__ */
|
|
1609
|
-
/* @__PURE__ */
|
|
1610
|
-
/* @__PURE__ */
|
|
1611
|
-
/* @__PURE__ */
|
|
1741
|
+
focusShortcut && /* @__PURE__ */ jsx6("div", { className: "mt-1.5 flex justify-end px-1", children: /* @__PURE__ */ jsxs5("span", { className: "text-muted-foreground text-xs", children: [
|
|
1742
|
+
/* @__PURE__ */ jsx6("kbd", { className: "rounded border border-[var(--md3-outline-variant)] bg-surface-container px-1 py-0.5 text-[10px]", children: "Cmd" }),
|
|
1743
|
+
/* @__PURE__ */ jsx6("kbd", { className: "ml-0.5 rounded border border-[var(--md3-outline-variant)] bg-surface-container px-1 py-0.5 text-[10px]", children: "L" }),
|
|
1744
|
+
/* @__PURE__ */ jsx6("span", { className: "ml-1", children: "to focus" })
|
|
1612
1745
|
] }) })
|
|
1613
1746
|
] });
|
|
1614
1747
|
}
|
|
1615
1748
|
|
|
1616
1749
|
// src/chat/artifact-agent-dock.tsx
|
|
1617
|
-
import * as
|
|
1750
|
+
import * as React7 from "react";
|
|
1618
1751
|
import { Sparkles as Sparkles2, Send, Square as Square2, X as X2 } from "lucide-react";
|
|
1619
1752
|
import { ChatMessage } from "@tangle-network/ui/chat";
|
|
1620
|
-
import { jsx as
|
|
1753
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1621
1754
|
function defaultScopeLabel(scope) {
|
|
1622
1755
|
if (scope.label) return scope.label;
|
|
1623
1756
|
switch (scope.kind) {
|
|
@@ -1663,23 +1796,23 @@ function ArtifactAgentDock({
|
|
|
1663
1796
|
onError,
|
|
1664
1797
|
className
|
|
1665
1798
|
}) {
|
|
1666
|
-
const [threadId, setThreadId] =
|
|
1667
|
-
const [messages, setMessages] =
|
|
1668
|
-
const [composer, setComposer] =
|
|
1669
|
-
const [streamContent, setStreamContent] =
|
|
1670
|
-
const [sending, setSending] =
|
|
1671
|
-
const [loading, setLoading] =
|
|
1672
|
-
const abortRef =
|
|
1673
|
-
const scrollRef =
|
|
1674
|
-
const scopeTokenRef =
|
|
1675
|
-
const reportError =
|
|
1799
|
+
const [threadId, setThreadId] = React7.useState(null);
|
|
1800
|
+
const [messages, setMessages] = React7.useState([]);
|
|
1801
|
+
const [composer, setComposer] = React7.useState(defaultPrompt ?? "");
|
|
1802
|
+
const [streamContent, setStreamContent] = React7.useState("");
|
|
1803
|
+
const [sending, setSending] = React7.useState(false);
|
|
1804
|
+
const [loading, setLoading] = React7.useState(false);
|
|
1805
|
+
const abortRef = React7.useRef(null);
|
|
1806
|
+
const scrollRef = React7.useRef(null);
|
|
1807
|
+
const scopeTokenRef = React7.useRef(0);
|
|
1808
|
+
const reportError = React7.useCallback(
|
|
1676
1809
|
(message) => {
|
|
1677
1810
|
if (onError) onError(message);
|
|
1678
1811
|
else if (typeof console !== "undefined") console.error("[ArtifactAgentDock]", message);
|
|
1679
1812
|
},
|
|
1680
1813
|
[onError]
|
|
1681
1814
|
);
|
|
1682
|
-
|
|
1815
|
+
React7.useEffect(() => {
|
|
1683
1816
|
if (!open) return;
|
|
1684
1817
|
scopeTokenRef.current += 1;
|
|
1685
1818
|
abortRef.current?.abort();
|
|
@@ -1715,11 +1848,11 @@ function ArtifactAgentDock({
|
|
|
1715
1848
|
cancelled = true;
|
|
1716
1849
|
};
|
|
1717
1850
|
}, [open, scope.kind, scope.key, transport, reportError]);
|
|
1718
|
-
|
|
1851
|
+
React7.useEffect(() => {
|
|
1719
1852
|
if (!scrollRef.current) return;
|
|
1720
1853
|
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
1721
1854
|
}, [messages.length, streamContent]);
|
|
1722
|
-
const send =
|
|
1855
|
+
const send = React7.useCallback(async () => {
|
|
1723
1856
|
const text = composer.trim();
|
|
1724
1857
|
if (!text || !threadId || sending) return;
|
|
1725
1858
|
const token = scopeTokenRef.current;
|
|
@@ -1769,7 +1902,7 @@ function ArtifactAgentDock({
|
|
|
1769
1902
|
if (abortRef.current === controller) abortRef.current = null;
|
|
1770
1903
|
}
|
|
1771
1904
|
}, [composer, threadId, sending, transport, reportError]);
|
|
1772
|
-
const cancel =
|
|
1905
|
+
const cancel = React7.useCallback(() => {
|
|
1773
1906
|
if (threadId && transport.cancel) {
|
|
1774
1907
|
try {
|
|
1775
1908
|
void Promise.resolve(transport.cancel({ threadId })).catch(() => {
|
|
@@ -1783,7 +1916,7 @@ function ArtifactAgentDock({
|
|
|
1783
1916
|
}, [threadId, transport]);
|
|
1784
1917
|
if (!open) return null;
|
|
1785
1918
|
const heading = defaultScopeLabel(scope);
|
|
1786
|
-
return /* @__PURE__ */
|
|
1919
|
+
return /* @__PURE__ */ jsxs6(
|
|
1787
1920
|
"aside",
|
|
1788
1921
|
{
|
|
1789
1922
|
className: cn(
|
|
@@ -1792,38 +1925,38 @@ function ArtifactAgentDock({
|
|
|
1792
1925
|
),
|
|
1793
1926
|
"aria-label": `Agent chat about ${heading}`,
|
|
1794
1927
|
children: [
|
|
1795
|
-
/* @__PURE__ */
|
|
1796
|
-
/* @__PURE__ */
|
|
1797
|
-
/* @__PURE__ */
|
|
1798
|
-
/* @__PURE__ */
|
|
1799
|
-
/* @__PURE__ */
|
|
1800
|
-
/* @__PURE__ */
|
|
1928
|
+
/* @__PURE__ */ jsxs6("header", { className: "flex items-center justify-between border-b border-[var(--md3-outline-variant)] bg-surface-container-low px-4 py-3", children: [
|
|
1929
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
1930
|
+
/* @__PURE__ */ jsx7(Sparkles2, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
|
|
1931
|
+
/* @__PURE__ */ jsxs6("div", { className: "min-w-0", children: [
|
|
1932
|
+
/* @__PURE__ */ jsx7("div", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground", children: "Discussing" }),
|
|
1933
|
+
/* @__PURE__ */ jsx7("div", { className: "truncate text-sm font-semibold text-foreground", children: heading })
|
|
1801
1934
|
] })
|
|
1802
1935
|
] }),
|
|
1803
|
-
/* @__PURE__ */
|
|
1936
|
+
/* @__PURE__ */ jsx7(
|
|
1804
1937
|
"button",
|
|
1805
1938
|
{
|
|
1806
1939
|
type: "button",
|
|
1807
1940
|
onClick: () => onOpenChange(false),
|
|
1808
1941
|
"aria-label": "Close artifact chat",
|
|
1809
1942
|
className: "rounded-md p-1 text-muted-foreground transition-colors hover:bg-surface-container-high hover:text-foreground",
|
|
1810
|
-
children: /* @__PURE__ */
|
|
1943
|
+
children: /* @__PURE__ */ jsx7(X2, { className: "h-4 w-4" })
|
|
1811
1944
|
}
|
|
1812
1945
|
)
|
|
1813
1946
|
] }),
|
|
1814
|
-
/* @__PURE__ */
|
|
1815
|
-
/* @__PURE__ */
|
|
1816
|
-
/* @__PURE__ */
|
|
1947
|
+
/* @__PURE__ */ jsx7("div", { ref: scrollRef, className: "flex-1 overflow-y-auto px-3 py-4", children: loading ? /* @__PURE__ */ jsx7("div", { className: "px-3 py-8 text-center text-xs text-muted-foreground", children: "Loading conversation\u2026" }) : messages.length === 0 && !streamContent ? /* @__PURE__ */ jsxs6("div", { className: "px-3 py-12 text-center", children: [
|
|
1948
|
+
/* @__PURE__ */ jsx7(Sparkles2, { className: "mx-auto mb-3 h-5 w-5 text-muted-foreground/40" }),
|
|
1949
|
+
/* @__PURE__ */ jsxs6("p", { className: "text-sm text-foreground", children: [
|
|
1817
1950
|
"Ask the agent about this ",
|
|
1818
1951
|
scope.kind === "vault-file" ? "document" : scope.kind,
|
|
1819
1952
|
"."
|
|
1820
1953
|
] }),
|
|
1821
|
-
/* @__PURE__ */
|
|
1822
|
-
] }) : /* @__PURE__ */
|
|
1823
|
-
messages.map((m) => /* @__PURE__ */
|
|
1824
|
-
streamContent && /* @__PURE__ */
|
|
1954
|
+
/* @__PURE__ */ jsx7("p", { className: "mt-1 text-xs text-muted-foreground", children: "It can read the current contents and propose edits, rewrites, or follow-ups." })
|
|
1955
|
+
] }) : /* @__PURE__ */ jsxs6("div", { className: "space-y-3", children: [
|
|
1956
|
+
messages.map((m) => /* @__PURE__ */ jsx7(ChatMessage, { role: m.role, content: m.content, timestamp: m.createdAt }, m.id)),
|
|
1957
|
+
streamContent && /* @__PURE__ */ jsx7(ChatMessage, { role: "assistant", content: streamContent, isStreaming: true })
|
|
1825
1958
|
] }) }),
|
|
1826
|
-
/* @__PURE__ */
|
|
1959
|
+
/* @__PURE__ */ jsx7(
|
|
1827
1960
|
"form",
|
|
1828
1961
|
{
|
|
1829
1962
|
className: "border-t border-[var(--md3-outline-variant)] bg-surface-container-low p-3",
|
|
@@ -1831,8 +1964,8 @@ function ArtifactAgentDock({
|
|
|
1831
1964
|
e.preventDefault();
|
|
1832
1965
|
void send();
|
|
1833
1966
|
},
|
|
1834
|
-
children: /* @__PURE__ */
|
|
1835
|
-
/* @__PURE__ */
|
|
1967
|
+
children: /* @__PURE__ */ jsxs6("div", { className: "flex items-end gap-2", children: [
|
|
1968
|
+
/* @__PURE__ */ jsx7(
|
|
1836
1969
|
"textarea",
|
|
1837
1970
|
{
|
|
1838
1971
|
value: composer,
|
|
@@ -1849,23 +1982,23 @@ function ArtifactAgentDock({
|
|
|
1849
1982
|
className: "min-h-[44px] flex-1 resize-none rounded-[20px] border border-[var(--md3-outline-variant)] bg-surface-dim px-3.5 py-2 text-sm text-foreground placeholder:text-muted-foreground transition-colors focus:outline-none focus:border-[var(--border-accent)] disabled:opacity-50"
|
|
1850
1983
|
}
|
|
1851
1984
|
),
|
|
1852
|
-
sending ? /* @__PURE__ */
|
|
1985
|
+
sending ? /* @__PURE__ */ jsx7(
|
|
1853
1986
|
"button",
|
|
1854
1987
|
{
|
|
1855
1988
|
type: "button",
|
|
1856
1989
|
onClick: cancel,
|
|
1857
1990
|
"aria-label": "Cancel",
|
|
1858
1991
|
className: "inline-flex h-9 w-9 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-surface-container-high hover:text-foreground",
|
|
1859
|
-
children: /* @__PURE__ */
|
|
1992
|
+
children: /* @__PURE__ */ jsx7(Square2, { className: "h-4 w-4" })
|
|
1860
1993
|
}
|
|
1861
|
-
) : /* @__PURE__ */
|
|
1994
|
+
) : /* @__PURE__ */ jsx7(
|
|
1862
1995
|
"button",
|
|
1863
1996
|
{
|
|
1864
1997
|
type: "submit",
|
|
1865
1998
|
disabled: !composer.trim() || !threadId,
|
|
1866
1999
|
"aria-label": "Send",
|
|
1867
2000
|
className: "inline-flex h-9 w-9 items-center justify-center rounded-full bg-primary text-primary-foreground transition-colors hover:bg-primary/90 disabled:opacity-50",
|
|
1868
|
-
children: /* @__PURE__ */
|
|
2001
|
+
children: /* @__PURE__ */ jsx7(Send, { className: "h-4 w-4" })
|
|
1869
2002
|
}
|
|
1870
2003
|
)
|
|
1871
2004
|
] })
|