@invergent/agent-chat-react 1.5.3 → 1.5.4
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/artifact-chart-X53FKRDZ.js +153 -0
- package/dist/artifact-chart-X53FKRDZ.js.map +1 -0
- package/dist/chunk-QSC4UIVT.js +11 -0
- package/dist/chunk-QSC4UIVT.js.map +1 -0
- package/dist/index.cjs +463 -172
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +210 -115
- package/dist/index.js.map +1 -1
- package/package.json +3 -6
- package/dist/artifact-chart-7J6GOR4M.js +0 -88
- package/dist/artifact-chart-7J6GOR4M.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { cn } from './chunk-QSC4UIVT.js';
|
|
1
2
|
import { createContext, memo, useRef, useState, useEffect, useCallback, useMemo, lazy, useContext, Suspense, Children } from 'react';
|
|
2
3
|
import { cva } from 'class-variance-authority';
|
|
3
4
|
import { Collapsible as Collapsible$1, Slot, Dialog as Dialog$1, ScrollArea as ScrollArea$1, Tooltip as Tooltip$1, Tabs as Tabs$1, Popover as Popover$1, DropdownMenu as DropdownMenu$1, HoverCard as HoverCard$1, Progress as Progress$1 } from 'radix-ui';
|
|
4
|
-
import { clsx } from 'clsx';
|
|
5
|
-
import { twMerge } from 'tailwind-merge';
|
|
6
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
6
|
import { ChevronDownIcon, AlertTriangle, ChevronDown, ChevronRight, RefreshCw, ChevronRightIcon, GitBranchIcon, XIcon, ThumbsUpIcon, ThumbsDownIcon, ActivityIcon, Loader2Icon, GlobeIcon, SearchIcon, ListTodoIcon, XCircleIcon, CheckCircle2Icon, Code, CheckIcon, CopyIcon, TerminalIcon, Trash2Icon, CircleDotIcon, CircleCheckIcon, CircleXIcon, SkullIcon, ClockIcon, CheckCircleIcon, CircleIcon, UsersIcon, MessageSquareIcon, FolderOpenIcon, UploadIcon, RefreshCwIcon, AlertCircleIcon, SquareIcon, ArrowDownIcon, DownloadIcon, TrashIcon, ImageIcon, FileTextIcon, Maximize2Icon, FolderIcon, FileIcon, ChevronLeftIcon, MinusIcon, PlusIcon, CornerDownLeftIcon } from 'lucide-react';
|
|
8
7
|
import { StickToBottom, useStickToBottomContext } from 'use-stick-to-bottom';
|
|
@@ -21,7 +20,6 @@ import { nanoid } from 'nanoid';
|
|
|
21
20
|
import 'pdfjs-dist/web/pdf_viewer.css';
|
|
22
21
|
import { formatDistanceToNow } from 'date-fns';
|
|
23
22
|
|
|
24
|
-
// src/agent-chat.tsx
|
|
25
23
|
var AgentChatAdapterContext = createContext(null);
|
|
26
24
|
var AgentChatAdapterProvider = AgentChatAdapterContext.Provider;
|
|
27
25
|
function useAgentChatAdapterContext() {
|
|
@@ -33,9 +31,6 @@ function useAgentChatAdapterContext() {
|
|
|
33
31
|
}
|
|
34
32
|
return value;
|
|
35
33
|
}
|
|
36
|
-
function cn(...inputs) {
|
|
37
|
-
return twMerge(clsx(inputs));
|
|
38
|
-
}
|
|
39
34
|
var buttonVariants = cva(
|
|
40
35
|
"group/button inline-flex shrink-0 items-center justify-center rounded-none border border-transparent bg-clip-padding text-xs font-semibold tracking-widest whitespace-nowrap uppercase transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
|
|
41
36
|
{
|
|
@@ -87,7 +82,7 @@ function Button({
|
|
|
87
82
|
var Conversation = ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
88
83
|
StickToBottom,
|
|
89
84
|
{
|
|
90
|
-
className: cn("relative flex-1
|
|
85
|
+
className: cn("relative flex-1", className),
|
|
91
86
|
initial: "smooth",
|
|
92
87
|
resize: "smooth",
|
|
93
88
|
role: "log",
|
|
@@ -570,6 +565,61 @@ function TimelineSeparator({
|
|
|
570
565
|
}
|
|
571
566
|
);
|
|
572
567
|
}
|
|
568
|
+
|
|
569
|
+
// src/components/chat/tools/shared.ts
|
|
570
|
+
function statusColorClass(status) {
|
|
571
|
+
if (status === "running") return "bg-primary animate-pulse";
|
|
572
|
+
if (status === "error") return "bg-red-500";
|
|
573
|
+
if (status === "cancelled") return "bg-muted-foreground/40";
|
|
574
|
+
return "bg-emerald-500";
|
|
575
|
+
}
|
|
576
|
+
function effectiveStatus(tc) {
|
|
577
|
+
if (tc.cancelled) return "cancelled";
|
|
578
|
+
if (tc.status !== "complete" || !tc.result) return tc.status;
|
|
579
|
+
try {
|
|
580
|
+
const parsed = JSON.parse(tc.result);
|
|
581
|
+
if (parsed?.exit_code !== void 0 && parsed.exit_code !== 0) return "error";
|
|
582
|
+
if (parsed?.error) return "error";
|
|
583
|
+
if (parsed?.status === "blocked" || parsed?.status === "error") return "error";
|
|
584
|
+
if (parsed?.success === false) return "error";
|
|
585
|
+
} catch {
|
|
586
|
+
}
|
|
587
|
+
return "complete";
|
|
588
|
+
}
|
|
589
|
+
function formatArgs(args) {
|
|
590
|
+
try {
|
|
591
|
+
return JSON.stringify(JSON.parse(args), null, 2);
|
|
592
|
+
} catch {
|
|
593
|
+
return args;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
function parseArgs(args) {
|
|
597
|
+
try {
|
|
598
|
+
return JSON.parse(args);
|
|
599
|
+
} catch {
|
|
600
|
+
return null;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
function truncate(s, max) {
|
|
604
|
+
return s.length > max ? s.slice(0, max) + "\n... (truncated)" : s;
|
|
605
|
+
}
|
|
606
|
+
function toolErrorSummary(result, max = 180) {
|
|
607
|
+
if (!result) return "";
|
|
608
|
+
try {
|
|
609
|
+
const parsed = JSON.parse(result);
|
|
610
|
+
const error = typeof parsed?.error === "string" ? parsed.error : "";
|
|
611
|
+
if (error === "sandbox_unavailable") {
|
|
612
|
+
return "Sandbox is unavailable. Workspace commands cannot run right now.";
|
|
613
|
+
}
|
|
614
|
+
const reason = typeof parsed?.reason === "string" ? parsed.reason : "";
|
|
615
|
+
const message = typeof parsed?.message === "string" ? parsed.message : "";
|
|
616
|
+
const detail = reason || message;
|
|
617
|
+
const summary = error && detail && detail !== error ? `${error}: ${detail}` : error || detail;
|
|
618
|
+
return summary ? summary.replace(/\s+/g, " ").slice(0, max) : "";
|
|
619
|
+
} catch {
|
|
620
|
+
return "";
|
|
621
|
+
}
|
|
622
|
+
}
|
|
573
623
|
function CopyButton({ text }) {
|
|
574
624
|
const [copied, setCopied] = useState(false);
|
|
575
625
|
return /* @__PURE__ */ jsx(
|
|
@@ -605,7 +655,8 @@ function parseTerminalResult(result, args) {
|
|
|
605
655
|
const hasOutput = typeof parsed?.output === "string";
|
|
606
656
|
const hasStdout = typeof parsed?.stdout === "string";
|
|
607
657
|
const hasExitCode = typeof parsed?.exit_code === "number";
|
|
608
|
-
|
|
658
|
+
const errorSummary = toolErrorSummary(result, 400);
|
|
659
|
+
if (!hasOutput && !hasStdout && !hasExitCode && !errorSummary) {
|
|
609
660
|
return null;
|
|
610
661
|
}
|
|
611
662
|
let command = "";
|
|
@@ -615,20 +666,20 @@ function parseTerminalResult(result, args) {
|
|
|
615
666
|
} catch {
|
|
616
667
|
}
|
|
617
668
|
const output = parsed.output ?? parsed.stdout ?? "";
|
|
618
|
-
const stderr = parsed.stderr ??
|
|
669
|
+
const stderr = parsed.stderr ?? errorSummary;
|
|
619
670
|
const combined = stderr ? `${output}
|
|
620
671
|
${stderr}`.trim() : output;
|
|
621
672
|
return {
|
|
622
673
|
output: combined,
|
|
623
|
-
exit_code: parsed.exit_code ?? 0,
|
|
624
|
-
error:
|
|
674
|
+
exit_code: parsed.exit_code ?? (errorSummary ? 1 : 0),
|
|
675
|
+
error: errorSummary || null,
|
|
625
676
|
command
|
|
626
677
|
};
|
|
627
678
|
} catch {
|
|
628
679
|
return null;
|
|
629
680
|
}
|
|
630
681
|
}
|
|
631
|
-
function TerminalCollapsible({ command, output, isRunning }) {
|
|
682
|
+
function TerminalCollapsible({ command, output, isRunning, hasError }) {
|
|
632
683
|
const [isOpen, setIsOpen] = useState(false);
|
|
633
684
|
return /* @__PURE__ */ jsxs(
|
|
634
685
|
Collapsible,
|
|
@@ -638,7 +689,7 @@ function TerminalCollapsible({ command, output, isRunning }) {
|
|
|
638
689
|
className: "not-prose w-full",
|
|
639
690
|
children: [
|
|
640
691
|
/* @__PURE__ */ jsxs(CollapsibleTrigger, { className: "group/trigger flex w-fit items-center gap-2 text-sm transition-colors", children: [
|
|
641
|
-
/* @__PURE__ */ jsx("span", { className: "text-left", children: isRunning ? /* @__PURE__ */ jsx(Shimmer, { as: "span", duration: 1, children: "Running command..." }) : /* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: "Command result" }) }),
|
|
692
|
+
/* @__PURE__ */ jsx("span", { className: "text-left", children: isRunning ? /* @__PURE__ */ jsx(Shimmer, { as: "span", duration: 1, children: "Running command..." }) : hasError ? /* @__PURE__ */ jsx("span", { className: "font-semibold text-destructive", children: "Command failed" }) : /* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: "Command result" }) }),
|
|
642
693
|
/* @__PURE__ */ jsx(
|
|
643
694
|
ChevronDownIcon,
|
|
644
695
|
{
|
|
@@ -695,7 +746,8 @@ function TerminalToolBlock({ tc }) {
|
|
|
695
746
|
{
|
|
696
747
|
command: result.command,
|
|
697
748
|
output,
|
|
698
|
-
isRunning
|
|
749
|
+
isRunning,
|
|
750
|
+
hasError: result.exit_code !== 0 || Boolean(result.error)
|
|
699
751
|
}
|
|
700
752
|
);
|
|
701
753
|
}
|
|
@@ -2340,7 +2392,7 @@ var Terminal = ({
|
|
|
2340
2392
|
}
|
|
2341
2393
|
) });
|
|
2342
2394
|
};
|
|
2343
|
-
function
|
|
2395
|
+
function parseArgs2(args) {
|
|
2344
2396
|
try {
|
|
2345
2397
|
return JSON.parse(args);
|
|
2346
2398
|
} catch {
|
|
@@ -2564,7 +2616,7 @@ function OutputPreview({ output }) {
|
|
|
2564
2616
|
}
|
|
2565
2617
|
function ProcessToolBlock({ tc }) {
|
|
2566
2618
|
const isRunning = tc.status === "running";
|
|
2567
|
-
const args =
|
|
2619
|
+
const args = parseArgs2(tc.args);
|
|
2568
2620
|
const result = parseResult(tc.result);
|
|
2569
2621
|
const action = args.action || "unknown";
|
|
2570
2622
|
const actionLabel = {
|
|
@@ -2647,44 +2699,6 @@ function Textarea({ className, ...props }) {
|
|
|
2647
2699
|
}
|
|
2648
2700
|
);
|
|
2649
2701
|
}
|
|
2650
|
-
|
|
2651
|
-
// src/components/chat/tools/shared.ts
|
|
2652
|
-
function statusColorClass(status) {
|
|
2653
|
-
if (status === "running") return "bg-primary animate-pulse";
|
|
2654
|
-
if (status === "error") return "bg-red-500";
|
|
2655
|
-
if (status === "cancelled") return "bg-muted-foreground/40";
|
|
2656
|
-
return "bg-emerald-500";
|
|
2657
|
-
}
|
|
2658
|
-
function effectiveStatus(tc) {
|
|
2659
|
-
if (tc.cancelled) return "cancelled";
|
|
2660
|
-
if (tc.status !== "complete" || !tc.result) return tc.status;
|
|
2661
|
-
try {
|
|
2662
|
-
const parsed = JSON.parse(tc.result);
|
|
2663
|
-
if (parsed?.exit_code !== void 0 && parsed.exit_code !== 0) return "error";
|
|
2664
|
-
if (parsed?.error) return "error";
|
|
2665
|
-
if (parsed?.status === "blocked" || parsed?.status === "error") return "error";
|
|
2666
|
-
if (parsed?.success === false) return "error";
|
|
2667
|
-
} catch {
|
|
2668
|
-
}
|
|
2669
|
-
return "complete";
|
|
2670
|
-
}
|
|
2671
|
-
function formatArgs(args) {
|
|
2672
|
-
try {
|
|
2673
|
-
return JSON.stringify(JSON.parse(args), null, 2);
|
|
2674
|
-
} catch {
|
|
2675
|
-
return args;
|
|
2676
|
-
}
|
|
2677
|
-
}
|
|
2678
|
-
function parseArgs2(args) {
|
|
2679
|
-
try {
|
|
2680
|
-
return JSON.parse(args);
|
|
2681
|
-
} catch {
|
|
2682
|
-
return null;
|
|
2683
|
-
}
|
|
2684
|
-
}
|
|
2685
|
-
function truncate(s, max) {
|
|
2686
|
-
return s.length > max ? s.slice(0, max) + "\n... (truncated)" : s;
|
|
2687
|
-
}
|
|
2688
2702
|
var MAX_REASON_LENGTH = 500;
|
|
2689
2703
|
function ExpertToolBlock({ tc }) {
|
|
2690
2704
|
const [expanded, setExpanded] = useState(false);
|
|
@@ -2720,7 +2734,7 @@ function ExpertToolBlock({ tc }) {
|
|
|
2720
2734
|
}
|
|
2721
2735
|
void submit("up");
|
|
2722
2736
|
};
|
|
2723
|
-
const args =
|
|
2737
|
+
const args = parseArgs(tc.args) ?? {};
|
|
2724
2738
|
const expertName = args.expert ?? null;
|
|
2725
2739
|
const question = args.question ?? args.prompt ?? "";
|
|
2726
2740
|
const result = parseExpertResult(tc.result);
|
|
@@ -2832,7 +2846,7 @@ function ExpertToolBlock({ tc }) {
|
|
|
2832
2846
|
}
|
|
2833
2847
|
function parseExpertResult(result) {
|
|
2834
2848
|
if (!result) return null;
|
|
2835
|
-
const parsed =
|
|
2849
|
+
const parsed = parseArgs(result);
|
|
2836
2850
|
if (parsed) {
|
|
2837
2851
|
return {
|
|
2838
2852
|
...parsed,
|
|
@@ -2939,11 +2953,11 @@ function ReasonForm({
|
|
|
2939
2953
|
] });
|
|
2940
2954
|
}
|
|
2941
2955
|
function SkillsListBlock({ tc }) {
|
|
2942
|
-
const args =
|
|
2956
|
+
const args = parseArgs(tc.args) ?? {};
|
|
2943
2957
|
const filter = args.category ? `category: ${args.category}` : "all";
|
|
2944
2958
|
let summary = "";
|
|
2945
2959
|
if (tc.result) {
|
|
2946
|
-
const parsed =
|
|
2960
|
+
const parsed = parseArgs(tc.result);
|
|
2947
2961
|
if (parsed?.count !== void 0) {
|
|
2948
2962
|
summary = `${parsed.count} skill${parsed.count === 1 ? "" : "s"}`;
|
|
2949
2963
|
}
|
|
@@ -2958,11 +2972,11 @@ function SkillsListBlock({ tc }) {
|
|
|
2958
2972
|
] });
|
|
2959
2973
|
}
|
|
2960
2974
|
function SkillViewBlock({ tc }) {
|
|
2961
|
-
const args =
|
|
2975
|
+
const args = parseArgs(tc.args) ?? {};
|
|
2962
2976
|
const target = args.file_path ? `${args.name ?? "?"}/${args.file_path}` : args.name ?? "?";
|
|
2963
2977
|
let summary = "";
|
|
2964
2978
|
if (tc.result) {
|
|
2965
|
-
const parsed =
|
|
2979
|
+
const parsed = parseArgs(tc.result);
|
|
2966
2980
|
if (parsed?.staged_at) {
|
|
2967
2981
|
summary = `staged at ${parsed.staged_at}`;
|
|
2968
2982
|
} else if (parsed?.token_estimate) {
|
|
@@ -3009,7 +3023,7 @@ function buildAnswer(q, sel) {
|
|
|
3009
3023
|
}
|
|
3010
3024
|
function ClarifyToolBlock({ tc }) {
|
|
3011
3025
|
const { adapter, sessionId } = useAgentChatAdapterContext();
|
|
3012
|
-
const args = useMemo(() =>
|
|
3026
|
+
const args = useMemo(() => parseArgs(tc.args), [tc.args]);
|
|
3013
3027
|
const questions = args?.questions ?? [];
|
|
3014
3028
|
const [active, setActive] = useState(0);
|
|
3015
3029
|
const [selections, setSelections] = useState(
|
|
@@ -3291,7 +3305,7 @@ function ClarifyLocked({
|
|
|
3291
3305
|
] });
|
|
3292
3306
|
}
|
|
3293
3307
|
function ArtifactToolBlock({ tc }) {
|
|
3294
|
-
const args =
|
|
3308
|
+
const args = parseArgs(tc.args) ?? {};
|
|
3295
3309
|
const status = effectiveStatus(tc);
|
|
3296
3310
|
const label = status === "running" ? "Creating artifact\u2026" : status === "error" ? "Tried to create" : "Created";
|
|
3297
3311
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-sm ", children: [
|
|
@@ -3305,7 +3319,7 @@ function firstLine(s) {
|
|
|
3305
3319
|
}
|
|
3306
3320
|
function DelegateToolBlock({ tc }) {
|
|
3307
3321
|
const [expanded, setExpanded] = useState(false);
|
|
3308
|
-
const args =
|
|
3322
|
+
const args = parseArgs(tc.args);
|
|
3309
3323
|
const goal = args?.goal ?? "";
|
|
3310
3324
|
const context = args?.context ?? "";
|
|
3311
3325
|
const agentType = args?.agent_type;
|
|
@@ -3415,8 +3429,8 @@ var TARGET_LABEL = {
|
|
|
3415
3429
|
};
|
|
3416
3430
|
function MemoryToolBlock({ tc }) {
|
|
3417
3431
|
const [isOpen, setIsOpen] = useState(false);
|
|
3418
|
-
const args =
|
|
3419
|
-
const result = tc.result ?
|
|
3432
|
+
const args = parseArgs(tc.args) ?? {};
|
|
3433
|
+
const result = tc.result ? parseArgs(tc.result) : null;
|
|
3420
3434
|
const action = args.action ?? "add";
|
|
3421
3435
|
const target = args.target ?? "memory";
|
|
3422
3436
|
const verb = ACTION_VERB[action] ?? action;
|
|
@@ -3494,8 +3508,8 @@ var ACTION_LABEL = {
|
|
|
3494
3508
|
remove_file: "Remove skill file"
|
|
3495
3509
|
};
|
|
3496
3510
|
function SkillManageToolBlock({ tc }) {
|
|
3497
|
-
const args =
|
|
3498
|
-
const result = tc.result ?
|
|
3511
|
+
const args = parseArgs(tc.args) ?? {};
|
|
3512
|
+
const result = tc.result ? parseArgs(tc.result) : null;
|
|
3499
3513
|
const action = args.action ?? "manage";
|
|
3500
3514
|
const label = ACTION_LABEL[action] ?? "Manage skill";
|
|
3501
3515
|
const target = args.file_path ? `${args.name ?? "?"}/${args.file_path}` : args.name ?? "?";
|
|
@@ -3516,8 +3530,8 @@ function firstLine2(value) {
|
|
|
3516
3530
|
return (index === -1 ? value : value.slice(0, index)).trim();
|
|
3517
3531
|
}
|
|
3518
3532
|
function CoordinatorToolBlock({ tc }) {
|
|
3519
|
-
const args =
|
|
3520
|
-
const result = tc.result ?
|
|
3533
|
+
const args = parseArgs(tc.args) ?? {};
|
|
3534
|
+
const result = tc.result ? parseArgs(tc.result) : null;
|
|
3521
3535
|
const failed = Boolean(result?.error);
|
|
3522
3536
|
let label = "Worker";
|
|
3523
3537
|
let target = "";
|
|
@@ -5468,7 +5482,7 @@ function exportArtifact(payload) {
|
|
|
5468
5482
|
};
|
|
5469
5483
|
case "chart":
|
|
5470
5484
|
return {
|
|
5471
|
-
text: JSON.stringify(payload.spec.
|
|
5485
|
+
text: JSON.stringify(payload.spec.chart_js, null, 2),
|
|
5472
5486
|
mime: "application/json",
|
|
5473
5487
|
extension: "json"
|
|
5474
5488
|
};
|
|
@@ -5529,7 +5543,7 @@ async function copyText(text) {
|
|
|
5529
5543
|
}
|
|
5530
5544
|
}
|
|
5531
5545
|
var ArtifactChart = lazy(
|
|
5532
|
-
() => import('./artifact-chart-
|
|
5546
|
+
() => import('./artifact-chart-X53FKRDZ.js').then((m) => ({ default: m.ArtifactChart }))
|
|
5533
5547
|
);
|
|
5534
5548
|
var KIND_LABEL = {
|
|
5535
5549
|
markdown: "Markdown document",
|
|
@@ -5654,7 +5668,7 @@ function ArtifactBody({
|
|
|
5654
5668
|
Suspense,
|
|
5655
5669
|
{
|
|
5656
5670
|
fallback: /* @__PURE__ */ jsx(Shimmer, { duration: 5, className: "text-sm text-muted-foreground", children: "Loading chart\u2026" }),
|
|
5657
|
-
children: /* @__PURE__ */ jsx(ArtifactChart, { spec: payload.spec })
|
|
5671
|
+
children: /* @__PURE__ */ jsx(ArtifactChart, { spec: payload.spec, fill })
|
|
5658
5672
|
}
|
|
5659
5673
|
);
|
|
5660
5674
|
case "html":
|
|
@@ -5874,7 +5888,7 @@ function OrphanSystemMarker({
|
|
|
5874
5888
|
);
|
|
5875
5889
|
}
|
|
5876
5890
|
if (message.systemKind === "error" && message.errorInfo) {
|
|
5877
|
-
return /* @__PURE__ */ jsx("div", { className: "mx-auto my-2 w-full max-w-4xl
|
|
5891
|
+
return /* @__PURE__ */ jsx("div", { className: "mx-auto my-2 w-full max-w-4xl", children: /* @__PURE__ */ jsx(ErrorMessage, { errorInfo: message.errorInfo, onRetry }) });
|
|
5878
5892
|
}
|
|
5879
5893
|
return null;
|
|
5880
5894
|
}
|
|
@@ -5928,6 +5942,7 @@ function TimelineEntryItem({
|
|
|
5928
5942
|
] });
|
|
5929
5943
|
}
|
|
5930
5944
|
if (entry.kind === "tool") {
|
|
5945
|
+
const failureSummary = effectiveStatus(entry.tc) === "error" ? toolErrorSummary(entry.tc.result) : "";
|
|
5931
5946
|
return /* @__PURE__ */ jsxs(TimelineItem, { step, children: [
|
|
5932
5947
|
/* @__PURE__ */ jsxs(TimelineHeader, { children: [
|
|
5933
5948
|
/* @__PURE__ */ jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
|
|
@@ -5938,7 +5953,10 @@ function TimelineEntryItem({
|
|
|
5938
5953
|
}
|
|
5939
5954
|
)
|
|
5940
5955
|
] }),
|
|
5941
|
-
/* @__PURE__ */ jsx(TimelineContent, { children: entry.tc.cancelled ? /* @__PURE__ */ jsx(CancelledToolRow, { tc: entry.tc }) : /* @__PURE__ */
|
|
5956
|
+
/* @__PURE__ */ jsx(TimelineContent, { children: entry.tc.cancelled ? /* @__PURE__ */ jsx(CancelledToolRow, { tc: entry.tc }) : /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
5957
|
+
/* @__PURE__ */ jsx(ToolCallBlock, { tc: entry.tc, onFileSelect }),
|
|
5958
|
+
failureSummary ? /* @__PURE__ */ jsx("div", { className: "max-w-full truncate text-xs text-destructive", title: failureSummary, children: failureSummary }) : null
|
|
5959
|
+
] }) })
|
|
5942
5960
|
] });
|
|
5943
5961
|
}
|
|
5944
5962
|
if (entry.kind === "text") {
|
|
@@ -6056,6 +6074,7 @@ function ChatThread({
|
|
|
6056
6074
|
sessionId,
|
|
6057
6075
|
messages,
|
|
6058
6076
|
isRunning,
|
|
6077
|
+
isLoadingHistory = false,
|
|
6059
6078
|
onSend,
|
|
6060
6079
|
onStop,
|
|
6061
6080
|
onFileSelect,
|
|
@@ -6078,7 +6097,14 @@ function ChatThread({
|
|
|
6078
6097
|
}, [messages]);
|
|
6079
6098
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden bg-background text-sm", children: [
|
|
6080
6099
|
/* @__PURE__ */ jsxs(Conversation, { className: "relative flex-1 min-h-0", children: [
|
|
6081
|
-
/* @__PURE__ */ jsx(ConversationContent, { className: "mx-auto w-full max-w-
|
|
6100
|
+
/* @__PURE__ */ jsx(ConversationContent, { className: "mx-auto w-full max-w-4xl", children: messages.length === 0 && isLoadingHistory ? /* @__PURE__ */ jsx(
|
|
6101
|
+
ConversationEmptyState,
|
|
6102
|
+
{
|
|
6103
|
+
icon: /* @__PURE__ */ jsx(MessageSquareIcon, { className: "size-8 opacity-40" }),
|
|
6104
|
+
title: "Loading conversation",
|
|
6105
|
+
description: "Fetching the session history."
|
|
6106
|
+
}
|
|
6107
|
+
) : messages.length === 0 && !disabled ? /* @__PURE__ */ jsx(
|
|
6082
6108
|
ConversationEmptyState,
|
|
6083
6109
|
{
|
|
6084
6110
|
icon: /* @__PURE__ */ jsx(MessageSquareIcon, { className: "size-8 opacity-40" }),
|
|
@@ -6131,7 +6157,7 @@ function ChatThread({
|
|
|
6131
6157
|
] }) }),
|
|
6132
6158
|
/* @__PURE__ */ jsx(ConversationScrollButton, {})
|
|
6133
6159
|
] }),
|
|
6134
|
-
/* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-
|
|
6160
|
+
/* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-4xl px-6 pb-5 pt-3", children: [
|
|
6135
6161
|
retryIndicator && /* @__PURE__ */ jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsx(RetryBanner, { indicator: retryIndicator }) }),
|
|
6136
6162
|
/* @__PURE__ */ jsx(
|
|
6137
6163
|
ChatComposer,
|
|
@@ -6732,7 +6758,7 @@ function formatPdfPreviewError(error) {
|
|
|
6732
6758
|
return error instanceof Error ? error.message : "Failed to render PDF preview.";
|
|
6733
6759
|
}
|
|
6734
6760
|
var SKELETON_WIDTHS2 = [75, 60, 90, 65, 80, 70, 85, 55];
|
|
6735
|
-
var DEFAULT_WIDTH =
|
|
6761
|
+
var DEFAULT_WIDTH = 400;
|
|
6736
6762
|
var MIN_WIDTH = 300;
|
|
6737
6763
|
var MAX_WIDTH = 900;
|
|
6738
6764
|
function collectExpandedPaths(entries, depth = 0) {
|
|
@@ -6814,6 +6840,8 @@ function WorkspacePanel({
|
|
|
6814
6840
|
sessionId,
|
|
6815
6841
|
selectedPath,
|
|
6816
6842
|
onSelectedPathChange,
|
|
6843
|
+
collapsed = false,
|
|
6844
|
+
onCollapsedChange,
|
|
6817
6845
|
disabled = false
|
|
6818
6846
|
}) {
|
|
6819
6847
|
const fileInputRef = useRef(null);
|
|
@@ -7008,6 +7036,25 @@ function WorkspacePanel({
|
|
|
7008
7036
|
window.removeEventListener("mouseup", onMouseUp);
|
|
7009
7037
|
};
|
|
7010
7038
|
}, []);
|
|
7039
|
+
if (collapsed) {
|
|
7040
|
+
return /* @__PURE__ */ jsx(
|
|
7041
|
+
"aside",
|
|
7042
|
+
{
|
|
7043
|
+
role: "button",
|
|
7044
|
+
tabIndex: 0,
|
|
7045
|
+
className: "relative z-10 flex min-h-0 w-10 shrink-0 cursor-pointer items-center justify-center border-l border-muted-foreground/20 bg-card text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30",
|
|
7046
|
+
"aria-label": "Expand workspace",
|
|
7047
|
+
onClick: () => onCollapsedChange?.(false),
|
|
7048
|
+
onKeyDown: (event) => {
|
|
7049
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
7050
|
+
event.preventDefault();
|
|
7051
|
+
onCollapsedChange?.(false);
|
|
7052
|
+
}
|
|
7053
|
+
},
|
|
7054
|
+
children: /* @__PURE__ */ jsx(FolderOpenIcon, { className: "size-4 text-amber-500" })
|
|
7055
|
+
}
|
|
7056
|
+
);
|
|
7057
|
+
}
|
|
7011
7058
|
return /* @__PURE__ */ jsxs(
|
|
7012
7059
|
"aside",
|
|
7013
7060
|
{
|
|
@@ -7040,6 +7087,19 @@ function WorkspacePanel({
|
|
|
7040
7087
|
/* @__PURE__ */ jsx("div", { className: "truncate text-sm font-medium text-foreground", children: rootName }),
|
|
7041
7088
|
/* @__PURE__ */ jsx("div", { className: "truncate text-xs text-faint", children: "Workspace" })
|
|
7042
7089
|
] }),
|
|
7090
|
+
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
7091
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
7092
|
+
Button,
|
|
7093
|
+
{
|
|
7094
|
+
variant: "ghost",
|
|
7095
|
+
size: "icon-sm",
|
|
7096
|
+
onClick: () => onCollapsedChange?.(true),
|
|
7097
|
+
"aria-label": "Collapse workspace",
|
|
7098
|
+
children: /* @__PURE__ */ jsx(ChevronRightIcon, { className: "size-4" })
|
|
7099
|
+
}
|
|
7100
|
+
) }),
|
|
7101
|
+
/* @__PURE__ */ jsx(TooltipContent, { side: "bottom", children: "Collapse" })
|
|
7102
|
+
] }),
|
|
7043
7103
|
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
7044
7104
|
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
7045
7105
|
Button,
|
|
@@ -7239,10 +7299,11 @@ var EMPTY_TOKEN_USAGE = {
|
|
|
7239
7299
|
contextWindow: 0,
|
|
7240
7300
|
model: ""
|
|
7241
7301
|
};
|
|
7242
|
-
function createInitialAgentChatState() {
|
|
7302
|
+
function createInitialAgentChatState(options = {}) {
|
|
7243
7303
|
return {
|
|
7244
7304
|
messages: [],
|
|
7245
7305
|
isRunning: false,
|
|
7306
|
+
isLoadingHistory: options.isLoadingHistory ?? false,
|
|
7246
7307
|
tokenUsage: EMPTY_TOKEN_USAGE,
|
|
7247
7308
|
retryIndicator: null,
|
|
7248
7309
|
lastEventId: 0,
|
|
@@ -7254,6 +7315,7 @@ function createInitialAgentChatState() {
|
|
|
7254
7315
|
function applyAgentChatEvent(state, event) {
|
|
7255
7316
|
let nextState = {
|
|
7256
7317
|
...state,
|
|
7318
|
+
isLoadingHistory: false,
|
|
7257
7319
|
lastEventId: Math.max(state.lastEventId, event.eventId),
|
|
7258
7320
|
sessionDone: state.sessionDone || event.type === "session.done"
|
|
7259
7321
|
};
|
|
@@ -7787,11 +7849,12 @@ function useAgentChatRuntime({
|
|
|
7787
7849
|
onSessionChange
|
|
7788
7850
|
}) {
|
|
7789
7851
|
const [state, setState] = useState(
|
|
7790
|
-
() => createInitialAgentChatState()
|
|
7852
|
+
() => createInitialAgentChatState({ isLoadingHistory: Boolean(sessionId) })
|
|
7791
7853
|
);
|
|
7792
7854
|
const stateRef = useRef(state);
|
|
7793
7855
|
const streamRef = useRef(null);
|
|
7794
7856
|
const reconnectTimerRef = useRef(null);
|
|
7857
|
+
const previousSessionIdRef = useRef(sessionId);
|
|
7795
7858
|
useEffect(() => {
|
|
7796
7859
|
stateRef.current = state;
|
|
7797
7860
|
}, [state]);
|
|
@@ -7807,6 +7870,8 @@ function useAgentChatRuntime({
|
|
|
7807
7870
|
stream?.close();
|
|
7808
7871
|
}, []);
|
|
7809
7872
|
useEffect(() => {
|
|
7873
|
+
const previousSessionId = previousSessionIdRef.current;
|
|
7874
|
+
previousSessionIdRef.current = sessionId;
|
|
7810
7875
|
clearReconnectTimer();
|
|
7811
7876
|
closeStream();
|
|
7812
7877
|
if (!sessionId) {
|
|
@@ -7814,11 +7879,11 @@ function useAgentChatRuntime({
|
|
|
7814
7879
|
return;
|
|
7815
7880
|
}
|
|
7816
7881
|
let cancelled = false;
|
|
7817
|
-
const connect = () => {
|
|
7882
|
+
const connect = (after) => {
|
|
7818
7883
|
if (cancelled) return;
|
|
7819
7884
|
const stream = adapter.openEventStream({
|
|
7820
7885
|
sessionId,
|
|
7821
|
-
after: stateRef.current.lastEventId
|
|
7886
|
+
after: after ?? stateRef.current.lastEventId
|
|
7822
7887
|
});
|
|
7823
7888
|
streamRef.current = stream;
|
|
7824
7889
|
for (const eventType of AGENT_CHAT_LISTENED_EVENTS) {
|
|
@@ -7841,14 +7906,32 @@ function useAgentChatRuntime({
|
|
|
7841
7906
|
streamRef.current = null;
|
|
7842
7907
|
}
|
|
7843
7908
|
if (!stateRef.current.sessionDone && !cancelled) {
|
|
7844
|
-
reconnectTimerRef.current = setTimeout(connect, 3e3);
|
|
7909
|
+
reconnectTimerRef.current = setTimeout(() => connect(), 3e3);
|
|
7845
7910
|
}
|
|
7846
7911
|
};
|
|
7847
7912
|
};
|
|
7848
|
-
|
|
7849
|
-
|
|
7913
|
+
const currentState = stateRef.current;
|
|
7914
|
+
const preservePendingFirstMessage = previousSessionId === null && currentState.isRunning && currentState.messages.some(
|
|
7915
|
+
(message) => message.role === "user" && message.id.startsWith("local-")
|
|
7916
|
+
);
|
|
7917
|
+
const initialState = preservePendingFirstMessage ? {
|
|
7918
|
+
...createInitialAgentChatState({ isLoadingHistory: false }),
|
|
7919
|
+
messages: currentState.messages,
|
|
7920
|
+
isRunning: true
|
|
7921
|
+
} : createInitialAgentChatState({
|
|
7922
|
+
isLoadingHistory: true
|
|
7923
|
+
});
|
|
7924
|
+
stateRef.current = initialState;
|
|
7925
|
+
setState(initialState);
|
|
7926
|
+
connect(0);
|
|
7850
7927
|
adapter.getSession({ sessionId }).then((session) => {
|
|
7851
7928
|
if (cancelled) return;
|
|
7929
|
+
if (session.messageCount === 0) {
|
|
7930
|
+
setState((prev) => ({
|
|
7931
|
+
...prev,
|
|
7932
|
+
isLoadingHistory: false
|
|
7933
|
+
}));
|
|
7934
|
+
}
|
|
7852
7935
|
if (isTerminalStatus(session.status)) {
|
|
7853
7936
|
setState((prev) => ({
|
|
7854
7937
|
...prev,
|
|
@@ -7931,13 +8014,18 @@ function useAgentChatRuntime({
|
|
|
7931
8014
|
}, []);
|
|
7932
8015
|
const send = useCallback(
|
|
7933
8016
|
async (content) => {
|
|
8017
|
+
markSending(content);
|
|
7934
8018
|
if (!sessionId) {
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
8019
|
+
try {
|
|
8020
|
+
const session = await adapter.createSession({ agentId });
|
|
8021
|
+
onSessionChange?.(session.id);
|
|
8022
|
+
await adapter.sendMessage({ sessionId: session.id, content });
|
|
8023
|
+
} catch (error) {
|
|
8024
|
+
markSendError(error instanceof Error ? error.message : "send failed");
|
|
8025
|
+
throw error;
|
|
8026
|
+
}
|
|
7938
8027
|
return;
|
|
7939
8028
|
}
|
|
7940
|
-
markSending(content);
|
|
7941
8029
|
try {
|
|
7942
8030
|
await adapter.sendMessage({ sessionId, content });
|
|
7943
8031
|
} catch (error) {
|
|
@@ -7974,6 +8062,7 @@ function useAgentChatRuntime({
|
|
|
7974
8062
|
return {
|
|
7975
8063
|
messages: state.messages,
|
|
7976
8064
|
isRunning: state.isRunning,
|
|
8065
|
+
isLoadingHistory: state.isLoadingHistory,
|
|
7977
8066
|
tokenUsage: state.tokenUsage,
|
|
7978
8067
|
retryIndicator: state.retryIndicator,
|
|
7979
8068
|
send,
|
|
@@ -8010,6 +8099,7 @@ function AgentChat({
|
|
|
8010
8099
|
disabled
|
|
8011
8100
|
}) {
|
|
8012
8101
|
const [workspacePath, setWorkspacePath] = useState(null);
|
|
8102
|
+
const [workspaceCollapsed, setWorkspaceCollapsed] = useState(false);
|
|
8013
8103
|
const runtime = useAgentChatRuntime({
|
|
8014
8104
|
adapter,
|
|
8015
8105
|
agentId,
|
|
@@ -8041,6 +8131,7 @@ function AgentChat({
|
|
|
8041
8131
|
sessionId,
|
|
8042
8132
|
messages: runtime.messages,
|
|
8043
8133
|
isRunning: runtime.isRunning,
|
|
8134
|
+
isLoadingHistory: runtime.isLoadingHistory,
|
|
8044
8135
|
onSend: (content) => void runtime.send(content),
|
|
8045
8136
|
onStop: () => void runtime.stop(),
|
|
8046
8137
|
onRetry: runtime.retry,
|
|
@@ -8057,6 +8148,8 @@ function AgentChat({
|
|
|
8057
8148
|
sessionId,
|
|
8058
8149
|
selectedPath: workspacePath,
|
|
8059
8150
|
onSelectedPathChange: setWorkspacePath,
|
|
8151
|
+
collapsed: workspaceCollapsed,
|
|
8152
|
+
onCollapsedChange: setWorkspaceCollapsed,
|
|
8060
8153
|
disabled
|
|
8061
8154
|
}
|
|
8062
8155
|
)
|
|
@@ -8127,6 +8220,20 @@ function mergeTreeNodes(groups) {
|
|
|
8127
8220
|
}
|
|
8128
8221
|
return Array.from(byId.values());
|
|
8129
8222
|
}
|
|
8223
|
+
function pruneDeletedSessionNodes(nodes, deletedSessionId) {
|
|
8224
|
+
const deletedIds = /* @__PURE__ */ new Set([deletedSessionId]);
|
|
8225
|
+
let changed = true;
|
|
8226
|
+
while (changed) {
|
|
8227
|
+
changed = false;
|
|
8228
|
+
for (const node of nodes) {
|
|
8229
|
+
if (node.parentId && deletedIds.has(node.parentId) && !deletedIds.has(node.id)) {
|
|
8230
|
+
deletedIds.add(node.id);
|
|
8231
|
+
changed = true;
|
|
8232
|
+
}
|
|
8233
|
+
}
|
|
8234
|
+
}
|
|
8235
|
+
return nodes.filter((node) => !deletedIds.has(node.id));
|
|
8236
|
+
}
|
|
8130
8237
|
function formatSessionTime(value) {
|
|
8131
8238
|
const date = new Date(value);
|
|
8132
8239
|
if (Number.isNaN(date.getTime())) return "";
|
|
@@ -8243,11 +8350,12 @@ function SessionTreePanel({
|
|
|
8243
8350
|
title = "Running",
|
|
8244
8351
|
sessionListLimit = DEFAULT_SESSION_LIST_LIMIT,
|
|
8245
8352
|
hideRoot = false,
|
|
8353
|
+
hideHeader = false,
|
|
8354
|
+
loadList = false,
|
|
8246
8355
|
onSessionSelect,
|
|
8247
8356
|
onSessionDelete
|
|
8248
8357
|
}) {
|
|
8249
8358
|
const [nodes, setNodes] = useState([]);
|
|
8250
|
-
const [loading, setLoading] = useState(false);
|
|
8251
8359
|
const [error, setError] = useState(null);
|
|
8252
8360
|
const [hasEverLoaded, setHasEverLoaded] = useState(false);
|
|
8253
8361
|
const [deletingSessionId, setDeletingSessionId] = useState(
|
|
@@ -8259,18 +8367,16 @@ function SessionTreePanel({
|
|
|
8259
8367
|
const resetContext = useRef(null);
|
|
8260
8368
|
const refetch = useCallback(
|
|
8261
8369
|
async (opts) => {
|
|
8262
|
-
const canLoadSessionList = Boolean(
|
|
8370
|
+
const canLoadSessionList = Boolean(loadList && adapter.listSessions);
|
|
8263
8371
|
const canLoadSessionTree = Boolean(sessionId && adapter.getSessionTree);
|
|
8264
8372
|
if (!canLoadSessionList && !canLoadSessionTree) {
|
|
8265
8373
|
setNodes([]);
|
|
8266
8374
|
setHasEverLoaded(true);
|
|
8267
|
-
setLoading(false);
|
|
8268
8375
|
return;
|
|
8269
8376
|
}
|
|
8270
8377
|
const currentRequestId = ++requestId.current;
|
|
8271
|
-
if (!opts?.silent) setLoading(true);
|
|
8272
8378
|
try {
|
|
8273
|
-
const sessionListPromise =
|
|
8379
|
+
const sessionListPromise = loadList && adapter.listSessions ? adapter.listSessions({
|
|
8274
8380
|
agentId,
|
|
8275
8381
|
limit: sessionListLimit
|
|
8276
8382
|
}) : Promise.resolve(null);
|
|
@@ -8296,13 +8402,9 @@ function SessionTreePanel({
|
|
|
8296
8402
|
if (!opts?.silent) {
|
|
8297
8403
|
setError(e instanceof Error ? e.message : "Failed to load tree");
|
|
8298
8404
|
}
|
|
8299
|
-
} finally {
|
|
8300
|
-
if (mounted.current && currentRequestId === requestId.current && !opts?.silent) {
|
|
8301
|
-
setLoading(false);
|
|
8302
|
-
}
|
|
8303
8405
|
}
|
|
8304
8406
|
},
|
|
8305
|
-
[adapter, agentId, sessionId, sessionListLimit]
|
|
8407
|
+
[adapter, agentId, loadList, sessionId, sessionListLimit]
|
|
8306
8408
|
);
|
|
8307
8409
|
useEffect(() => {
|
|
8308
8410
|
mounted.current = true;
|
|
@@ -8312,8 +8414,8 @@ function SessionTreePanel({
|
|
|
8312
8414
|
}, []);
|
|
8313
8415
|
useEffect(() => {
|
|
8314
8416
|
const previous = resetContext.current;
|
|
8315
|
-
const shouldReset = !previous || previous.
|
|
8316
|
-
resetContext.current = {
|
|
8417
|
+
const shouldReset = !previous || previous.loadList !== loadList || previous.agentId !== agentId || previous.sessionListLimit !== sessionListLimit;
|
|
8418
|
+
resetContext.current = { loadList, agentId, sessionListLimit };
|
|
8317
8419
|
if (shouldReset) {
|
|
8318
8420
|
setNodes([]);
|
|
8319
8421
|
setHasEverLoaded(false);
|
|
@@ -8321,7 +8423,7 @@ function SessionTreePanel({
|
|
|
8321
8423
|
}
|
|
8322
8424
|
setError(null);
|
|
8323
8425
|
void refetch();
|
|
8324
|
-
}, [adapter, agentId, refetch, sessionListLimit]);
|
|
8426
|
+
}, [adapter, agentId, loadList, refetch, sessionListLimit]);
|
|
8325
8427
|
const runningCount = useMemo(
|
|
8326
8428
|
() => nodes.filter((n) => n.status === "active").length,
|
|
8327
8429
|
[nodes]
|
|
@@ -8358,6 +8460,11 @@ function SessionTreePanel({
|
|
|
8358
8460
|
setDeletingSessionId(id);
|
|
8359
8461
|
try {
|
|
8360
8462
|
await adapter.deleteSession({ sessionId: id });
|
|
8463
|
+
setNodes((current) => {
|
|
8464
|
+
const next = pruneDeletedSessionNodes(current, id);
|
|
8465
|
+
lastFingerprint.current = treeFingerprint(next);
|
|
8466
|
+
return next;
|
|
8467
|
+
});
|
|
8361
8468
|
onSessionDelete?.(id);
|
|
8362
8469
|
await refetch({ silent: true });
|
|
8363
8470
|
} catch (e) {
|
|
@@ -8372,24 +8479,12 @@ function SessionTreePanel({
|
|
|
8372
8479
|
if (nodes.length === 0) return null;
|
|
8373
8480
|
const topLevel = hideRoot ? roots.flatMap((r) => r.children) : roots;
|
|
8374
8481
|
if (topLevel.length === 0) return null;
|
|
8375
|
-
return /* @__PURE__ */ jsxs(
|
|
8376
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 px-3 py-2 text-xs font-semibold uppercase tracking-wide", children: [
|
|
8482
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8483
|
+
!hideHeader && /* @__PURE__ */ jsxs("div", { className: "border-t border-line flex items-center gap-1.5 px-3 py-2 text-xs font-semibold uppercase tracking-wide", children: [
|
|
8377
8484
|
/* @__PURE__ */ jsx(UsersIcon, { className: "w-3.5 h-3.5" }),
|
|
8378
8485
|
/* @__PURE__ */ jsx("span", { children: title }),
|
|
8379
8486
|
runningCount > 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", className: "h-4 px-1.5 text-[10px] ml-auto", children: runningCount })
|
|
8380
8487
|
] }),
|
|
8381
|
-
loading && /* @__PURE__ */ jsx(
|
|
8382
|
-
"div",
|
|
8383
|
-
{
|
|
8384
|
-
className: "px-3 py-2",
|
|
8385
|
-
role: "status",
|
|
8386
|
-
"aria-label": "Loading sessions",
|
|
8387
|
-
children: /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
8388
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 w-28" }),
|
|
8389
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-20" })
|
|
8390
|
-
] })
|
|
8391
|
-
}
|
|
8392
|
-
),
|
|
8393
8488
|
error && /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-xs text-destructive", children: error }),
|
|
8394
8489
|
!error && /* @__PURE__ */ jsx("div", { className: "px-1 pb-2", children: topLevel.map((entry) => /* @__PURE__ */ jsx(
|
|
8395
8490
|
TreeNodeRow,
|