@tangle-network/agent-app 0.43.1 → 0.43.3
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/README.md +3 -1
- package/dist/assistant/index.d.ts +1 -1
- package/dist/assistant/index.js +2 -1
- package/dist/assistant/index.js.map +1 -1
- package/dist/chunk-65P3HJY3.js +166 -0
- package/dist/chunk-65P3HJY3.js.map +1 -0
- package/dist/{chunk-FNFCDSEB.js → chunk-CIQ3GHZW.js} +2 -1
- package/dist/chunk-CIQ3GHZW.js.map +1 -0
- package/dist/{chunk-7DPQ5VWR.js → chunk-VKHB7VP4.js} +389 -430
- package/dist/chunk-VKHB7VP4.js.map +1 -0
- package/dist/composer/index.js.map +1 -1
- package/dist/design-canvas-react/index.js +4 -4
- package/dist/index.js +12 -12
- package/dist/sandbox/index.js +1 -1
- package/dist/sandbox-terminal-BIIC__CP.d.ts +46 -0
- package/dist/teams-react/index.js +3 -3
- package/dist/web-react/index.d.ts +18 -102
- package/dist/web-react/index.js +5 -5
- package/dist/web-react/terminal.d.ts +49 -0
- package/dist/web-react/terminal.js +95 -0
- package/dist/web-react/terminal.js.map +1 -0
- package/package.json +6 -1
- package/dist/chunk-7DPQ5VWR.js.map +0 -1
- package/dist/chunk-FNFCDSEB.js.map +0 -1
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-E7QYOOON.js";
|
|
8
8
|
|
|
9
9
|
// src/web-react/index.tsx
|
|
10
|
-
import { useEffect as useEffect5, useMemo as useMemo3, useRef as useRef4, useState as
|
|
10
|
+
import { useEffect as useEffect5, useMemo as useMemo3, useRef as useRef4, useState as useState6, memo } from "react";
|
|
11
11
|
|
|
12
12
|
// src/web-react/smooth-text.ts
|
|
13
13
|
import { useEffect, useRef, useState } from "react";
|
|
@@ -490,11 +490,35 @@ async function streamChatTurn(opts) {
|
|
|
490
490
|
}
|
|
491
491
|
|
|
492
492
|
// src/web-react/chat-composer.tsx
|
|
493
|
-
import { useCallback, useState as useState3 } from "react";
|
|
494
493
|
import {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
494
|
+
useCallback,
|
|
495
|
+
useEffect as useEffect3,
|
|
496
|
+
useRef as useRef3,
|
|
497
|
+
useState as useState3
|
|
498
|
+
} from "react";
|
|
499
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
500
|
+
function SendGlyph({ className }) {
|
|
501
|
+
return /* @__PURE__ */ jsx4("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx4("path", { d: "M22 2 11 13M22 2l-7 20-4-9-9-4 20-7z" }) });
|
|
502
|
+
}
|
|
503
|
+
function StopGlyph({ className }) {
|
|
504
|
+
return /* @__PURE__ */ jsx4("svg", { className, viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsx4("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) });
|
|
505
|
+
}
|
|
506
|
+
function PaperclipGlyph({ className }) {
|
|
507
|
+
return /* @__PURE__ */ jsx4("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx4("path", { d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) });
|
|
508
|
+
}
|
|
509
|
+
function FolderGlyph({ className }) {
|
|
510
|
+
return /* @__PURE__ */ jsxs3("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
511
|
+
/* @__PURE__ */ jsx4("path", { d: "M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z" }),
|
|
512
|
+
/* @__PURE__ */ jsx4("path", { d: "M12 10v6m-3-3h6" })
|
|
513
|
+
] });
|
|
514
|
+
}
|
|
515
|
+
function CloseGlyph({ className }) {
|
|
516
|
+
return /* @__PURE__ */ jsx4("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx4("path", { d: "M18 6 6 18M6 6l12 12" }) });
|
|
517
|
+
}
|
|
518
|
+
function UploadGlyph({ className }) {
|
|
519
|
+
return /* @__PURE__ */ jsx4("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx4("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12" }) });
|
|
520
|
+
}
|
|
521
|
+
var MAX_HEIGHT = 168;
|
|
498
522
|
function ChatComposer({
|
|
499
523
|
onSend,
|
|
500
524
|
onCancel,
|
|
@@ -505,13 +529,14 @@ function ChatComposer({
|
|
|
505
529
|
onValueChange,
|
|
506
530
|
initialValue,
|
|
507
531
|
controls,
|
|
532
|
+
controlsPlacement = "above",
|
|
508
533
|
onAttach,
|
|
509
534
|
onAttachFolder,
|
|
510
|
-
pendingFiles,
|
|
535
|
+
pendingFiles = [],
|
|
511
536
|
onRemoveFile,
|
|
512
537
|
accept,
|
|
513
|
-
dropTitle,
|
|
514
|
-
dropDescription,
|
|
538
|
+
dropTitle = "Drop files to add context",
|
|
539
|
+
dropDescription = "They attach to your next message.",
|
|
515
540
|
focusShortcut = true,
|
|
516
541
|
sendLabel = "Send",
|
|
517
542
|
className
|
|
@@ -519,6 +544,11 @@ function ChatComposer({
|
|
|
519
544
|
const isControlled = value !== void 0;
|
|
520
545
|
const [internal, setInternal] = useState3(initialValue ?? "");
|
|
521
546
|
const text = isControlled ? value : internal;
|
|
547
|
+
const textareaRef = useRef3(null);
|
|
548
|
+
const fileInputRef = useRef3(null);
|
|
549
|
+
const folderInputRef = useRef3(null);
|
|
550
|
+
const [dragOver, setDragOver] = useState3(false);
|
|
551
|
+
const dragDepth = useRef3(0);
|
|
522
552
|
const setText = useCallback(
|
|
523
553
|
(next) => {
|
|
524
554
|
if (!isControlled) setInternal(next);
|
|
@@ -526,40 +556,218 @@ function ChatComposer({
|
|
|
526
556
|
},
|
|
527
557
|
[isControlled, onValueChange]
|
|
528
558
|
);
|
|
529
|
-
|
|
559
|
+
useEffect3(() => {
|
|
560
|
+
const el = textareaRef.current;
|
|
561
|
+
if (!el) return;
|
|
562
|
+
el.style.height = "auto";
|
|
563
|
+
el.style.height = `${Math.min(el.scrollHeight, MAX_HEIGHT)}px`;
|
|
564
|
+
}, [text]);
|
|
565
|
+
useEffect3(() => {
|
|
566
|
+
if (!focusShortcut || disabled) return;
|
|
567
|
+
function onKeyDown(e) {
|
|
568
|
+
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "l") {
|
|
569
|
+
e.preventDefault();
|
|
570
|
+
textareaRef.current?.focus();
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
document.addEventListener("keydown", onKeyDown);
|
|
574
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
575
|
+
}, [focusShortcut, disabled]);
|
|
576
|
+
const canSend = text.trim().length > 0 && !isStreaming && !disabled;
|
|
577
|
+
const send = useCallback(() => {
|
|
530
578
|
const trimmed = text.trim();
|
|
531
579
|
if (!trimmed || isStreaming || disabled) return;
|
|
532
580
|
onSend(trimmed);
|
|
533
581
|
setText("");
|
|
534
582
|
}, [text, isStreaming, disabled, onSend, setText]);
|
|
535
|
-
|
|
536
|
-
|
|
583
|
+
const handleKeyDown = (e) => {
|
|
584
|
+
if (e.nativeEvent.isComposing) return;
|
|
585
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
586
|
+
e.preventDefault();
|
|
587
|
+
send();
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
const handleFileChange = (e) => {
|
|
591
|
+
if (e.target.files?.length) onAttach?.(e.target.files);
|
|
592
|
+
e.target.value = "";
|
|
593
|
+
};
|
|
594
|
+
const handleFolderChange = (e) => {
|
|
595
|
+
if (e.target.files?.length) (onAttachFolder ?? onAttach)?.(e.target.files);
|
|
596
|
+
e.target.value = "";
|
|
597
|
+
};
|
|
598
|
+
const handleDragEnter = useCallback((e) => {
|
|
599
|
+
e.preventDefault();
|
|
600
|
+
e.stopPropagation();
|
|
601
|
+
dragDepth.current++;
|
|
602
|
+
if (e.dataTransfer?.types.includes("Files")) setDragOver(true);
|
|
603
|
+
}, []);
|
|
604
|
+
const handleDragLeave = useCallback((e) => {
|
|
605
|
+
e.preventDefault();
|
|
606
|
+
e.stopPropagation();
|
|
607
|
+
dragDepth.current--;
|
|
608
|
+
if (dragDepth.current <= 0) {
|
|
609
|
+
dragDepth.current = 0;
|
|
610
|
+
setDragOver(false);
|
|
611
|
+
}
|
|
612
|
+
}, []);
|
|
613
|
+
const handleDragOver = useCallback((e) => {
|
|
614
|
+
e.preventDefault();
|
|
615
|
+
e.stopPropagation();
|
|
616
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "copy";
|
|
617
|
+
}, []);
|
|
618
|
+
const handleDrop = useCallback(
|
|
619
|
+
(e) => {
|
|
620
|
+
e.preventDefault();
|
|
621
|
+
e.stopPropagation();
|
|
622
|
+
dragDepth.current = 0;
|
|
623
|
+
setDragOver(false);
|
|
624
|
+
const files = e.dataTransfer?.files;
|
|
625
|
+
if (files?.length) onAttach?.(files);
|
|
626
|
+
},
|
|
627
|
+
[onAttach]
|
|
628
|
+
);
|
|
629
|
+
const folderChips = pendingFiles.filter((f) => f.kind === "folder");
|
|
630
|
+
const fileChips = pendingFiles.filter((f) => f.kind !== "folder");
|
|
631
|
+
const showFooter = controls != null && controlsPlacement === "footer";
|
|
632
|
+
const showAbove = controls != null && controlsPlacement === "above";
|
|
633
|
+
return /* @__PURE__ */ jsxs3(
|
|
634
|
+
"div",
|
|
537
635
|
{
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
636
|
+
className: `relative ${className ?? ""}`,
|
|
637
|
+
onDragEnter: onAttach ? handleDragEnter : void 0,
|
|
638
|
+
onDragLeave: onAttach ? handleDragLeave : void 0,
|
|
639
|
+
onDragOver: onAttach ? handleDragOver : void 0,
|
|
640
|
+
onDrop: onAttach ? handleDrop : void 0,
|
|
641
|
+
children: [
|
|
642
|
+
dragOver && /* @__PURE__ */ jsx4("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-card/95", children: /* @__PURE__ */ jsxs3("div", { className: "text-center", children: [
|
|
643
|
+
/* @__PURE__ */ jsx4("span", { className: "mx-auto mb-2 flex h-11 w-11 items-center justify-center rounded-xl bg-primary/10 text-primary", children: /* @__PURE__ */ jsx4(UploadGlyph, { className: "h-5 w-5" }) }),
|
|
644
|
+
/* @__PURE__ */ jsx4("p", { className: "text-sm font-semibold text-foreground", children: dropTitle }),
|
|
645
|
+
/* @__PURE__ */ jsx4("p", { className: "mt-0.5 text-xs text-muted-foreground", children: dropDescription })
|
|
646
|
+
] }) }),
|
|
647
|
+
showAbove && /* @__PURE__ */ jsx4("div", { className: "mb-1.5 flex flex-wrap items-center gap-1.5 px-1", children: controls }),
|
|
648
|
+
pendingFiles.length > 0 && /* @__PURE__ */ jsx4("div", { className: "mb-2 flex flex-wrap gap-1.5", children: [...folderChips, ...fileChips].map((f) => /* @__PURE__ */ jsxs3(
|
|
649
|
+
"span",
|
|
650
|
+
{
|
|
651
|
+
className: `inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs ${f.status === "error" ? "border-destructive/40 text-destructive" : "border-border bg-muted/50 text-foreground"}`,
|
|
652
|
+
children: [
|
|
653
|
+
f.kind === "folder" ? /* @__PURE__ */ jsx4(FolderGlyph, { className: "h-3 w-3 shrink-0" }) : /* @__PURE__ */ jsx4(PaperclipGlyph, { className: "h-3 w-3 shrink-0" }),
|
|
654
|
+
/* @__PURE__ */ jsx4("span", { className: "max-w-[150px] truncate", children: f.name }),
|
|
655
|
+
f.fileCount !== void 0 && /* @__PURE__ */ jsxs3("span", { className: "text-muted-foreground", children: [
|
|
656
|
+
"(",
|
|
657
|
+
f.fileCount,
|
|
658
|
+
")"
|
|
659
|
+
] }),
|
|
660
|
+
f.status === "uploading" && /* @__PURE__ */ jsx4("span", { className: "h-3 w-3 animate-spin rounded-full border-2 border-primary border-t-transparent" }),
|
|
661
|
+
onRemoveFile && /* @__PURE__ */ jsx4(
|
|
662
|
+
"button",
|
|
663
|
+
{
|
|
664
|
+
type: "button",
|
|
665
|
+
"aria-label": `Remove ${f.name}`,
|
|
666
|
+
onClick: () => onRemoveFile(f.id),
|
|
667
|
+
className: "rounded p-0.5 text-muted-foreground transition hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
668
|
+
children: /* @__PURE__ */ jsx4(CloseGlyph, { className: "h-3 w-3" })
|
|
669
|
+
}
|
|
670
|
+
)
|
|
671
|
+
]
|
|
672
|
+
},
|
|
673
|
+
f.id
|
|
674
|
+
)) }),
|
|
675
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-end gap-2 rounded-2xl border border-border bg-card px-2.5 py-2 transition focus-within:border-primary/40 focus-within:ring-2 focus-within:ring-primary/15", children: [
|
|
676
|
+
onAttach && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
677
|
+
/* @__PURE__ */ jsx4(
|
|
678
|
+
"button",
|
|
679
|
+
{
|
|
680
|
+
type: "button",
|
|
681
|
+
onClick: () => fileInputRef.current?.click(),
|
|
682
|
+
disabled,
|
|
683
|
+
"aria-label": "Attach files",
|
|
684
|
+
title: "Attach files",
|
|
685
|
+
className: "mb-0.5 shrink-0 rounded-lg p-2 text-muted-foreground transition hover:bg-accent/40 hover:text-foreground disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
686
|
+
children: /* @__PURE__ */ jsx4(PaperclipGlyph, { className: "h-4 w-4" })
|
|
687
|
+
}
|
|
688
|
+
),
|
|
689
|
+
/* @__PURE__ */ jsx4("input", { ref: fileInputRef, type: "file", multiple: true, className: "hidden", accept, onChange: handleFileChange })
|
|
690
|
+
] }),
|
|
691
|
+
onAttachFolder && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
692
|
+
/* @__PURE__ */ jsx4(
|
|
693
|
+
"button",
|
|
694
|
+
{
|
|
695
|
+
type: "button",
|
|
696
|
+
onClick: () => folderInputRef.current?.click(),
|
|
697
|
+
disabled,
|
|
698
|
+
"aria-label": "Attach folder",
|
|
699
|
+
title: "Attach folder",
|
|
700
|
+
className: "mb-0.5 shrink-0 rounded-lg p-2 text-muted-foreground transition hover:bg-accent/40 hover:text-foreground disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
701
|
+
children: /* @__PURE__ */ jsx4(FolderGlyph, { className: "h-4 w-4" })
|
|
702
|
+
}
|
|
703
|
+
),
|
|
704
|
+
/* @__PURE__ */ jsx4(
|
|
705
|
+
"input",
|
|
706
|
+
{
|
|
707
|
+
ref: folderInputRef,
|
|
708
|
+
type: "file",
|
|
709
|
+
multiple: true,
|
|
710
|
+
className: "hidden",
|
|
711
|
+
onChange: handleFolderChange,
|
|
712
|
+
...{ webkitdirectory: "" }
|
|
713
|
+
}
|
|
714
|
+
)
|
|
715
|
+
] }),
|
|
716
|
+
/* @__PURE__ */ jsx4(
|
|
717
|
+
"textarea",
|
|
718
|
+
{
|
|
719
|
+
ref: textareaRef,
|
|
720
|
+
value: text,
|
|
721
|
+
onChange: (e) => setText(e.target.value),
|
|
722
|
+
onKeyDown: handleKeyDown,
|
|
723
|
+
placeholder,
|
|
724
|
+
disabled,
|
|
725
|
+
rows: 1,
|
|
726
|
+
"aria-label": "Message input",
|
|
727
|
+
className: "max-h-[168px] min-h-[40px] flex-1 resize-none bg-transparent px-1.5 py-2 text-[15px] leading-6 text-foreground outline-none placeholder:text-muted-foreground disabled:opacity-50"
|
|
728
|
+
}
|
|
729
|
+
),
|
|
730
|
+
showFooter && /* @__PURE__ */ jsx4("div", { className: "mb-0.5 flex shrink-0 items-center gap-1.5", children: controls }),
|
|
731
|
+
isStreaming ? /* @__PURE__ */ jsxs3(
|
|
732
|
+
"button",
|
|
733
|
+
{
|
|
734
|
+
type: "button",
|
|
735
|
+
onClick: onCancel,
|
|
736
|
+
"aria-label": "Stop response",
|
|
737
|
+
className: "mb-0.5 inline-flex shrink-0 items-center gap-1.5 rounded-full bg-destructive/15 px-3.5 py-2 text-sm font-medium text-destructive transition hover:bg-destructive/25 focus:outline-none focus-visible:ring-2 focus-visible:ring-destructive/50",
|
|
738
|
+
children: [
|
|
739
|
+
/* @__PURE__ */ jsx4(StopGlyph, { className: "h-3.5 w-3.5" }),
|
|
740
|
+
/* @__PURE__ */ jsx4("span", { children: "Stop" })
|
|
741
|
+
]
|
|
742
|
+
}
|
|
743
|
+
) : /* @__PURE__ */ jsxs3(
|
|
744
|
+
"button",
|
|
745
|
+
{
|
|
746
|
+
type: "button",
|
|
747
|
+
onClick: send,
|
|
748
|
+
disabled: !canSend,
|
|
749
|
+
"aria-label": sendLabel,
|
|
750
|
+
className: "mb-0.5 inline-flex shrink-0 items-center gap-1.5 rounded-full bg-primary px-3.5 py-2 text-sm font-medium text-primary-foreground shadow-sm transition hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-40 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-card",
|
|
751
|
+
children: [
|
|
752
|
+
/* @__PURE__ */ jsx4(SendGlyph, { className: "h-3.5 w-3.5" }),
|
|
753
|
+
/* @__PURE__ */ jsx4("span", { children: sendLabel })
|
|
754
|
+
]
|
|
755
|
+
}
|
|
756
|
+
)
|
|
757
|
+
] }),
|
|
758
|
+
focusShortcut && /* @__PURE__ */ jsx4("div", { className: "mt-1.5 flex justify-end px-1", children: /* @__PURE__ */ jsxs3("span", { className: "text-xs text-muted-foreground", children: [
|
|
759
|
+
/* @__PURE__ */ jsx4("kbd", { className: "rounded border border-border bg-background px-1 py-0.5 text-[10px]", children: "Cmd" }),
|
|
760
|
+
/* @__PURE__ */ jsx4("kbd", { className: "ml-0.5 rounded border border-border bg-background px-1 py-0.5 text-[10px]", children: "L" }),
|
|
761
|
+
/* @__PURE__ */ jsx4("span", { className: "ml-1", children: "to focus" })
|
|
762
|
+
] }) })
|
|
763
|
+
]
|
|
556
764
|
}
|
|
557
765
|
);
|
|
558
766
|
}
|
|
559
767
|
|
|
560
768
|
// src/web-react/mission-activity.tsx
|
|
561
|
-
import { useCallback as useCallback2, useEffect as
|
|
562
|
-
import { Fragment as
|
|
769
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useState as useState4 } from "react";
|
|
770
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
563
771
|
var LIVE_STATUSES = /* @__PURE__ */ new Set(["pending", "running"]);
|
|
564
772
|
var OK_STATUSES = /* @__PURE__ */ new Set(["completed", "done", "succeeded"]);
|
|
565
773
|
var ERROR_STATUSES = /* @__PURE__ */ new Set(["failed", "error", "cancelled", "aborted"]);
|
|
@@ -612,7 +820,7 @@ function RefreshGlyph({ className }) {
|
|
|
612
820
|
return /* @__PURE__ */ jsx5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx5("path", { d: "M21 12a9 9 0 1 1-2.64-6.36M21 3v6h-6" }) });
|
|
613
821
|
}
|
|
614
822
|
function CopyGlyph({ className }) {
|
|
615
|
-
return /* @__PURE__ */
|
|
823
|
+
return /* @__PURE__ */ jsxs4("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
616
824
|
/* @__PURE__ */ jsx5("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
|
|
617
825
|
/* @__PURE__ */ jsx5("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
|
|
618
826
|
] });
|
|
@@ -629,7 +837,7 @@ function TraceIdCopy({ traceId }) {
|
|
|
629
837
|
}
|
|
630
838
|
);
|
|
631
839
|
}, [traceId]);
|
|
632
|
-
return /* @__PURE__ */
|
|
840
|
+
return /* @__PURE__ */ jsxs4(
|
|
633
841
|
"button",
|
|
634
842
|
{
|
|
635
843
|
type: "button",
|
|
@@ -646,7 +854,7 @@ function TraceIdCopy({ traceId }) {
|
|
|
646
854
|
);
|
|
647
855
|
}
|
|
648
856
|
function StatusDot({ tone }) {
|
|
649
|
-
return /* @__PURE__ */
|
|
857
|
+
return /* @__PURE__ */ jsxs4("span", { className: "inline-flex items-center", children: [
|
|
650
858
|
/* @__PURE__ */ jsx5(
|
|
651
859
|
"span",
|
|
652
860
|
{
|
|
@@ -666,8 +874,8 @@ function FlowWaterfall({ trace }) {
|
|
|
666
874
|
const rows = waterfallLayout(trace);
|
|
667
875
|
if (rows.length === 0) return null;
|
|
668
876
|
const cost = formatActivityCost(trace.costUsd);
|
|
669
|
-
return /* @__PURE__ */
|
|
670
|
-
rows.map((row, i) => /* @__PURE__ */
|
|
877
|
+
return /* @__PURE__ */ jsxs4("div", { className: "space-y-1", children: [
|
|
878
|
+
rows.map((row, i) => /* @__PURE__ */ jsxs4("div", { className: "grid grid-cols-[minmax(0,2fr)_minmax(0,3fr)_auto] items-center gap-2", children: [
|
|
671
879
|
/* @__PURE__ */ jsx5("span", { className: "truncate font-mono text-[11px] text-muted-foreground", title: row.name, children: row.name }),
|
|
672
880
|
/* @__PURE__ */ jsx5("div", { className: "relative h-2 rounded-sm bg-muted/40", children: /* @__PURE__ */ jsx5(
|
|
673
881
|
"div",
|
|
@@ -678,7 +886,7 @@ function FlowWaterfall({ trace }) {
|
|
|
678
886
|
) }),
|
|
679
887
|
/* @__PURE__ */ jsx5("span", { className: "shrink-0 font-mono text-[10px] tabular-nums text-muted-foreground/70", children: row.durationLabel })
|
|
680
888
|
] }, i)),
|
|
681
|
-
/* @__PURE__ */
|
|
889
|
+
/* @__PURE__ */ jsxs4("p", { className: "pt-0.5 text-right font-mono text-[10px] tabular-nums text-muted-foreground/60", children: [
|
|
682
890
|
(trace.totalMs / 1e3).toFixed(1),
|
|
683
891
|
"s",
|
|
684
892
|
cost ? ` \xB7 ${cost}` : ""
|
|
@@ -688,29 +896,29 @@ function FlowWaterfall({ trace }) {
|
|
|
688
896
|
function MissionActivityLane({ activity, startedAt, nowMs }) {
|
|
689
897
|
const [expanded, setExpanded] = useState4(false);
|
|
690
898
|
if (activity.length === 0) return null;
|
|
691
|
-
return /* @__PURE__ */
|
|
899
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mt-1 border-l border-border/50 pl-3", children: [
|
|
692
900
|
activity.map((run) => {
|
|
693
901
|
const tone = activityTone(run.status);
|
|
694
902
|
const cost = formatActivityCost(run.costUsd);
|
|
695
903
|
const duration = formatActivityDuration(run.durationMs);
|
|
696
|
-
return /* @__PURE__ */
|
|
904
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 py-1 text-xs", children: [
|
|
697
905
|
/* @__PURE__ */ jsx5(StatusDot, { tone }),
|
|
698
|
-
/* @__PURE__ */
|
|
906
|
+
/* @__PURE__ */ jsxs4("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
699
907
|
/* @__PURE__ */ jsx5("span", { className: "font-medium", children: run.tool }),
|
|
700
|
-
/* @__PURE__ */
|
|
908
|
+
/* @__PURE__ */ jsxs4("span", { className: "text-muted-foreground", children: [
|
|
701
909
|
" \u2014 ",
|
|
702
910
|
run.detail
|
|
703
911
|
] })
|
|
704
912
|
] }),
|
|
705
913
|
tone === "live" && (run.iteration !== void 0 || run.phase !== void 0) && /* @__PURE__ */ jsx5("span", { className: "shrink-0 rounded-full bg-warning/10 px-1.5 py-0.5 font-mono text-[10px] text-warning", children: [run.iteration !== void 0 ? `iter ${run.iteration}` : null, run.phase ?? null].filter(Boolean).join(" \xB7 ") }),
|
|
706
|
-
/* @__PURE__ */
|
|
914
|
+
/* @__PURE__ */ jsxs4("span", { className: "flex shrink-0 items-center gap-1.5 font-mono text-[10px] tabular-nums text-muted-foreground/70", children: [
|
|
707
915
|
tone !== "live" && tone !== "ok" && /* @__PURE__ */ jsx5("span", { children: run.status }),
|
|
708
916
|
cost && /* @__PURE__ */ jsx5("span", { children: cost }),
|
|
709
917
|
duration && /* @__PURE__ */ jsx5("span", { children: duration })
|
|
710
918
|
] })
|
|
711
919
|
] }, run.taskId);
|
|
712
920
|
}),
|
|
713
|
-
/* @__PURE__ */
|
|
921
|
+
/* @__PURE__ */ jsxs4(
|
|
714
922
|
"button",
|
|
715
923
|
{
|
|
716
924
|
type: "button",
|
|
@@ -741,12 +949,12 @@ function ActivityRow({
|
|
|
741
949
|
const tone = activityTone(record.status);
|
|
742
950
|
const cost = formatActivityCost(record.costUsd);
|
|
743
951
|
const duration = formatActivityDuration(record.durationMs);
|
|
744
|
-
return /* @__PURE__ */
|
|
745
|
-
/* @__PURE__ */
|
|
952
|
+
return /* @__PURE__ */ jsxs4("div", { className: "rounded-lg border border-border/60 bg-card", children: [
|
|
953
|
+
/* @__PURE__ */ jsxs4("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm", children: [
|
|
746
954
|
/* @__PURE__ */ jsx5(StatusDot, { tone }),
|
|
747
|
-
/* @__PURE__ */
|
|
955
|
+
/* @__PURE__ */ jsxs4("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
748
956
|
/* @__PURE__ */ jsx5("span", { className: "font-medium", children: record.tool }),
|
|
749
|
-
/* @__PURE__ */
|
|
957
|
+
/* @__PURE__ */ jsxs4("span", { className: "text-muted-foreground", children: [
|
|
750
958
|
" \u2014 ",
|
|
751
959
|
record.detail
|
|
752
960
|
] })
|
|
@@ -762,18 +970,18 @@ function ActivityRow({
|
|
|
762
970
|
cost && /* @__PURE__ */ jsx5("span", { className: "shrink-0 font-mono text-[11px] tabular-nums text-muted-foreground", children: cost }),
|
|
763
971
|
/* @__PURE__ */ jsx5(ChevronGlyph, { className: `h-3 w-3 shrink-0 text-muted-foreground transition-transform ${open ? "rotate-180" : ""}` })
|
|
764
972
|
] }),
|
|
765
|
-
open && /* @__PURE__ */
|
|
973
|
+
open && /* @__PURE__ */ jsxs4("div", { className: "space-y-2.5 border-t border-border/40 px-3 py-2.5", children: [
|
|
766
974
|
record.durationMs !== void 0 && /* @__PURE__ */ jsx5("div", { className: "rounded-md border border-border/50 bg-muted/10 p-2", children: /* @__PURE__ */ jsx5(FlowWaterfall, { trace: stepActivityFlowTrace([record]) }) }),
|
|
767
|
-
/* @__PURE__ */
|
|
975
|
+
/* @__PURE__ */ jsxs4("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 font-mono text-[11px]", children: [
|
|
768
976
|
/* @__PURE__ */ jsx5("dt", { className: "text-muted-foreground/60", children: "task" }),
|
|
769
977
|
/* @__PURE__ */ jsx5("dd", { className: "truncate text-muted-foreground", children: record.taskId }),
|
|
770
978
|
/* @__PURE__ */ jsx5("dt", { className: "text-muted-foreground/60", children: "started" }),
|
|
771
979
|
/* @__PURE__ */ jsx5("dd", { className: "text-muted-foreground", children: new Date(record.startedAt).toLocaleString() }),
|
|
772
|
-
duration && /* @__PURE__ */
|
|
980
|
+
duration && /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
773
981
|
/* @__PURE__ */ jsx5("dt", { className: "text-muted-foreground/60", children: "duration" }),
|
|
774
982
|
/* @__PURE__ */ jsx5("dd", { className: "text-muted-foreground", children: duration })
|
|
775
983
|
] }),
|
|
776
|
-
record.traceId && /* @__PURE__ */
|
|
984
|
+
record.traceId && /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
777
985
|
/* @__PURE__ */ jsx5("dt", { className: "text-muted-foreground/60", children: "trace" }),
|
|
778
986
|
/* @__PURE__ */ jsx5("dd", { className: "min-w-0", children: /* @__PURE__ */ jsx5(TraceIdCopy, { traceId: record.traceId }) })
|
|
779
987
|
] })
|
|
@@ -803,11 +1011,11 @@ function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent ac
|
|
|
803
1011
|
},
|
|
804
1012
|
[fetchActivity]
|
|
805
1013
|
);
|
|
806
|
-
|
|
1014
|
+
useEffect4(() => {
|
|
807
1015
|
void load();
|
|
808
1016
|
}, [load]);
|
|
809
|
-
return /* @__PURE__ */
|
|
810
|
-
/* @__PURE__ */
|
|
1017
|
+
return /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
|
|
1018
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
|
|
811
1019
|
/* @__PURE__ */ jsx5("h2", { className: "flex-1 text-sm font-semibold", children: title }),
|
|
812
1020
|
/* @__PURE__ */ jsx5(
|
|
813
1021
|
"button",
|
|
@@ -837,256 +1045,10 @@ function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent ac
|
|
|
837
1045
|
] });
|
|
838
1046
|
}
|
|
839
1047
|
|
|
840
|
-
// src/web-react/sandbox-terminal.ts
|
|
841
|
-
import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef3, useState as useState5 } from "react";
|
|
842
|
-
var DEFAULT_PROVISION_POLL_INTERVAL_MS = 2e3;
|
|
843
|
-
var DEFAULT_PROVISION_POLL_TIMEOUT_MS = 9e4;
|
|
844
|
-
var DEFAULT_TOKEN_REFRESH_SKEW_MS = 12e4;
|
|
845
|
-
var EMPTY_CONNECTION = {
|
|
846
|
-
runtimeUrl: null,
|
|
847
|
-
sidecarUrl: null,
|
|
848
|
-
token: null,
|
|
849
|
-
expiresAt: null,
|
|
850
|
-
status: "idle",
|
|
851
|
-
error: null,
|
|
852
|
-
loading: false
|
|
853
|
-
};
|
|
854
|
-
function useSandboxTerminalConnection(opts) {
|
|
855
|
-
const [conn, setConn] = useState5(EMPTY_CONNECTION);
|
|
856
|
-
const mountedRef = useRef3(false);
|
|
857
|
-
const generationRef = useRef3(0);
|
|
858
|
-
const fetcher = opts.fetcher ?? fetch;
|
|
859
|
-
const pollIntervalMs = opts.provisionPollIntervalMs ?? DEFAULT_PROVISION_POLL_INTERVAL_MS;
|
|
860
|
-
const pollTimeoutMs = opts.provisionPollTimeoutMs ?? DEFAULT_PROVISION_POLL_TIMEOUT_MS;
|
|
861
|
-
const refreshSkewMs = opts.tokenRefreshSkewMs ?? DEFAULT_TOKEN_REFRESH_SKEW_MS;
|
|
862
|
-
const connectionUrl = useCallback3(() => {
|
|
863
|
-
if (typeof opts.connectionUrl === "function") return opts.connectionUrl(opts.workspaceId);
|
|
864
|
-
return opts.connectionUrl ?? `/api/workspaces/${encodeURIComponent(opts.workspaceId)}/sandbox/connection`;
|
|
865
|
-
}, [opts.connectionUrl, opts.workspaceId]);
|
|
866
|
-
const connect = useCallback3(async () => {
|
|
867
|
-
const generation = generationRef.current + 1;
|
|
868
|
-
generationRef.current = generation;
|
|
869
|
-
const isCurrent = () => mountedRef.current && generationRef.current === generation;
|
|
870
|
-
const setCurrentConn = (value) => {
|
|
871
|
-
if (!isCurrent()) return;
|
|
872
|
-
setConn(value);
|
|
873
|
-
};
|
|
874
|
-
setCurrentConn((current) => ({ ...current, loading: true, error: null }));
|
|
875
|
-
const deadline = Date.now() + pollTimeoutMs;
|
|
876
|
-
while (isCurrent()) {
|
|
877
|
-
try {
|
|
878
|
-
const res = await fetcher(connectionUrl());
|
|
879
|
-
const data = await res.json();
|
|
880
|
-
if (!isCurrent()) return;
|
|
881
|
-
const runtimeUrl = data.runtimeUrl ?? data.sidecarUrl;
|
|
882
|
-
if (res.ok && runtimeUrl && data.token && data.expiresAt) {
|
|
883
|
-
setCurrentConn({
|
|
884
|
-
runtimeUrl,
|
|
885
|
-
sidecarUrl: data.sidecarUrl ?? runtimeUrl,
|
|
886
|
-
token: data.token,
|
|
887
|
-
expiresAt: data.expiresAt,
|
|
888
|
-
status: data.status ?? "running",
|
|
889
|
-
error: null,
|
|
890
|
-
loading: false,
|
|
891
|
-
...data.sandboxId ? { sandboxId: data.sandboxId } : {}
|
|
892
|
-
});
|
|
893
|
-
return;
|
|
894
|
-
}
|
|
895
|
-
if (res.ok) {
|
|
896
|
-
setCurrentConn({
|
|
897
|
-
runtimeUrl: null,
|
|
898
|
-
sidecarUrl: null,
|
|
899
|
-
token: null,
|
|
900
|
-
expiresAt: null,
|
|
901
|
-
loading: false,
|
|
902
|
-
error: "Sandbox connection response is missing required fields",
|
|
903
|
-
status: data.status ?? "error",
|
|
904
|
-
...data.sandboxId ? { sandboxId: data.sandboxId } : {}
|
|
905
|
-
});
|
|
906
|
-
return;
|
|
907
|
-
}
|
|
908
|
-
if (res.status === 503 && Date.now() < deadline) {
|
|
909
|
-
setCurrentConn((current) => ({
|
|
910
|
-
...current,
|
|
911
|
-
loading: true,
|
|
912
|
-
status: data.status ?? "provisioning",
|
|
913
|
-
error: null
|
|
914
|
-
}));
|
|
915
|
-
await sleep(pollIntervalMs);
|
|
916
|
-
continue;
|
|
917
|
-
}
|
|
918
|
-
setCurrentConn((current) => ({
|
|
919
|
-
...current,
|
|
920
|
-
runtimeUrl: null,
|
|
921
|
-
sidecarUrl: null,
|
|
922
|
-
token: null,
|
|
923
|
-
expiresAt: null,
|
|
924
|
-
loading: false,
|
|
925
|
-
error: data.error ?? "Sandbox not available",
|
|
926
|
-
status: data.status ?? "error"
|
|
927
|
-
}));
|
|
928
|
-
return;
|
|
929
|
-
} catch (err) {
|
|
930
|
-
if (!isCurrent()) return;
|
|
931
|
-
if (Date.now() < deadline) {
|
|
932
|
-
await sleep(pollIntervalMs);
|
|
933
|
-
continue;
|
|
934
|
-
}
|
|
935
|
-
setCurrentConn((current) => ({
|
|
936
|
-
...current,
|
|
937
|
-
runtimeUrl: null,
|
|
938
|
-
sidecarUrl: null,
|
|
939
|
-
token: null,
|
|
940
|
-
expiresAt: null,
|
|
941
|
-
loading: false,
|
|
942
|
-
error: err instanceof Error ? err.message : "Connection failed"
|
|
943
|
-
}));
|
|
944
|
-
return;
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
}, [connectionUrl, fetcher, pollIntervalMs, pollTimeoutMs]);
|
|
948
|
-
useEffect4(() => {
|
|
949
|
-
mountedRef.current = true;
|
|
950
|
-
return () => {
|
|
951
|
-
mountedRef.current = false;
|
|
952
|
-
generationRef.current += 1;
|
|
953
|
-
};
|
|
954
|
-
}, []);
|
|
955
|
-
useEffect4(() => {
|
|
956
|
-
void connect();
|
|
957
|
-
}, [connect]);
|
|
958
|
-
useEffect4(() => {
|
|
959
|
-
if (!conn.runtimeUrl || !conn.token || !conn.expiresAt) return;
|
|
960
|
-
const refreshAt = Date.parse(conn.expiresAt) - Date.now() - refreshSkewMs;
|
|
961
|
-
if (!Number.isFinite(refreshAt)) {
|
|
962
|
-
setConn((current) => ({
|
|
963
|
-
...current,
|
|
964
|
-
runtimeUrl: null,
|
|
965
|
-
sidecarUrl: null,
|
|
966
|
-
token: null,
|
|
967
|
-
expiresAt: null,
|
|
968
|
-
status: "error",
|
|
969
|
-
error: "Sandbox token expiry is invalid"
|
|
970
|
-
}));
|
|
971
|
-
return;
|
|
972
|
-
}
|
|
973
|
-
const timer = window.setTimeout(() => {
|
|
974
|
-
void connect();
|
|
975
|
-
}, Math.max(1e3, refreshAt));
|
|
976
|
-
return () => window.clearTimeout(timer);
|
|
977
|
-
}, [conn.runtimeUrl, conn.token, conn.expiresAt, connect, refreshSkewMs]);
|
|
978
|
-
return { ...conn, connect };
|
|
979
|
-
}
|
|
980
|
-
function sleep(ms) {
|
|
981
|
-
return new Promise((resolve) => window.setTimeout(resolve, ms));
|
|
982
|
-
}
|
|
983
|
-
var DEFAULT_TERMINAL_CID_KEY = "agent-app:terminal-connection-id";
|
|
984
|
-
function newConnectionId() {
|
|
985
|
-
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
986
|
-
return `cid-${Date.now().toString(36)}-${Math.floor(Math.random() * 1e9).toString(36)}`;
|
|
987
|
-
}
|
|
988
|
-
function tabTerminalConnectionId(storageKey = DEFAULT_TERMINAL_CID_KEY) {
|
|
989
|
-
try {
|
|
990
|
-
const store = globalThis.sessionStorage;
|
|
991
|
-
const existing = store?.getItem(storageKey);
|
|
992
|
-
if (existing) return existing;
|
|
993
|
-
const id = newConnectionId();
|
|
994
|
-
store?.setItem(storageKey, id);
|
|
995
|
-
return id;
|
|
996
|
-
} catch {
|
|
997
|
-
return newConnectionId();
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
// src/web-react/workspace-terminal-panel.tsx
|
|
1002
|
-
import { lazy as lazy2, Suspense as Suspense2 } from "react";
|
|
1003
|
-
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1004
|
-
var TerminalView = lazy2(
|
|
1005
|
-
() => import("@tangle-network/sandbox-ui/terminal").then((m) => ({ default: m.TerminalView }))
|
|
1006
|
-
);
|
|
1007
|
-
var TONE_DOT = {
|
|
1008
|
-
idle: "bg-muted-foreground/50",
|
|
1009
|
-
connecting: "animate-pulse bg-warning",
|
|
1010
|
-
connected: "bg-success",
|
|
1011
|
-
error: "bg-destructive"
|
|
1012
|
-
};
|
|
1013
|
-
function defaultStatusDisplay(conn) {
|
|
1014
|
-
if (conn.error) return { tone: "error", label: "Disconnected" };
|
|
1015
|
-
if (conn.runtimeUrl && conn.token) return { tone: "connected", label: "Connected" };
|
|
1016
|
-
if (conn.loading) return { tone: "connecting", label: conn.status === "provisioning" ? "Provisioning\u2026" : "Connecting\u2026" };
|
|
1017
|
-
return { tone: "idle", label: "Idle" };
|
|
1018
|
-
}
|
|
1019
|
-
function WorkspaceTerminalPanel({
|
|
1020
|
-
connection,
|
|
1021
|
-
connectionId,
|
|
1022
|
-
title = "Terminal",
|
|
1023
|
-
subtitle,
|
|
1024
|
-
isActive,
|
|
1025
|
-
onRetry,
|
|
1026
|
-
statusDisplay,
|
|
1027
|
-
headerExtra,
|
|
1028
|
-
className
|
|
1029
|
-
}) {
|
|
1030
|
-
const status = (statusDisplay ?? defaultStatusDisplay)(connection);
|
|
1031
|
-
const apiUrl = connection.runtimeUrl ?? connection.sidecarUrl;
|
|
1032
|
-
const ready = Boolean(apiUrl && connection.token);
|
|
1033
|
-
return /* @__PURE__ */ jsxs4("div", { className: `flex h-full min-h-0 flex-col overflow-hidden rounded-xl border border-border bg-card ${className ?? ""}`, children: [
|
|
1034
|
-
/* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between gap-3 border-b border-border px-4 py-2.5", children: [
|
|
1035
|
-
/* @__PURE__ */ jsxs4("div", { className: "min-w-0", children: [
|
|
1036
|
-
/* @__PURE__ */ jsx6("p", { className: "truncate text-sm font-medium text-foreground", children: title }),
|
|
1037
|
-
subtitle && /* @__PURE__ */ jsx6("p", { className: "truncate text-xs text-muted-foreground", children: subtitle })
|
|
1038
|
-
] }),
|
|
1039
|
-
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
|
|
1040
|
-
/* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
1041
|
-
/* @__PURE__ */ jsx6("span", { className: `h-1.5 w-1.5 rounded-full ${TONE_DOT[status.tone]}`, "aria-hidden": true }),
|
|
1042
|
-
status.label
|
|
1043
|
-
] }),
|
|
1044
|
-
headerExtra
|
|
1045
|
-
] })
|
|
1046
|
-
] }),
|
|
1047
|
-
/* @__PURE__ */ jsx6("div", { className: "relative min-h-0 flex-1", children: ready ? /* @__PURE__ */ jsx6(Suspense2, { fallback: /* @__PURE__ */ jsx6(TerminalMessage, { children: "Loading terminal\u2026" }), children: /* @__PURE__ */ jsx6(
|
|
1048
|
-
TerminalView,
|
|
1049
|
-
{
|
|
1050
|
-
apiUrl,
|
|
1051
|
-
token: connection.token,
|
|
1052
|
-
connectionId,
|
|
1053
|
-
title,
|
|
1054
|
-
subtitle,
|
|
1055
|
-
isActive
|
|
1056
|
-
}
|
|
1057
|
-
) }) : /* @__PURE__ */ jsx6(TerminalMessage, { children: connection.error ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1058
|
-
/* @__PURE__ */ jsx6("p", { className: "text-sm text-destructive", children: connection.error }),
|
|
1059
|
-
onRetry && /* @__PURE__ */ jsx6(
|
|
1060
|
-
"button",
|
|
1061
|
-
{
|
|
1062
|
-
type: "button",
|
|
1063
|
-
onClick: onRetry,
|
|
1064
|
-
className: "mt-3 inline-flex items-center justify-center rounded-lg border border-border px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-muted",
|
|
1065
|
-
children: "Reconnect"
|
|
1066
|
-
}
|
|
1067
|
-
)
|
|
1068
|
-
] }) : connection.loading ? /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: connection.status === "provisioning" ? "Provisioning sandbox\u2026" : "Connecting\u2026" }) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1069
|
-
/* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: "Terminal not connected." }),
|
|
1070
|
-
onRetry && /* @__PURE__ */ jsx6(
|
|
1071
|
-
"button",
|
|
1072
|
-
{
|
|
1073
|
-
type: "button",
|
|
1074
|
-
onClick: onRetry,
|
|
1075
|
-
className: "mt-3 inline-flex items-center justify-center rounded-lg border border-border px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-muted",
|
|
1076
|
-
children: "Connect"
|
|
1077
|
-
}
|
|
1078
|
-
)
|
|
1079
|
-
] }) }) })
|
|
1080
|
-
] });
|
|
1081
|
-
}
|
|
1082
|
-
function TerminalMessage({ children }) {
|
|
1083
|
-
return /* @__PURE__ */ jsx6("div", { className: "absolute inset-0 flex flex-col items-center justify-center p-6 text-center", children });
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
1048
|
// src/web-react/seat-paywall.tsx
|
|
1087
|
-
import { jsx as
|
|
1049
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1088
1050
|
function CheckGlyph() {
|
|
1089
|
-
return /* @__PURE__ */
|
|
1051
|
+
return /* @__PURE__ */ jsx6(
|
|
1090
1052
|
"svg",
|
|
1091
1053
|
{
|
|
1092
1054
|
className: "h-4 w-4 shrink-0 text-primary",
|
|
@@ -1097,14 +1059,14 @@ function CheckGlyph() {
|
|
|
1097
1059
|
strokeLinecap: "round",
|
|
1098
1060
|
strokeLinejoin: "round",
|
|
1099
1061
|
"aria-hidden": true,
|
|
1100
|
-
children: /* @__PURE__ */
|
|
1062
|
+
children: /* @__PURE__ */ jsx6("path", { d: "M20 6 9 17l-5-5" })
|
|
1101
1063
|
}
|
|
1102
1064
|
);
|
|
1103
1065
|
}
|
|
1104
1066
|
function Benefit({ children }) {
|
|
1105
1067
|
return /* @__PURE__ */ jsxs5("li", { className: "flex items-start gap-2.5 text-sm text-foreground", children: [
|
|
1106
|
-
/* @__PURE__ */
|
|
1107
|
-
/* @__PURE__ */
|
|
1068
|
+
/* @__PURE__ */ jsx6("span", { className: "mt-0.5", children: /* @__PURE__ */ jsx6(CheckGlyph, {}) }),
|
|
1069
|
+
/* @__PURE__ */ jsx6("span", { children })
|
|
1108
1070
|
] });
|
|
1109
1071
|
}
|
|
1110
1072
|
function SeatPaywall({
|
|
@@ -1118,30 +1080,30 @@ function SeatPaywall({
|
|
|
1118
1080
|
footnote
|
|
1119
1081
|
}) {
|
|
1120
1082
|
const { pending, run } = usePending();
|
|
1121
|
-
return /* @__PURE__ */
|
|
1122
|
-
/* @__PURE__ */
|
|
1083
|
+
return /* @__PURE__ */ jsx6("div", { className: "flex min-h-[60vh] w-full items-center justify-center p-6", children: /* @__PURE__ */ jsxs5("div", { className: "w-full max-w-md rounded-2xl border border-border bg-card p-8 shadow-sm", children: [
|
|
1084
|
+
/* @__PURE__ */ jsx6("p", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: product }),
|
|
1123
1085
|
/* @__PURE__ */ jsxs5("h1", { className: "mt-2 text-2xl font-semibold tracking-tight text-foreground", children: [
|
|
1124
1086
|
"Unlock ",
|
|
1125
1087
|
product
|
|
1126
1088
|
] }),
|
|
1127
|
-
tagline && /* @__PURE__ */
|
|
1089
|
+
tagline && /* @__PURE__ */ jsx6("p", { className: "mt-2 text-sm text-muted-foreground", children: tagline }),
|
|
1128
1090
|
/* @__PURE__ */ jsxs5("div", { className: "mt-6 flex items-baseline gap-1.5", children: [
|
|
1129
1091
|
/* @__PURE__ */ jsxs5("span", { className: "text-3xl font-semibold text-foreground", children: [
|
|
1130
1092
|
"$",
|
|
1131
1093
|
priceUsd
|
|
1132
1094
|
] }),
|
|
1133
|
-
/* @__PURE__ */
|
|
1095
|
+
/* @__PURE__ */ jsx6("span", { className: "text-sm text-muted-foreground", children: "/mo" })
|
|
1134
1096
|
] }),
|
|
1135
1097
|
/* @__PURE__ */ jsxs5("p", { className: "mt-1 text-sm text-muted-foreground", children: [
|
|
1136
1098
|
"Includes $",
|
|
1137
1099
|
includedUsageUsd,
|
|
1138
1100
|
"/mo of AI usage"
|
|
1139
1101
|
] }),
|
|
1140
|
-
/* @__PURE__ */
|
|
1102
|
+
/* @__PURE__ */ jsx6("ul", { className: "mt-6 space-y-2.5", children: (benefits ?? [
|
|
1141
1103
|
`Full access to ${product}`,
|
|
1142
1104
|
`$${includedUsageUsd}/mo of AI usage included, every month`
|
|
1143
|
-
]).map((benefit, i) => /* @__PURE__ */
|
|
1144
|
-
/* @__PURE__ */
|
|
1105
|
+
]).map((benefit, i) => /* @__PURE__ */ jsx6(Benefit, { children: benefit }, i)) }),
|
|
1106
|
+
/* @__PURE__ */ jsx6(
|
|
1145
1107
|
"button",
|
|
1146
1108
|
{
|
|
1147
1109
|
type: "button",
|
|
@@ -1151,13 +1113,13 @@ function SeatPaywall({
|
|
|
1151
1113
|
children: pending ? "Opening checkout\u2026" : ctaLabel ?? `Unlock ${product}`
|
|
1152
1114
|
}
|
|
1153
1115
|
),
|
|
1154
|
-
footnote && /* @__PURE__ */
|
|
1116
|
+
footnote && /* @__PURE__ */ jsx6("p", { className: "mt-3 text-center text-xs text-muted-foreground/70", children: footnote })
|
|
1155
1117
|
] }) });
|
|
1156
1118
|
}
|
|
1157
1119
|
|
|
1158
1120
|
// src/web-react/agent-session-controls.tsx
|
|
1159
|
-
import { useMemo as useMemo2, useState as
|
|
1160
|
-
import { jsx as
|
|
1121
|
+
import { useMemo as useMemo2, useState as useState5 } from "react";
|
|
1122
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1161
1123
|
var HARNESS_LABELS = {
|
|
1162
1124
|
opencode: "OpenCode (any model)",
|
|
1163
1125
|
"claude-code": "Claude Code (Anthropic)",
|
|
@@ -1177,12 +1139,12 @@ function harnessLabel(h) {
|
|
|
1177
1139
|
return HARNESS_LABELS[h] ?? h;
|
|
1178
1140
|
}
|
|
1179
1141
|
function ChevronDown2({ className }) {
|
|
1180
|
-
return /* @__PURE__ */
|
|
1142
|
+
return /* @__PURE__ */ jsx7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx7("path", { d: "m6 9 6 6 6-6" }) });
|
|
1181
1143
|
}
|
|
1182
1144
|
function GearGlyph({ className }) {
|
|
1183
1145
|
return /* @__PURE__ */ jsxs6("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1184
|
-
/* @__PURE__ */
|
|
1185
|
-
/* @__PURE__ */
|
|
1146
|
+
/* @__PURE__ */ jsx7("circle", { cx: "12", cy: "12", r: "3" }),
|
|
1147
|
+
/* @__PURE__ */ jsx7("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z" })
|
|
1186
1148
|
] });
|
|
1187
1149
|
}
|
|
1188
1150
|
var FOCUS_RING = "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background";
|
|
@@ -1191,7 +1153,7 @@ function HarnessPicker({
|
|
|
1191
1153
|
onChange,
|
|
1192
1154
|
available
|
|
1193
1155
|
}) {
|
|
1194
|
-
const [open, setOpen] =
|
|
1156
|
+
const [open, setOpen] = useState5(false);
|
|
1195
1157
|
const { containerRef, triggerProps } = usePopover(open, setOpen);
|
|
1196
1158
|
const options = available ?? Object.keys(HARNESS_LABELS);
|
|
1197
1159
|
return /* @__PURE__ */ jsxs6("div", { ref: containerRef, className: "relative inline-flex", children: [
|
|
@@ -1204,12 +1166,12 @@ function HarnessPicker({
|
|
|
1204
1166
|
title: "Agent backend",
|
|
1205
1167
|
className: `inline-flex w-full items-center justify-between gap-1.5 rounded-lg border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent/30 ${FOCUS_RING}`,
|
|
1206
1168
|
children: [
|
|
1207
|
-
/* @__PURE__ */
|
|
1208
|
-
/* @__PURE__ */
|
|
1169
|
+
/* @__PURE__ */ jsx7("span", { className: "truncate", children: harnessLabel(value) }),
|
|
1170
|
+
/* @__PURE__ */ jsx7(ChevronDown2, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
1209
1171
|
]
|
|
1210
1172
|
}
|
|
1211
1173
|
),
|
|
1212
|
-
open && /* @__PURE__ */
|
|
1174
|
+
open && /* @__PURE__ */ jsx7("div", { role: "menu", className: "absolute bottom-full left-0 z-50 mb-2 max-h-64 w-full min-w-[220px] overflow-y-auto rounded-xl border border-border bg-card p-1 shadow-lg", children: options.map((h) => /* @__PURE__ */ jsx7(
|
|
1213
1175
|
"button",
|
|
1214
1176
|
{
|
|
1215
1177
|
type: "button",
|
|
@@ -1256,11 +1218,11 @@ function AgentSessionControls(props) {
|
|
|
1256
1218
|
className
|
|
1257
1219
|
} = props;
|
|
1258
1220
|
const { onModel, onHarness } = useCoherentHandlers(props);
|
|
1259
|
-
const [open, setOpen] =
|
|
1221
|
+
const [open, setOpen] = useState5(false);
|
|
1260
1222
|
const { containerRef: popoverRef, triggerProps } = usePopover(open, setOpen);
|
|
1261
1223
|
const selectedModel = models.find((m) => m.id === model);
|
|
1262
1224
|
const showEffort = selectedModel?.supportsReasoning ?? true;
|
|
1263
|
-
const modelPicker = /* @__PURE__ */
|
|
1225
|
+
const modelPicker = /* @__PURE__ */ jsx7(
|
|
1264
1226
|
ModelPicker,
|
|
1265
1227
|
{
|
|
1266
1228
|
value: model,
|
|
@@ -1273,15 +1235,15 @@ function AgentSessionControls(props) {
|
|
|
1273
1235
|
if (layout === "inline") {
|
|
1274
1236
|
return /* @__PURE__ */ jsxs6("div", { className: `flex items-center gap-1.5 ${className ?? ""}`, children: [
|
|
1275
1237
|
modelPicker,
|
|
1276
|
-
showHarness && /* @__PURE__ */
|
|
1277
|
-
showEffort && /* @__PURE__ */
|
|
1238
|
+
showHarness && /* @__PURE__ */ jsx7(HarnessPicker, { value: harness, onChange: onHarness, available: availableHarnesses }),
|
|
1239
|
+
showEffort && /* @__PURE__ */ jsx7(EffortPicker, { value: effort, onChange: onEffortChange })
|
|
1278
1240
|
] });
|
|
1279
1241
|
}
|
|
1280
1242
|
const hasAdvanced = showHarness || showEffort;
|
|
1281
1243
|
return /* @__PURE__ */ jsxs6("div", { className: `flex items-center gap-1.5 ${className ?? ""}`, children: [
|
|
1282
1244
|
modelPicker,
|
|
1283
1245
|
hasAdvanced && /* @__PURE__ */ jsxs6("div", { ref: popoverRef, className: "relative inline-flex", children: [
|
|
1284
|
-
/* @__PURE__ */
|
|
1246
|
+
/* @__PURE__ */ jsx7(
|
|
1285
1247
|
"button",
|
|
1286
1248
|
{
|
|
1287
1249
|
type: "button",
|
|
@@ -1290,19 +1252,19 @@ function AgentSessionControls(props) {
|
|
|
1290
1252
|
title: "Model settings \u2014 pick the agent backend and how hard it thinks",
|
|
1291
1253
|
className: `flex h-8 w-8 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground data-[state=open]:bg-muted ${FOCUS_RING}`,
|
|
1292
1254
|
"data-state": open ? "open" : "closed",
|
|
1293
|
-
children: /* @__PURE__ */
|
|
1255
|
+
children: /* @__PURE__ */ jsx7(GearGlyph, { className: "h-4 w-4" })
|
|
1294
1256
|
}
|
|
1295
1257
|
),
|
|
1296
1258
|
open && /* @__PURE__ */ jsxs6("div", { className: "absolute bottom-full left-0 z-50 mb-2 w-72 space-y-3 rounded-xl border border-border bg-card p-3 shadow-lg", children: [
|
|
1297
1259
|
showHarness && /* @__PURE__ */ jsxs6("div", { className: "space-y-1.5", children: [
|
|
1298
|
-
/* @__PURE__ */
|
|
1299
|
-
/* @__PURE__ */
|
|
1300
|
-
/* @__PURE__ */
|
|
1260
|
+
/* @__PURE__ */ jsx7("p", { className: "text-xs font-medium text-foreground", children: "Agent backend" }),
|
|
1261
|
+
/* @__PURE__ */ jsx7(HarnessPicker, { value: harness, onChange: onHarness, available: availableHarnesses }),
|
|
1262
|
+
/* @__PURE__ */ jsx7("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "The engine that runs the agent. Switching it keeps your model choice compatible." })
|
|
1301
1263
|
] }),
|
|
1302
1264
|
showEffort && /* @__PURE__ */ jsxs6("div", { className: "space-y-1.5", children: [
|
|
1303
|
-
/* @__PURE__ */
|
|
1304
|
-
/* @__PURE__ */
|
|
1305
|
-
/* @__PURE__ */
|
|
1265
|
+
/* @__PURE__ */ jsx7("p", { className: "text-xs font-medium text-foreground", children: "Thinking" }),
|
|
1266
|
+
/* @__PURE__ */ jsx7(EffortPicker, { value: effort, onChange: onEffortChange, label: "" }),
|
|
1267
|
+
/* @__PURE__ */ jsx7("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "How hard the agent thinks before answering. Higher is slower but more thorough." })
|
|
1306
1268
|
] })
|
|
1307
1269
|
] })
|
|
1308
1270
|
] })
|
|
@@ -1310,7 +1272,7 @@ function AgentSessionControls(props) {
|
|
|
1310
1272
|
}
|
|
1311
1273
|
|
|
1312
1274
|
// src/web-react/index.tsx
|
|
1313
|
-
import { Fragment as Fragment4, jsx as
|
|
1275
|
+
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1314
1276
|
function formatModelCost(msg, models) {
|
|
1315
1277
|
if (msg.promptTokens == null && msg.completionTokens == null) return null;
|
|
1316
1278
|
const pricing = models.find((m) => m.id === msg.modelUsed)?.pricing;
|
|
@@ -1326,39 +1288,39 @@ function formatTokensPerSecond(msg) {
|
|
|
1326
1288
|
function RunDrillIn({ run, onClose }) {
|
|
1327
1289
|
return /* @__PURE__ */ jsxs7("div", { className: "fixed inset-y-0 right-0 z-50 flex w-[480px] max-w-full flex-col border-l border-border bg-card shadow-xl", children: [
|
|
1328
1290
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
|
|
1329
|
-
/* @__PURE__ */
|
|
1291
|
+
/* @__PURE__ */ jsx8(
|
|
1330
1292
|
"span",
|
|
1331
1293
|
{
|
|
1332
1294
|
className: `h-2 w-2 shrink-0 rounded-full ${run.status === "running" ? "bg-warning" : run.status === "error" ? "bg-destructive" : "bg-success"}`
|
|
1333
1295
|
}
|
|
1334
1296
|
),
|
|
1335
1297
|
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
|
|
1336
|
-
/* @__PURE__ */
|
|
1337
|
-
/* @__PURE__ */
|
|
1298
|
+
/* @__PURE__ */ jsx8("p", { className: "truncate text-sm font-semibold", children: run.title }),
|
|
1299
|
+
/* @__PURE__ */ jsx8("p", { className: "truncate font-mono text-[11px] text-muted-foreground", children: run.toolName })
|
|
1338
1300
|
] }),
|
|
1339
|
-
/* @__PURE__ */
|
|
1301
|
+
/* @__PURE__ */ jsx8(
|
|
1340
1302
|
"button",
|
|
1341
1303
|
{
|
|
1342
1304
|
type: "button",
|
|
1343
1305
|
onClick: onClose,
|
|
1344
1306
|
"aria-label": "Close",
|
|
1345
1307
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent/30 hover:text-foreground",
|
|
1346
|
-
children: /* @__PURE__ */
|
|
1308
|
+
children: /* @__PURE__ */ jsx8("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx8("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
1347
1309
|
}
|
|
1348
1310
|
)
|
|
1349
1311
|
] }),
|
|
1350
1312
|
/* @__PURE__ */ jsxs7("div", { className: "flex-1 space-y-3 overflow-y-auto p-4", children: [
|
|
1351
|
-
run.steps.length === 0 && /* @__PURE__ */
|
|
1313
|
+
run.steps.length === 0 && /* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground", children: "No steps recorded yet." }),
|
|
1352
1314
|
run.steps.map((step, i) => /* @__PURE__ */ jsxs7("div", { className: "rounded-lg border border-border/60 bg-background", children: [
|
|
1353
1315
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-baseline gap-2 border-b border-border/40 px-3 py-1.5", children: [
|
|
1354
|
-
/* @__PURE__ */
|
|
1355
|
-
/* @__PURE__ */
|
|
1356
|
-
/* @__PURE__ */
|
|
1316
|
+
/* @__PURE__ */ jsx8("span", { className: `font-mono text-[11px] ${step.status === "error" ? "text-destructive" : "text-muted-foreground"}`, children: step.status === "error" ? "\u2717" : "$" }),
|
|
1317
|
+
/* @__PURE__ */ jsx8("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: step.label }),
|
|
1318
|
+
/* @__PURE__ */ jsx8("span", { className: "shrink-0 text-[10px] text-muted-foreground", children: new Date(step.at).toLocaleTimeString() })
|
|
1357
1319
|
] }),
|
|
1358
|
-
step.detail && /* @__PURE__ */
|
|
1320
|
+
step.detail && /* @__PURE__ */ jsx8("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap px-3 py-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: step.detail })
|
|
1359
1321
|
] }, i))
|
|
1360
1322
|
] }),
|
|
1361
|
-
/* @__PURE__ */
|
|
1323
|
+
/* @__PURE__ */ jsx8("p", { className: "border-t border-border px-4 py-2 text-[11px] text-muted-foreground", children: "Readonly drill-in. Follow up in the main chat." })
|
|
1362
1324
|
] });
|
|
1363
1325
|
}
|
|
1364
1326
|
function pendingApprovalOf(call) {
|
|
@@ -1373,19 +1335,19 @@ function ChatEmptyState({
|
|
|
1373
1335
|
doors
|
|
1374
1336
|
}) {
|
|
1375
1337
|
return /* @__PURE__ */ jsxs7("div", { className: "mx-auto flex w-full max-w-2xl flex-col items-center px-6 py-12 text-center sm:py-20", children: [
|
|
1376
|
-
/* @__PURE__ */
|
|
1377
|
-
/* @__PURE__ */
|
|
1378
|
-
/* @__PURE__ */
|
|
1379
|
-
subline && /* @__PURE__ */
|
|
1380
|
-
doors && doors.length > 0 && /* @__PURE__ */
|
|
1338
|
+
/* @__PURE__ */ jsx8("span", { className: "mb-5 inline-flex h-14 w-14 items-center justify-center rounded-2xl bg-primary/10 ring-1 ring-primary/15", children: /* @__PURE__ */ jsx8(BrandMark, { size: 32, className: "shrink-0" }) }),
|
|
1339
|
+
/* @__PURE__ */ jsx8("p", { className: "text-[11px] font-semibold uppercase tracking-[0.18em] text-muted-foreground", children: productName }),
|
|
1340
|
+
/* @__PURE__ */ jsx8("h2", { className: "mt-1.5 text-balance text-2xl font-semibold leading-tight text-foreground sm:text-[28px]", children: headline }),
|
|
1341
|
+
subline && /* @__PURE__ */ jsx8("p", { className: "mt-3 max-w-md text-[15px] leading-relaxed text-muted-foreground", children: subline }),
|
|
1342
|
+
doors && doors.length > 0 && /* @__PURE__ */ jsx8("div", { className: "mt-7 grid w-full gap-2.5 sm:grid-cols-3", children: doors.slice(0, 3).map((door, i) => /* @__PURE__ */ jsxs7(
|
|
1381
1343
|
"button",
|
|
1382
1344
|
{
|
|
1383
1345
|
type: "button",
|
|
1384
1346
|
onClick: door.onSelect,
|
|
1385
1347
|
className: "group flex min-h-[44px] flex-col items-start rounded-xl border border-border bg-card px-4 py-3 text-left transition hover:border-primary/40 hover:bg-accent/30 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
1386
1348
|
children: [
|
|
1387
|
-
/* @__PURE__ */
|
|
1388
|
-
door.description && /* @__PURE__ */
|
|
1349
|
+
/* @__PURE__ */ jsx8("span", { className: "text-sm font-semibold text-foreground", children: door.label }),
|
|
1350
|
+
door.description && /* @__PURE__ */ jsx8("span", { className: "mt-0.5 text-[12px] leading-snug text-muted-foreground", children: door.description })
|
|
1389
1351
|
]
|
|
1390
1352
|
},
|
|
1391
1353
|
i
|
|
@@ -1395,25 +1357,25 @@ function ChatEmptyState({
|
|
|
1395
1357
|
function ToolGlyph({ name, className }) {
|
|
1396
1358
|
if (name.startsWith("sandbox_")) {
|
|
1397
1359
|
return /* @__PURE__ */ jsxs7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1398
|
-
/* @__PURE__ */
|
|
1399
|
-
/* @__PURE__ */
|
|
1360
|
+
/* @__PURE__ */ jsx8("polyline", { points: "4 17 10 11 4 5" }),
|
|
1361
|
+
/* @__PURE__ */ jsx8("line", { x1: "12", y1: "19", x2: "20", y2: "19" })
|
|
1400
1362
|
] });
|
|
1401
1363
|
}
|
|
1402
1364
|
if (name === "submit_proposal") {
|
|
1403
1365
|
return /* @__PURE__ */ jsxs7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1404
|
-
/* @__PURE__ */
|
|
1405
|
-
/* @__PURE__ */
|
|
1366
|
+
/* @__PURE__ */ jsx8("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
1367
|
+
/* @__PURE__ */ jsx8("path", { d: "M14 2v6h6M9 15l2 2 4-4" })
|
|
1406
1368
|
] });
|
|
1407
1369
|
}
|
|
1408
1370
|
if (name === "schedule_followup") {
|
|
1409
1371
|
return /* @__PURE__ */ jsxs7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: [
|
|
1410
|
-
/* @__PURE__ */
|
|
1411
|
-
/* @__PURE__ */
|
|
1372
|
+
/* @__PURE__ */ jsx8("circle", { cx: "12", cy: "12", r: "9" }),
|
|
1373
|
+
/* @__PURE__ */ jsx8("path", { d: "M12 7v5l3 3" })
|
|
1412
1374
|
] });
|
|
1413
1375
|
}
|
|
1414
1376
|
return /* @__PURE__ */ jsxs7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1415
|
-
/* @__PURE__ */
|
|
1416
|
-
/* @__PURE__ */
|
|
1377
|
+
/* @__PURE__ */ jsx8("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3" }),
|
|
1378
|
+
/* @__PURE__ */ jsx8("circle", { cx: "12", cy: "12", r: "4" })
|
|
1417
1379
|
] });
|
|
1418
1380
|
}
|
|
1419
1381
|
function toolOutcomeOf(call) {
|
|
@@ -1480,9 +1442,9 @@ function truncate(v, max = 240) {
|
|
|
1480
1442
|
function KvRows({ data }) {
|
|
1481
1443
|
const entries = Object.entries(data).filter(([, v]) => v !== void 0 && v !== null && v !== "");
|
|
1482
1444
|
if (!entries.length) return null;
|
|
1483
|
-
return /* @__PURE__ */
|
|
1484
|
-
/* @__PURE__ */
|
|
1485
|
-
/* @__PURE__ */
|
|
1445
|
+
return /* @__PURE__ */ jsx8("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: entries.map(([k, v]) => /* @__PURE__ */ jsxs7("div", { className: "contents", children: [
|
|
1446
|
+
/* @__PURE__ */ jsx8("dt", { className: "font-mono text-[11px] text-muted-foreground", children: k }),
|
|
1447
|
+
/* @__PURE__ */ jsx8("dd", { className: "min-w-0 whitespace-pre-wrap break-words font-mono text-[11px] text-muted-foreground", children: truncate(v) })
|
|
1486
1448
|
] }, k)) });
|
|
1487
1449
|
}
|
|
1488
1450
|
function ShellDetail({ call }) {
|
|
@@ -1490,26 +1452,26 @@ function ShellDetail({ call }) {
|
|
|
1490
1452
|
const r = outcome?.result ?? {};
|
|
1491
1453
|
return /* @__PURE__ */ jsxs7("div", { className: "overflow-hidden rounded-md bg-zinc-900 font-mono text-[11px] leading-relaxed", children: [
|
|
1492
1454
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 px-3 pt-2 text-zinc-400", children: [
|
|
1493
|
-
/* @__PURE__ */
|
|
1494
|
-
/* @__PURE__ */
|
|
1455
|
+
/* @__PURE__ */ jsx8("span", { className: "select-none text-zinc-500", children: "$" }),
|
|
1456
|
+
/* @__PURE__ */ jsx8("span", { className: "min-w-0 flex-1 truncate text-zinc-200", children: String(call.args?.command ?? "") }),
|
|
1495
1457
|
r.exitCode != null && /* @__PURE__ */ jsxs7("span", { className: r.exitCode === 0 ? "text-success" : "text-destructive", children: [
|
|
1496
1458
|
"exit ",
|
|
1497
1459
|
r.exitCode
|
|
1498
1460
|
] })
|
|
1499
1461
|
] }),
|
|
1500
|
-
/* @__PURE__ */
|
|
1462
|
+
/* @__PURE__ */ jsx8("pre", { className: "max-h-56 overflow-auto whitespace-pre-wrap px-3 pb-2.5 pt-1.5 text-zinc-300", children: outcome?.ok === false ? outcome.message ?? "failed" : [r.stdout, r.stderr].filter(Boolean).join("\n") || "(no output)" })
|
|
1501
1463
|
] });
|
|
1502
1464
|
}
|
|
1503
1465
|
function DefaultToolDetail({ call }) {
|
|
1504
1466
|
const outcome = toolOutcomeOf(call);
|
|
1505
1467
|
return /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
|
|
1506
1468
|
call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */ jsxs7("div", { children: [
|
|
1507
|
-
/* @__PURE__ */
|
|
1508
|
-
/* @__PURE__ */
|
|
1469
|
+
/* @__PURE__ */ jsx8("p", { className: "mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground", children: "Called with" }),
|
|
1470
|
+
/* @__PURE__ */ jsx8(KvRows, { data: call.args })
|
|
1509
1471
|
] }),
|
|
1510
1472
|
outcome && /* @__PURE__ */ jsxs7("div", { children: [
|
|
1511
|
-
/* @__PURE__ */
|
|
1512
|
-
outcome.ok === false ? /* @__PURE__ */
|
|
1473
|
+
/* @__PURE__ */ jsx8("p", { className: "mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground", children: outcome.ok === false ? "Failed" : "Result" }),
|
|
1474
|
+
outcome.ok === false ? /* @__PURE__ */ jsx8("p", { className: "text-xs text-destructive", children: outcome.message ?? "Tool failed" }) : outcome.result && typeof outcome.result === "object" ? /* @__PURE__ */ jsx8(KvRows, { data: outcome.result }) : /* @__PURE__ */ jsx8("p", { className: "font-mono text-[11px] text-muted-foreground", children: truncate(outcome.result) })
|
|
1513
1475
|
] })
|
|
1514
1476
|
] });
|
|
1515
1477
|
}
|
|
@@ -1520,23 +1482,23 @@ function ProposalCard({
|
|
|
1520
1482
|
approval,
|
|
1521
1483
|
renderers
|
|
1522
1484
|
}) {
|
|
1523
|
-
const [expanded, setExpanded] =
|
|
1485
|
+
const [expanded, setExpanded] = useState6(false);
|
|
1524
1486
|
const { summary, meta } = proposalPreview(call);
|
|
1525
1487
|
const custom = renderers?.[call.name]?.(call, message);
|
|
1526
1488
|
const { pending: deciding, run: decide } = usePending();
|
|
1527
1489
|
return /* @__PURE__ */ jsxs7("div", { className: "w-full max-w-full rounded-xl border border-warning/50 bg-warning/[0.06] text-sm shadow-sm ring-1 ring-warning/10", children: [
|
|
1528
1490
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-start gap-2.5 px-4 pt-3.5", children: [
|
|
1529
|
-
/* @__PURE__ */
|
|
1491
|
+
/* @__PURE__ */ jsx8("span", { className: "mt-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-warning/15 text-warning", children: /* @__PURE__ */ jsx8(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
|
|
1530
1492
|
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
|
|
1531
|
-
/* @__PURE__ */
|
|
1532
|
-
/* @__PURE__ */
|
|
1533
|
-
summary && /* @__PURE__ */
|
|
1534
|
-
meta.length > 0 && /* @__PURE__ */
|
|
1493
|
+
/* @__PURE__ */ jsx8("p", { className: "text-[10px] font-semibold uppercase tracking-wider text-warning-foreground", children: "Needs your approval" }),
|
|
1494
|
+
/* @__PURE__ */ jsx8("p", { className: "mt-0.5 text-[15px] font-semibold leading-snug text-foreground", children: friendlyToolTitle(call) }),
|
|
1495
|
+
summary && /* @__PURE__ */ jsx8("p", { className: "mt-1 text-[13px] leading-relaxed text-muted-foreground", children: summary }),
|
|
1496
|
+
meta.length > 0 && /* @__PURE__ */ jsx8("div", { className: "mt-1.5 flex flex-wrap items-center gap-1.5", children: meta.map((m, i) => /* @__PURE__ */ jsx8("span", { className: "rounded-full bg-muted/60 px-2 py-0.5 text-[11px] font-medium text-muted-foreground", children: m }, i)) })
|
|
1535
1497
|
] })
|
|
1536
1498
|
] }),
|
|
1537
1499
|
/* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap items-center gap-2 px-4 pb-3.5 pt-3", children: [
|
|
1538
1500
|
approval ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1539
|
-
/* @__PURE__ */
|
|
1501
|
+
/* @__PURE__ */ jsx8(
|
|
1540
1502
|
"button",
|
|
1541
1503
|
{
|
|
1542
1504
|
type: "button",
|
|
@@ -1546,7 +1508,7 @@ function ProposalCard({
|
|
|
1546
1508
|
children: "Approve & run"
|
|
1547
1509
|
}
|
|
1548
1510
|
),
|
|
1549
|
-
/* @__PURE__ */
|
|
1511
|
+
/* @__PURE__ */ jsx8(
|
|
1550
1512
|
"button",
|
|
1551
1513
|
{
|
|
1552
1514
|
type: "button",
|
|
@@ -1556,7 +1518,7 @@ function ProposalCard({
|
|
|
1556
1518
|
children: "Reject"
|
|
1557
1519
|
}
|
|
1558
1520
|
)
|
|
1559
|
-
] }) : /* @__PURE__ */
|
|
1521
|
+
] }) : /* @__PURE__ */ jsx8("span", { className: "text-[12px] font-medium text-muted-foreground", children: "Awaiting approval\u2026" }),
|
|
1560
1522
|
/* @__PURE__ */ jsxs7(
|
|
1561
1523
|
"button",
|
|
1562
1524
|
{
|
|
@@ -1566,12 +1528,12 @@ function ProposalCard({
|
|
|
1566
1528
|
className: "ml-auto inline-flex items-center gap-1 rounded text-[12px] font-medium text-muted-foreground transition hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
1567
1529
|
children: [
|
|
1568
1530
|
expanded ? "Hide details" : "View details",
|
|
1569
|
-
/* @__PURE__ */
|
|
1531
|
+
/* @__PURE__ */ jsx8(ChevronDown, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` })
|
|
1570
1532
|
]
|
|
1571
1533
|
}
|
|
1572
1534
|
)
|
|
1573
1535
|
] }),
|
|
1574
|
-
expanded && /* @__PURE__ */
|
|
1536
|
+
expanded && /* @__PURE__ */ jsx8("div", { className: "border-t border-warning/20 px-4 py-3 text-xs", children: custom ?? /* @__PURE__ */ jsx8(DefaultToolDetail, { call }) })
|
|
1575
1537
|
] });
|
|
1576
1538
|
}
|
|
1577
1539
|
function FollowupCard({ call }) {
|
|
@@ -1579,10 +1541,10 @@ function FollowupCard({ call }) {
|
|
|
1579
1541
|
const when = typeof a.when === "string" ? a.when : typeof a.at === "string" ? a.at : typeof a.schedule === "string" ? a.schedule : null;
|
|
1580
1542
|
return /* @__PURE__ */ jsxs7("div", { className: "w-fit min-w-[260px] max-w-full rounded-lg border border-border/60 border-l-2 border-l-primary/60 bg-muted/20 px-3 py-2 text-sm", children: [
|
|
1581
1543
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
|
|
1582
|
-
/* @__PURE__ */
|
|
1583
|
-
/* @__PURE__ */
|
|
1544
|
+
/* @__PURE__ */ jsx8(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5 shrink-0 text-primary/80" }),
|
|
1545
|
+
/* @__PURE__ */ jsx8("span", { className: "min-w-0 flex-1 truncate font-medium text-foreground", children: friendlyToolTitle(call) })
|
|
1584
1546
|
] }),
|
|
1585
|
-
when && /* @__PURE__ */
|
|
1547
|
+
when && /* @__PURE__ */ jsx8("p", { className: "mt-0.5 pl-[22px] text-[12px] text-muted-foreground", children: when })
|
|
1586
1548
|
] });
|
|
1587
1549
|
}
|
|
1588
1550
|
function ToolCallCard({
|
|
@@ -1592,13 +1554,13 @@ function ToolCallCard({
|
|
|
1592
1554
|
onOpenRun,
|
|
1593
1555
|
renderers
|
|
1594
1556
|
}) {
|
|
1595
|
-
const [expanded, setExpanded] =
|
|
1557
|
+
const [expanded, setExpanded] = useState6(false);
|
|
1596
1558
|
const pending = call.status === "done" ? pendingApprovalOf(call) : null;
|
|
1597
1559
|
const kind = blockKindOf(call);
|
|
1598
1560
|
const failed = call.status === "error" || toolOutcomeOf(call)?.ok === false;
|
|
1599
1561
|
const custom = renderers?.[call.name]?.(call, message);
|
|
1600
1562
|
if (pending) {
|
|
1601
|
-
return /* @__PURE__ */
|
|
1563
|
+
return /* @__PURE__ */ jsx8(
|
|
1602
1564
|
ProposalCard,
|
|
1603
1565
|
{
|
|
1604
1566
|
call,
|
|
@@ -1610,7 +1572,7 @@ function ToolCallCard({
|
|
|
1610
1572
|
);
|
|
1611
1573
|
}
|
|
1612
1574
|
if (kind === "followup" && !failed) {
|
|
1613
|
-
return /* @__PURE__ */
|
|
1575
|
+
return /* @__PURE__ */ jsx8(FollowupCard, { call });
|
|
1614
1576
|
}
|
|
1615
1577
|
const isCommand = kind === "command";
|
|
1616
1578
|
return /* @__PURE__ */ jsxs7(
|
|
@@ -1627,14 +1589,14 @@ function ToolCallCard({
|
|
|
1627
1589
|
"aria-expanded": expanded,
|
|
1628
1590
|
className: "flex min-w-0 flex-1 items-center gap-2 rounded text-left focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
1629
1591
|
children: [
|
|
1630
|
-
/* @__PURE__ */
|
|
1592
|
+
/* @__PURE__ */ jsx8(
|
|
1631
1593
|
"span",
|
|
1632
1594
|
{
|
|
1633
1595
|
className: `h-2 w-2 shrink-0 rounded-full ${call.status === "running" ? "animate-pulse bg-warning" : failed ? "bg-destructive" : "bg-success"}`
|
|
1634
1596
|
}
|
|
1635
1597
|
),
|
|
1636
|
-
/* @__PURE__ */
|
|
1637
|
-
/* @__PURE__ */
|
|
1598
|
+
/* @__PURE__ */ jsx8(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
1599
|
+
/* @__PURE__ */ jsx8(
|
|
1638
1600
|
"span",
|
|
1639
1601
|
{
|
|
1640
1602
|
className: `min-w-0 flex-1 truncate ${isCommand ? "font-mono text-[12px] tracking-tight text-foreground/90" : "font-medium"}`,
|
|
@@ -1644,8 +1606,8 @@ function ToolCallCard({
|
|
|
1644
1606
|
]
|
|
1645
1607
|
}
|
|
1646
1608
|
),
|
|
1647
|
-
/* @__PURE__ */
|
|
1648
|
-
/* @__PURE__ */
|
|
1609
|
+
/* @__PURE__ */ jsx8("span", { className: "shrink-0 text-[11px] text-muted-foreground", children: call.status === "running" ? "running\u2026" : failed ? "failed" : "done" }),
|
|
1610
|
+
/* @__PURE__ */ jsx8(
|
|
1649
1611
|
"button",
|
|
1650
1612
|
{
|
|
1651
1613
|
type: "button",
|
|
@@ -1653,13 +1615,13 @@ function ToolCallCard({
|
|
|
1653
1615
|
"aria-label": expanded ? "Collapse details" : "Expand details",
|
|
1654
1616
|
"aria-expanded": expanded,
|
|
1655
1617
|
className: "shrink-0 rounded p-0.5 focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
1656
|
-
children: /* @__PURE__ */
|
|
1618
|
+
children: /* @__PURE__ */ jsx8(ChevronDown, { className: `h-3 w-3 text-muted-foreground transition-transform ${expanded ? "rotate-180" : ""}` })
|
|
1657
1619
|
}
|
|
1658
1620
|
)
|
|
1659
1621
|
] }),
|
|
1660
1622
|
expanded && /* @__PURE__ */ jsxs7("div", { className: "border-t border-border/40 px-3 py-2.5", children: [
|
|
1661
|
-
custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */
|
|
1662
|
-
onOpenRun && call.name.startsWith("sandbox_") && /* @__PURE__ */
|
|
1623
|
+
custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */ jsx8(ShellDetail, { call }) : /* @__PURE__ */ jsx8(DefaultToolDetail, { call })),
|
|
1624
|
+
onOpenRun && call.name.startsWith("sandbox_") && /* @__PURE__ */ jsx8(
|
|
1663
1625
|
"button",
|
|
1664
1626
|
{
|
|
1665
1627
|
type: "button",
|
|
@@ -1674,7 +1636,7 @@ function ToolCallCard({
|
|
|
1674
1636
|
);
|
|
1675
1637
|
}
|
|
1676
1638
|
function StreamingCaret() {
|
|
1677
|
-
return /* @__PURE__ */
|
|
1639
|
+
return /* @__PURE__ */ jsx8(
|
|
1678
1640
|
"span",
|
|
1679
1641
|
{
|
|
1680
1642
|
className: "ml-0.5 inline-block h-[1.1em] w-[3px] translate-y-[2px] animate-pulse rounded-sm bg-foreground/70",
|
|
@@ -1693,7 +1655,7 @@ function SegmentText({
|
|
|
1693
1655
|
if (!content.trim() && !showCaret) return null;
|
|
1694
1656
|
return /* @__PURE__ */ jsxs7("div", { className: "text-base leading-[1.75]", children: [
|
|
1695
1657
|
body,
|
|
1696
|
-
showCaret && /* @__PURE__ */
|
|
1658
|
+
showCaret && /* @__PURE__ */ jsx8(StreamingCaret, {})
|
|
1697
1659
|
] });
|
|
1698
1660
|
}
|
|
1699
1661
|
function SegmentedBody({
|
|
@@ -1712,7 +1674,7 @@ function SegmentedBody({
|
|
|
1712
1674
|
const leftoverToolCalls = (msg.toolCalls ?? []).filter(
|
|
1713
1675
|
(tc) => !segmentToolIds.has(tc.id)
|
|
1714
1676
|
);
|
|
1715
|
-
const renderToolCard = (call) => /* @__PURE__ */
|
|
1677
|
+
const renderToolCard = (call) => /* @__PURE__ */ jsx8(
|
|
1716
1678
|
ToolCallCard,
|
|
1717
1679
|
{
|
|
1718
1680
|
call,
|
|
@@ -1725,7 +1687,7 @@ function SegmentedBody({
|
|
|
1725
1687
|
);
|
|
1726
1688
|
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-2", children: [
|
|
1727
1689
|
segments.map(
|
|
1728
|
-
(seg, i) => seg.kind === "text" ? /* @__PURE__ */
|
|
1690
|
+
(seg, i) => seg.kind === "text" ? /* @__PURE__ */ jsx8(
|
|
1729
1691
|
SegmentText,
|
|
1730
1692
|
{
|
|
1731
1693
|
content: seg.content,
|
|
@@ -1737,7 +1699,7 @@ function SegmentedBody({
|
|
|
1737
1699
|
) : renderToolCard(seg.call)
|
|
1738
1700
|
),
|
|
1739
1701
|
leftoverToolCalls.map(renderToolCard),
|
|
1740
|
-
streaming && segments[lastIndex]?.kind === "tool" && /* @__PURE__ */
|
|
1702
|
+
streaming && segments[lastIndex]?.kind === "tool" && /* @__PURE__ */ jsx8(StreamingCaret, {})
|
|
1741
1703
|
] });
|
|
1742
1704
|
}
|
|
1743
1705
|
function AssistantMessageImpl({
|
|
@@ -1774,19 +1736,19 @@ function AssistantMessageImpl({
|
|
|
1774
1736
|
);
|
|
1775
1737
|
return /* @__PURE__ */ jsxs7("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
|
|
1776
1738
|
/* @__PURE__ */ jsxs7("div", { className: "mb-1 flex items-baseline gap-2 text-[11px] tracking-wide text-muted-foreground", children: [
|
|
1777
|
-
/* @__PURE__ */
|
|
1778
|
-
msg.modelUsed && /* @__PURE__ */
|
|
1779
|
-
formatTokensPerSecond(msg) && /* @__PURE__ */
|
|
1780
|
-
formatModelCost(msg, models) && /* @__PURE__ */
|
|
1739
|
+
/* @__PURE__ */ jsx8("span", { className: "font-semibold uppercase", children: agentLabel }),
|
|
1740
|
+
msg.modelUsed && /* @__PURE__ */ jsx8("span", { className: "font-mono normal-case", children: msg.modelUsed }),
|
|
1741
|
+
formatTokensPerSecond(msg) && /* @__PURE__ */ jsx8("span", { children: formatTokensPerSecond(msg) }),
|
|
1742
|
+
formatModelCost(msg, models) && /* @__PURE__ */ jsx8("span", { children: formatModelCost(msg, models) })
|
|
1781
1743
|
] }),
|
|
1782
1744
|
reasoning && /* @__PURE__ */ jsxs7("details", { className: "mb-2 rounded-lg border-l-2 border-border/70 bg-muted/20 px-3 py-2", open: !hasAnswerText, children: [
|
|
1783
|
-
/* @__PURE__ */
|
|
1745
|
+
/* @__PURE__ */ jsx8("summary", { className: "cursor-pointer select-none text-xs font-medium text-muted-foreground", children: !hasAnswerText ? /* @__PURE__ */ jsxs7("span", { className: "animate-pulse", children: [
|
|
1784
1746
|
"Thinking",
|
|
1785
1747
|
thinkingSeconds >= 3 ? ` \xB7 ${thinkingSeconds}s` : "\u2026"
|
|
1786
1748
|
] }) : thinkMsRef.current != null ? `Thought for ${Math.max(1, Math.round(thinkMsRef.current / 1e3))}s` : "Thought process" }),
|
|
1787
|
-
/* @__PURE__ */
|
|
1749
|
+
/* @__PURE__ */ jsx8("div", { ref: reasoningScrollRef, className: "mt-2 max-h-48 overflow-y-auto whitespace-pre-wrap text-[13px] leading-relaxed text-muted-foreground", children: reasoning })
|
|
1788
1750
|
] }),
|
|
1789
|
-
segments && segments.length > 0 ? /* @__PURE__ */
|
|
1751
|
+
segments && segments.length > 0 ? /* @__PURE__ */ jsx8(
|
|
1790
1752
|
SegmentedBody,
|
|
1791
1753
|
{
|
|
1792
1754
|
segments,
|
|
@@ -1800,9 +1762,9 @@ function AssistantMessageImpl({
|
|
|
1800
1762
|
) : /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1801
1763
|
/* @__PURE__ */ jsxs7("div", { className: "text-base leading-[1.75]", children: [
|
|
1802
1764
|
body,
|
|
1803
|
-
streaming && content && !msg.toolCalls?.length && /* @__PURE__ */
|
|
1765
|
+
streaming && content && !msg.toolCalls?.length && /* @__PURE__ */ jsx8(StreamingCaret, {})
|
|
1804
1766
|
] }),
|
|
1805
|
-
msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */
|
|
1767
|
+
msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx8("div", { className: "mt-2 flex flex-col gap-1.5", children: msg.toolCalls.map((tc) => /* @__PURE__ */ jsx8(
|
|
1806
1768
|
ToolCallCard,
|
|
1807
1769
|
{
|
|
1808
1770
|
call: tc,
|
|
@@ -1819,7 +1781,7 @@ function AssistantMessageImpl({
|
|
|
1819
1781
|
}
|
|
1820
1782
|
var AssistantMessage = memo(AssistantMessageImpl);
|
|
1821
1783
|
function useThinkingSeconds(active) {
|
|
1822
|
-
const [seconds, setSeconds] =
|
|
1784
|
+
const [seconds, setSeconds] = useState6(0);
|
|
1823
1785
|
useEffect5(() => {
|
|
1824
1786
|
if (!active) return;
|
|
1825
1787
|
setSeconds(0);
|
|
@@ -1831,22 +1793,22 @@ function useThinkingSeconds(active) {
|
|
|
1831
1793
|
function ThinkingRow({ agentLabel }) {
|
|
1832
1794
|
const seconds = useThinkingSeconds(true);
|
|
1833
1795
|
return /* @__PURE__ */ jsxs7("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
|
|
1834
|
-
/* @__PURE__ */
|
|
1796
|
+
/* @__PURE__ */ jsx8("p", { className: "mb-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: agentLabel }),
|
|
1835
1797
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 text-base text-muted-foreground", children: [
|
|
1836
|
-
/* @__PURE__ */
|
|
1798
|
+
/* @__PURE__ */ jsx8("svg", { className: "h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx8("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }),
|
|
1837
1799
|
"Thinking",
|
|
1838
1800
|
seconds >= 3 ? ` \xB7 ${seconds}s` : "..."
|
|
1839
1801
|
] })
|
|
1840
1802
|
] });
|
|
1841
1803
|
}
|
|
1842
1804
|
function StreamErrorRow({ message, onRetry }) {
|
|
1843
|
-
return /* @__PURE__ */
|
|
1805
|
+
return /* @__PURE__ */ jsx8("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs7("div", { role: "alert", className: "flex items-start gap-2.5 rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2.5 text-sm text-destructive", children: [
|
|
1844
1806
|
/* @__PURE__ */ jsxs7("svg", { className: "mt-0.5 h-4 w-4 shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1845
|
-
/* @__PURE__ */
|
|
1846
|
-
/* @__PURE__ */
|
|
1807
|
+
/* @__PURE__ */ jsx8("circle", { cx: "12", cy: "12", r: "9" }),
|
|
1808
|
+
/* @__PURE__ */ jsx8("path", { d: "M12 8v4m0 4h.01" })
|
|
1847
1809
|
] }),
|
|
1848
|
-
/* @__PURE__ */
|
|
1849
|
-
onRetry && /* @__PURE__ */
|
|
1810
|
+
/* @__PURE__ */ jsx8("span", { className: "min-w-0 flex-1 break-words", children: message }),
|
|
1811
|
+
onRetry && /* @__PURE__ */ jsx8(
|
|
1850
1812
|
"button",
|
|
1851
1813
|
{
|
|
1852
1814
|
type: "button",
|
|
@@ -1875,12 +1837,12 @@ function ChatMessages({
|
|
|
1875
1837
|
header
|
|
1876
1838
|
}) {
|
|
1877
1839
|
const renderBody = useMemo3(
|
|
1878
|
-
() => renderMarkdown ?? ((content) => /* @__PURE__ */
|
|
1840
|
+
() => renderMarkdown ?? ((content) => /* @__PURE__ */ jsx8("p", { className: "whitespace-pre-wrap", children: content })),
|
|
1879
1841
|
[renderMarkdown]
|
|
1880
1842
|
);
|
|
1881
1843
|
const lastIsUser = messages[messages.length - 1]?.role === "user";
|
|
1882
1844
|
if (messages.length === 0 && !loading && !error) {
|
|
1883
|
-
const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */
|
|
1845
|
+
const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */ jsx8(ChatEmptyState, { ...emptyState });
|
|
1884
1846
|
return /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1885
1847
|
header,
|
|
1886
1848
|
empty
|
|
@@ -1889,10 +1851,10 @@ function ChatMessages({
|
|
|
1889
1851
|
return /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1890
1852
|
header,
|
|
1891
1853
|
messages.map(
|
|
1892
|
-
(msg) => msg.role === "user" ? /* @__PURE__ */
|
|
1893
|
-
/* @__PURE__ */
|
|
1894
|
-
/* @__PURE__ */
|
|
1895
|
-
] }) }, msg.id) : /* @__PURE__ */
|
|
1854
|
+
(msg) => msg.role === "user" ? /* @__PURE__ */ jsx8("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs7("div", { className: "ml-auto w-fit max-w-[85%]", children: [
|
|
1855
|
+
/* @__PURE__ */ jsx8("p", { className: "mb-1 text-right text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: userLabel }),
|
|
1856
|
+
/* @__PURE__ */ jsx8("div", { className: "rounded-2xl rounded-tr-md bg-primary/10 px-4 py-2.5 text-base leading-relaxed", children: /* @__PURE__ */ jsx8("p", { className: "whitespace-pre-wrap", children: msg.content }) })
|
|
1857
|
+
] }) }, msg.id) : /* @__PURE__ */ jsx8(
|
|
1896
1858
|
AssistantMessage,
|
|
1897
1859
|
{
|
|
1898
1860
|
msg,
|
|
@@ -1908,8 +1870,8 @@ function ChatMessages({
|
|
|
1908
1870
|
msg.id
|
|
1909
1871
|
)
|
|
1910
1872
|
),
|
|
1911
|
-
loading && lastIsUser && /* @__PURE__ */
|
|
1912
|
-
error && !loading && /* @__PURE__ */
|
|
1873
|
+
loading && lastIsUser && /* @__PURE__ */ jsx8(ThinkingRow, { agentLabel }),
|
|
1874
|
+
error && !loading && /* @__PURE__ */ jsx8(StreamErrorRow, { message: error, onRetry })
|
|
1913
1875
|
] });
|
|
1914
1876
|
}
|
|
1915
1877
|
|
|
@@ -1934,9 +1896,6 @@ export {
|
|
|
1934
1896
|
FlowWaterfall,
|
|
1935
1897
|
MissionActivityLane,
|
|
1936
1898
|
AgentActivityPanel,
|
|
1937
|
-
useSandboxTerminalConnection,
|
|
1938
|
-
tabTerminalConnectionId,
|
|
1939
|
-
WorkspaceTerminalPanel,
|
|
1940
1899
|
SeatPaywall,
|
|
1941
1900
|
AgentSessionControls,
|
|
1942
1901
|
formatModelCost,
|
|
@@ -1947,4 +1906,4 @@ export {
|
|
|
1947
1906
|
useThinkingSeconds,
|
|
1948
1907
|
ChatMessages
|
|
1949
1908
|
};
|
|
1950
|
-
//# sourceMappingURL=chunk-
|
|
1909
|
+
//# sourceMappingURL=chunk-VKHB7VP4.js.map
|