@invergent/agent-chat-react 1.5.3 → 1.5.5
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 +520 -183
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +267 -126
- 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.cjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var clsx = require('clsx');
|
|
4
|
+
var tailwindMerge = require('tailwind-merge');
|
|
3
5
|
var react = require('react');
|
|
4
|
-
var
|
|
6
|
+
var auto = require('chart.js/auto');
|
|
5
7
|
var nextThemes = require('next-themes');
|
|
6
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
9
|
var classVarianceAuthority = require('class-variance-authority');
|
|
8
10
|
var radixUi = require('radix-ui');
|
|
9
|
-
var clsx = require('clsx');
|
|
10
|
-
var tailwindMerge = require('tailwind-merge');
|
|
11
11
|
var lucideReact = require('lucide-react');
|
|
12
12
|
var useStickToBottom = require('use-stick-to-bottom');
|
|
13
13
|
var cjk = require('@streamdown/cjk');
|
|
@@ -39,56 +39,63 @@ var __export = (target, all) => {
|
|
|
39
39
|
for (var name in all)
|
|
40
40
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
41
41
|
};
|
|
42
|
+
function cn(...inputs) {
|
|
43
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
44
|
+
}
|
|
45
|
+
var init_utils = __esm({
|
|
46
|
+
"src/lib/utils.ts"() {
|
|
47
|
+
}
|
|
48
|
+
});
|
|
42
49
|
|
|
43
50
|
// src/components/chat/artifacts/artifact-chart.tsx
|
|
44
51
|
var artifact_chart_exports = {};
|
|
45
52
|
__export(artifact_chart_exports, {
|
|
46
53
|
ArtifactChart: () => ArtifactChart
|
|
47
54
|
});
|
|
48
|
-
function ArtifactChart({
|
|
55
|
+
function ArtifactChart({
|
|
56
|
+
spec,
|
|
57
|
+
fill = false
|
|
58
|
+
}) {
|
|
49
59
|
const { resolvedTheme } = nextThemes.useTheme();
|
|
50
60
|
const isDark = resolvedTheme === "dark";
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
react.useEffect(() => {
|
|
54
|
-
const el = containerRef.current;
|
|
55
|
-
if (!el) return;
|
|
56
|
-
const observer = new ResizeObserver((entries) => {
|
|
57
|
-
const w = entries[0]?.contentRect.width ?? el.offsetWidth;
|
|
58
|
-
if (w >= MIN_CHART_WIDTH) setWidth(Math.floor(w));
|
|
59
|
-
});
|
|
60
|
-
observer.observe(el);
|
|
61
|
-
if (el.offsetWidth >= MIN_CHART_WIDTH) setWidth(el.offsetWidth);
|
|
62
|
-
return () => observer.disconnect();
|
|
63
|
-
}, []);
|
|
61
|
+
const canvasRef = react.useRef(null);
|
|
62
|
+
const chartRef = react.useRef(null);
|
|
64
63
|
const [error, setError] = react.useState(null);
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
const base = spec.vega_lite ?? {};
|
|
68
|
-
const themeConfig = isDark ? DARK_CONFIG : LIGHT_CONFIG;
|
|
64
|
+
const config = react.useMemo(() => {
|
|
65
|
+
const base = cloneChartConfig(spec.chart_js ?? {});
|
|
69
66
|
return {
|
|
70
|
-
$schema: VEGA_LITE_SCHEMA,
|
|
71
|
-
width,
|
|
72
|
-
height: DEFAULT_CHART_HEIGHT,
|
|
73
67
|
...base,
|
|
74
|
-
|
|
75
|
-
...themeConfig,
|
|
76
|
-
...base.config ?? {}
|
|
77
|
-
}
|
|
68
|
+
options: mergeThemeOptions(base.options, base.type, isDark)
|
|
78
69
|
};
|
|
79
|
-
}, [spec.
|
|
70
|
+
}, [spec.chart_js, isDark]);
|
|
80
71
|
react.useEffect(() => {
|
|
72
|
+
const canvas = canvasRef.current;
|
|
73
|
+
if (!canvas) return;
|
|
74
|
+
chartRef.current?.destroy();
|
|
75
|
+
chartRef.current = null;
|
|
81
76
|
setError(null);
|
|
82
|
-
|
|
77
|
+
try {
|
|
78
|
+
chartRef.current = new auto.Chart(canvas, config);
|
|
79
|
+
} catch (e) {
|
|
80
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
81
|
+
}
|
|
82
|
+
return () => {
|
|
83
|
+
chartRef.current?.destroy();
|
|
84
|
+
chartRef.current = null;
|
|
85
|
+
};
|
|
86
|
+
}, [config]);
|
|
83
87
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
84
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
85
|
-
|
|
88
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
89
|
+
"div",
|
|
86
90
|
{
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
className: cn("relative w-full", fill && "h-full min-h-80"),
|
|
92
|
+
style: fill ? void 0 : {
|
|
93
|
+
height: DEFAULT_CHART_HEIGHT,
|
|
94
|
+
maxHeight: MAX_INLINE_CHART_HEIGHT
|
|
95
|
+
},
|
|
96
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("canvas", { ref: canvasRef })
|
|
90
97
|
}
|
|
91
|
-
)
|
|
98
|
+
),
|
|
92
99
|
error && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-destructive", children: [
|
|
93
100
|
"Chart error: ",
|
|
94
101
|
error
|
|
@@ -96,35 +103,101 @@ function ArtifactChart({ spec }) {
|
|
|
96
103
|
spec.caption && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: spec.caption })
|
|
97
104
|
] });
|
|
98
105
|
}
|
|
99
|
-
|
|
106
|
+
function cloneChartConfig(value) {
|
|
107
|
+
return JSON.parse(JSON.stringify(value));
|
|
108
|
+
}
|
|
109
|
+
function mergeThemeOptions(options, chartType, isDark) {
|
|
110
|
+
const theme = isDark ? DARK_THEME : LIGHT_THEME;
|
|
111
|
+
const base = isRecord(options) ? options : {};
|
|
112
|
+
const plugins = isRecord(base.plugins) ? base.plugins : {};
|
|
113
|
+
const legend = isRecord(plugins.legend) ? plugins.legend : {};
|
|
114
|
+
const legendLabels = isRecord(legend.labels) ? legend.labels : {};
|
|
115
|
+
const title = isRecord(plugins.title) ? plugins.title : {};
|
|
116
|
+
const scales = isRecord(base.scales) ? base.scales : {};
|
|
117
|
+
return {
|
|
118
|
+
responsive: true,
|
|
119
|
+
maintainAspectRatio: false,
|
|
120
|
+
color: theme.text,
|
|
121
|
+
...base,
|
|
122
|
+
plugins: {
|
|
123
|
+
...plugins,
|
|
124
|
+
legend: {
|
|
125
|
+
...legend,
|
|
126
|
+
labels: {
|
|
127
|
+
color: theme.text,
|
|
128
|
+
...legendLabels
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
title: {
|
|
132
|
+
color: theme.title,
|
|
133
|
+
...title
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
scales: mergeScales(scales, chartType, theme)
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function mergeScales(scales, chartType, theme) {
|
|
140
|
+
const names = /* @__PURE__ */ new Set([...defaultScaleNames(chartType), ...Object.keys(scales)]);
|
|
141
|
+
const merged = {};
|
|
142
|
+
for (const name of names) {
|
|
143
|
+
const scale = isRecord(scales[name]) ? scales[name] : {};
|
|
144
|
+
const ticks = isRecord(scale.ticks) ? scale.ticks : {};
|
|
145
|
+
const grid = isRecord(scale.grid) ? scale.grid : {};
|
|
146
|
+
const title = isRecord(scale.title) ? scale.title : {};
|
|
147
|
+
merged[name] = {
|
|
148
|
+
...scale,
|
|
149
|
+
ticks: {
|
|
150
|
+
color: theme.text,
|
|
151
|
+
...ticks
|
|
152
|
+
},
|
|
153
|
+
grid: {
|
|
154
|
+
color: theme.grid,
|
|
155
|
+
...grid
|
|
156
|
+
},
|
|
157
|
+
border: {
|
|
158
|
+
color: theme.border,
|
|
159
|
+
...isRecord(scale.border) ? scale.border : {}
|
|
160
|
+
},
|
|
161
|
+
title: {
|
|
162
|
+
color: theme.title,
|
|
163
|
+
...title
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return merged;
|
|
168
|
+
}
|
|
169
|
+
function defaultScaleNames(chartType) {
|
|
170
|
+
if (chartType === "bar" || chartType === "line" || chartType === "scatter") {
|
|
171
|
+
return ["x", "y"];
|
|
172
|
+
}
|
|
173
|
+
if (chartType === "bubble") {
|
|
174
|
+
return ["x", "y"];
|
|
175
|
+
}
|
|
176
|
+
if (chartType === "radar" || chartType === "polarArea") {
|
|
177
|
+
return ["r"];
|
|
178
|
+
}
|
|
179
|
+
return [];
|
|
180
|
+
}
|
|
181
|
+
function isRecord(value) {
|
|
182
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
183
|
+
}
|
|
184
|
+
var DEFAULT_CHART_HEIGHT, MAX_INLINE_CHART_HEIGHT, LIGHT_THEME, DARK_THEME;
|
|
100
185
|
var init_artifact_chart = __esm({
|
|
101
186
|
"src/components/chat/artifacts/artifact-chart.tsx"() {
|
|
102
|
-
|
|
187
|
+
init_utils();
|
|
103
188
|
DEFAULT_CHART_HEIGHT = 320;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
gridColor: "#e5e7eb",
|
|
111
|
-
domainColor: "#d1d5db",
|
|
112
|
-
tickColor: "#d1d5db"
|
|
113
|
-
},
|
|
114
|
-
view: { stroke: "transparent" },
|
|
115
|
-
legend: { labelColor: "#444", titleColor: "#111" }
|
|
189
|
+
MAX_INLINE_CHART_HEIGHT = 800;
|
|
190
|
+
LIGHT_THEME = {
|
|
191
|
+
text: "#444",
|
|
192
|
+
title: "#111",
|
|
193
|
+
grid: "#e5e7eb",
|
|
194
|
+
border: "#d1d5db"
|
|
116
195
|
};
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
gridColor: "#374151",
|
|
123
|
-
domainColor: "#4b5563",
|
|
124
|
-
tickColor: "#4b5563"
|
|
125
|
-
},
|
|
126
|
-
view: { stroke: "transparent" },
|
|
127
|
-
legend: { labelColor: "#cbd5e1", titleColor: "#f1f5f9" }
|
|
196
|
+
DARK_THEME = {
|
|
197
|
+
text: "#cbd5e1",
|
|
198
|
+
title: "#f1f5f9",
|
|
199
|
+
grid: "#374151",
|
|
200
|
+
border: "#4b5563"
|
|
128
201
|
};
|
|
129
202
|
}
|
|
130
203
|
});
|
|
@@ -139,9 +212,9 @@ function useAgentChatAdapterContext() {
|
|
|
139
212
|
}
|
|
140
213
|
return value;
|
|
141
214
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
215
|
+
|
|
216
|
+
// src/components/ui/button.tsx
|
|
217
|
+
init_utils();
|
|
145
218
|
var buttonVariants = classVarianceAuthority.cva(
|
|
146
219
|
"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",
|
|
147
220
|
{
|
|
@@ -190,10 +263,13 @@ function Button({
|
|
|
190
263
|
}
|
|
191
264
|
);
|
|
192
265
|
}
|
|
266
|
+
|
|
267
|
+
// src/components/ai-elements/conversation.tsx
|
|
268
|
+
init_utils();
|
|
193
269
|
var Conversation = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
194
270
|
useStickToBottom.StickToBottom,
|
|
195
271
|
{
|
|
196
|
-
className: cn("relative flex-1
|
|
272
|
+
className: cn("relative flex-1", className),
|
|
197
273
|
initial: "smooth",
|
|
198
274
|
resize: "smooth",
|
|
199
275
|
role: "log",
|
|
@@ -258,6 +334,9 @@ var ConversationScrollButton = ({
|
|
|
258
334
|
}
|
|
259
335
|
);
|
|
260
336
|
};
|
|
337
|
+
|
|
338
|
+
// src/components/ui/tooltip.tsx
|
|
339
|
+
init_utils();
|
|
261
340
|
function TooltipProvider({
|
|
262
341
|
delayDuration = 0,
|
|
263
342
|
...props
|
|
@@ -304,6 +383,9 @@ function TooltipContent({
|
|
|
304
383
|
}
|
|
305
384
|
) });
|
|
306
385
|
}
|
|
386
|
+
|
|
387
|
+
// src/components/ai-elements/message.tsx
|
|
388
|
+
init_utils();
|
|
307
389
|
var Message = ({ className, from, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
308
390
|
"div",
|
|
309
391
|
{
|
|
@@ -378,6 +460,12 @@ function CollapsibleContent({
|
|
|
378
460
|
}
|
|
379
461
|
);
|
|
380
462
|
}
|
|
463
|
+
|
|
464
|
+
// src/components/ai-elements/reasoning.tsx
|
|
465
|
+
init_utils();
|
|
466
|
+
|
|
467
|
+
// src/components/ai-elements/shimmer.tsx
|
|
468
|
+
init_utils();
|
|
381
469
|
var ShimmerComponent = ({
|
|
382
470
|
children,
|
|
383
471
|
as: Component = "p",
|
|
@@ -554,6 +642,9 @@ var ReasoningContent = react.memo(
|
|
|
554
642
|
Reasoning.displayName = "Reasoning";
|
|
555
643
|
ReasoningTrigger.displayName = "ReasoningTrigger";
|
|
556
644
|
ReasoningContent.displayName = "ReasoningContent";
|
|
645
|
+
|
|
646
|
+
// src/components/reui/timeline.tsx
|
|
647
|
+
init_utils();
|
|
557
648
|
var TimelineContext = react.createContext(
|
|
558
649
|
void 0
|
|
559
650
|
);
|
|
@@ -676,6 +767,62 @@ function TimelineSeparator({
|
|
|
676
767
|
}
|
|
677
768
|
);
|
|
678
769
|
}
|
|
770
|
+
init_utils();
|
|
771
|
+
|
|
772
|
+
// src/components/chat/tools/shared.ts
|
|
773
|
+
function statusColorClass(status) {
|
|
774
|
+
if (status === "running") return "bg-primary animate-pulse";
|
|
775
|
+
if (status === "error") return "bg-red-500";
|
|
776
|
+
if (status === "cancelled") return "bg-muted-foreground/40";
|
|
777
|
+
return "bg-emerald-500";
|
|
778
|
+
}
|
|
779
|
+
function effectiveStatus(tc) {
|
|
780
|
+
if (tc.cancelled) return "cancelled";
|
|
781
|
+
if (tc.status !== "complete" || !tc.result) return tc.status;
|
|
782
|
+
try {
|
|
783
|
+
const parsed = JSON.parse(tc.result);
|
|
784
|
+
if (parsed?.exit_code !== void 0 && parsed.exit_code !== 0) return "error";
|
|
785
|
+
if (parsed?.error) return "error";
|
|
786
|
+
if (parsed?.status === "blocked" || parsed?.status === "error") return "error";
|
|
787
|
+
if (parsed?.success === false) return "error";
|
|
788
|
+
} catch {
|
|
789
|
+
}
|
|
790
|
+
return "complete";
|
|
791
|
+
}
|
|
792
|
+
function formatArgs(args) {
|
|
793
|
+
try {
|
|
794
|
+
return JSON.stringify(JSON.parse(args), null, 2);
|
|
795
|
+
} catch {
|
|
796
|
+
return args;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
function parseArgs(args) {
|
|
800
|
+
try {
|
|
801
|
+
return JSON.parse(args);
|
|
802
|
+
} catch {
|
|
803
|
+
return null;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
function truncate(s, max) {
|
|
807
|
+
return s.length > max ? s.slice(0, max) + "\n... (truncated)" : s;
|
|
808
|
+
}
|
|
809
|
+
function toolErrorSummary(result, max = 180) {
|
|
810
|
+
if (!result) return "";
|
|
811
|
+
try {
|
|
812
|
+
const parsed = JSON.parse(result);
|
|
813
|
+
const error = typeof parsed?.error === "string" ? parsed.error : "";
|
|
814
|
+
if (error === "sandbox_unavailable") {
|
|
815
|
+
return "Sandbox is unavailable. Workspace commands cannot run right now.";
|
|
816
|
+
}
|
|
817
|
+
const reason = typeof parsed?.reason === "string" ? parsed.reason : "";
|
|
818
|
+
const message = typeof parsed?.message === "string" ? parsed.message : "";
|
|
819
|
+
const detail = reason || message;
|
|
820
|
+
const summary = error && detail && detail !== error ? `${error}: ${detail}` : error || detail;
|
|
821
|
+
return summary ? summary.replace(/\s+/g, " ").slice(0, max) : "";
|
|
822
|
+
} catch {
|
|
823
|
+
return "";
|
|
824
|
+
}
|
|
825
|
+
}
|
|
679
826
|
function CopyButton({ text }) {
|
|
680
827
|
const [copied, setCopied] = react.useState(false);
|
|
681
828
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -711,7 +858,8 @@ function parseTerminalResult(result, args) {
|
|
|
711
858
|
const hasOutput = typeof parsed?.output === "string";
|
|
712
859
|
const hasStdout = typeof parsed?.stdout === "string";
|
|
713
860
|
const hasExitCode = typeof parsed?.exit_code === "number";
|
|
714
|
-
|
|
861
|
+
const errorSummary = toolErrorSummary(result, 400);
|
|
862
|
+
if (!hasOutput && !hasStdout && !hasExitCode && !errorSummary) {
|
|
715
863
|
return null;
|
|
716
864
|
}
|
|
717
865
|
let command = "";
|
|
@@ -721,20 +869,20 @@ function parseTerminalResult(result, args) {
|
|
|
721
869
|
} catch {
|
|
722
870
|
}
|
|
723
871
|
const output = parsed.output ?? parsed.stdout ?? "";
|
|
724
|
-
const stderr = parsed.stderr ??
|
|
872
|
+
const stderr = parsed.stderr ?? errorSummary;
|
|
725
873
|
const combined = stderr ? `${output}
|
|
726
874
|
${stderr}`.trim() : output;
|
|
727
875
|
return {
|
|
728
876
|
output: combined,
|
|
729
|
-
exit_code: parsed.exit_code ?? 0,
|
|
730
|
-
error:
|
|
877
|
+
exit_code: parsed.exit_code ?? (errorSummary ? 1 : 0),
|
|
878
|
+
error: errorSummary || null,
|
|
731
879
|
command
|
|
732
880
|
};
|
|
733
881
|
} catch {
|
|
734
882
|
return null;
|
|
735
883
|
}
|
|
736
884
|
}
|
|
737
|
-
function TerminalCollapsible({ command, output, isRunning }) {
|
|
885
|
+
function TerminalCollapsible({ command, output, isRunning, hasError }) {
|
|
738
886
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
739
887
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
740
888
|
Collapsible,
|
|
@@ -744,7 +892,7 @@ function TerminalCollapsible({ command, output, isRunning }) {
|
|
|
744
892
|
className: "not-prose w-full",
|
|
745
893
|
children: [
|
|
746
894
|
/* @__PURE__ */ jsxRuntime.jsxs(CollapsibleTrigger, { className: "group/trigger flex w-fit items-center gap-2 text-sm transition-colors", children: [
|
|
747
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-left", children: isRunning ? /* @__PURE__ */ jsxRuntime.jsx(Shimmer, { as: "span", duration: 1, children: "Running command..." }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: "Command result" }) }),
|
|
895
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-left", children: isRunning ? /* @__PURE__ */ jsxRuntime.jsx(Shimmer, { as: "span", duration: 1, children: "Running command..." }) : hasError ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-destructive", children: "Command failed" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: "Command result" }) }),
|
|
748
896
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
749
897
|
lucideReact.ChevronDownIcon,
|
|
750
898
|
{
|
|
@@ -801,7 +949,8 @@ function TerminalToolBlock({ tc }) {
|
|
|
801
949
|
{
|
|
802
950
|
command: result.command,
|
|
803
951
|
output,
|
|
804
|
-
isRunning
|
|
952
|
+
isRunning,
|
|
953
|
+
hasError: result.exit_code !== 0 || Boolean(result.error)
|
|
805
954
|
}
|
|
806
955
|
);
|
|
807
956
|
}
|
|
@@ -816,6 +965,9 @@ function TerminalToolBlock({ tc }) {
|
|
|
816
965
|
}
|
|
817
966
|
return null;
|
|
818
967
|
}
|
|
968
|
+
|
|
969
|
+
// src/components/ui/scroll-area.tsx
|
|
970
|
+
init_utils();
|
|
819
971
|
function ScrollArea({
|
|
820
972
|
className,
|
|
821
973
|
children,
|
|
@@ -868,6 +1020,9 @@ function ScrollBar({
|
|
|
868
1020
|
}
|
|
869
1021
|
);
|
|
870
1022
|
}
|
|
1023
|
+
|
|
1024
|
+
// src/components/ai-elements/queue.tsx
|
|
1025
|
+
init_utils();
|
|
871
1026
|
var QueueItem = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
872
1027
|
"li",
|
|
873
1028
|
{
|
|
@@ -1020,6 +1175,9 @@ function TodoToolBlock({ tc }) {
|
|
|
1020
1175
|
}) }) })
|
|
1021
1176
|
] }) });
|
|
1022
1177
|
}
|
|
1178
|
+
|
|
1179
|
+
// src/components/ai-elements/code-block.tsx
|
|
1180
|
+
init_utils();
|
|
1023
1181
|
var isItalic = (fontStyle) => fontStyle && fontStyle & 1;
|
|
1024
1182
|
var isBold = (fontStyle) => fontStyle && fontStyle & 2;
|
|
1025
1183
|
var isUnderline = (fontStyle) => (
|
|
@@ -1309,6 +1467,9 @@ var CodeBlockCopyButton = ({
|
|
|
1309
1467
|
}
|
|
1310
1468
|
);
|
|
1311
1469
|
};
|
|
1470
|
+
|
|
1471
|
+
// src/components/ui/tabs.tsx
|
|
1472
|
+
init_utils();
|
|
1312
1473
|
function Tabs({
|
|
1313
1474
|
className,
|
|
1314
1475
|
orientation = "horizontal",
|
|
@@ -1388,6 +1549,12 @@ function TabsContent({
|
|
|
1388
1549
|
}
|
|
1389
1550
|
);
|
|
1390
1551
|
}
|
|
1552
|
+
|
|
1553
|
+
// src/components/ai-elements/sandbox.tsx
|
|
1554
|
+
init_utils();
|
|
1555
|
+
|
|
1556
|
+
// src/components/ui/badge.tsx
|
|
1557
|
+
init_utils();
|
|
1391
1558
|
var badgeVariants = classVarianceAuthority.cva(
|
|
1392
1559
|
"group/badge inline-flex w-fit shrink-0 items-center justify-center gap-1.5 overflow-hidden rounded-none border-0 bg-transparent px-0 py-0 text-[0.625rem] font-semibold tracking-widest whitespace-nowrap uppercase transition-colors focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-0 has-data-[icon=inline-start]:pl-0 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
|
|
1393
1560
|
{
|
|
@@ -1645,6 +1812,9 @@ function WebToolBlock({ tc }) {
|
|
|
1645
1812
|
displayText && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/70 truncate text-xs", children: displayText })
|
|
1646
1813
|
] });
|
|
1647
1814
|
}
|
|
1815
|
+
|
|
1816
|
+
// src/components/ui/dialog.tsx
|
|
1817
|
+
init_utils();
|
|
1648
1818
|
function Dialog({
|
|
1649
1819
|
...props
|
|
1650
1820
|
}) {
|
|
@@ -1774,6 +1944,12 @@ function DialogDescription({
|
|
|
1774
1944
|
}
|
|
1775
1945
|
);
|
|
1776
1946
|
}
|
|
1947
|
+
|
|
1948
|
+
// src/components/chat/tools/file-tools.tsx
|
|
1949
|
+
init_utils();
|
|
1950
|
+
|
|
1951
|
+
// src/components/chat/diff-viewer.tsx
|
|
1952
|
+
init_utils();
|
|
1777
1953
|
function splitChangeLines(change) {
|
|
1778
1954
|
const v = change.value;
|
|
1779
1955
|
if (v === "") return [];
|
|
@@ -2252,6 +2428,9 @@ function ListFilesBlock({ tc }) {
|
|
|
2252
2428
|
] })
|
|
2253
2429
|
] });
|
|
2254
2430
|
}
|
|
2431
|
+
|
|
2432
|
+
// src/components/ai-elements/terminal.tsx
|
|
2433
|
+
init_utils();
|
|
2255
2434
|
var TerminalContext = react.createContext({
|
|
2256
2435
|
autoScroll: true,
|
|
2257
2436
|
isStreaming: false,
|
|
@@ -2446,7 +2625,10 @@ var Terminal = ({
|
|
|
2446
2625
|
}
|
|
2447
2626
|
) });
|
|
2448
2627
|
};
|
|
2449
|
-
|
|
2628
|
+
|
|
2629
|
+
// src/components/chat/tools/process-tool.tsx
|
|
2630
|
+
init_utils();
|
|
2631
|
+
function parseArgs2(args) {
|
|
2450
2632
|
try {
|
|
2451
2633
|
return JSON.parse(args);
|
|
2452
2634
|
} catch {
|
|
@@ -2670,7 +2852,7 @@ function OutputPreview({ output }) {
|
|
|
2670
2852
|
}
|
|
2671
2853
|
function ProcessToolBlock({ tc }) {
|
|
2672
2854
|
const isRunning = tc.status === "running";
|
|
2673
|
-
const args =
|
|
2855
|
+
const args = parseArgs2(tc.args);
|
|
2674
2856
|
const result = parseResult(tc.result);
|
|
2675
2857
|
const action = args.action || "unknown";
|
|
2676
2858
|
const actionLabel = {
|
|
@@ -2740,6 +2922,12 @@ function ProcessToolBlock({ tc }) {
|
|
|
2740
2922
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-background pb-1", children: content })
|
|
2741
2923
|
] });
|
|
2742
2924
|
}
|
|
2925
|
+
|
|
2926
|
+
// src/components/chat/tools/expert-tool.tsx
|
|
2927
|
+
init_utils();
|
|
2928
|
+
|
|
2929
|
+
// src/components/ui/textarea.tsx
|
|
2930
|
+
init_utils();
|
|
2743
2931
|
function Textarea({ className, ...props }) {
|
|
2744
2932
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2745
2933
|
"textarea",
|
|
@@ -2753,44 +2941,6 @@ function Textarea({ className, ...props }) {
|
|
|
2753
2941
|
}
|
|
2754
2942
|
);
|
|
2755
2943
|
}
|
|
2756
|
-
|
|
2757
|
-
// src/components/chat/tools/shared.ts
|
|
2758
|
-
function statusColorClass(status) {
|
|
2759
|
-
if (status === "running") return "bg-primary animate-pulse";
|
|
2760
|
-
if (status === "error") return "bg-red-500";
|
|
2761
|
-
if (status === "cancelled") return "bg-muted-foreground/40";
|
|
2762
|
-
return "bg-emerald-500";
|
|
2763
|
-
}
|
|
2764
|
-
function effectiveStatus(tc) {
|
|
2765
|
-
if (tc.cancelled) return "cancelled";
|
|
2766
|
-
if (tc.status !== "complete" || !tc.result) return tc.status;
|
|
2767
|
-
try {
|
|
2768
|
-
const parsed = JSON.parse(tc.result);
|
|
2769
|
-
if (parsed?.exit_code !== void 0 && parsed.exit_code !== 0) return "error";
|
|
2770
|
-
if (parsed?.error) return "error";
|
|
2771
|
-
if (parsed?.status === "blocked" || parsed?.status === "error") return "error";
|
|
2772
|
-
if (parsed?.success === false) return "error";
|
|
2773
|
-
} catch {
|
|
2774
|
-
}
|
|
2775
|
-
return "complete";
|
|
2776
|
-
}
|
|
2777
|
-
function formatArgs(args) {
|
|
2778
|
-
try {
|
|
2779
|
-
return JSON.stringify(JSON.parse(args), null, 2);
|
|
2780
|
-
} catch {
|
|
2781
|
-
return args;
|
|
2782
|
-
}
|
|
2783
|
-
}
|
|
2784
|
-
function parseArgs2(args) {
|
|
2785
|
-
try {
|
|
2786
|
-
return JSON.parse(args);
|
|
2787
|
-
} catch {
|
|
2788
|
-
return null;
|
|
2789
|
-
}
|
|
2790
|
-
}
|
|
2791
|
-
function truncate(s, max) {
|
|
2792
|
-
return s.length > max ? s.slice(0, max) + "\n... (truncated)" : s;
|
|
2793
|
-
}
|
|
2794
2944
|
var MAX_REASON_LENGTH = 500;
|
|
2795
2945
|
function ExpertToolBlock({ tc }) {
|
|
2796
2946
|
const [expanded, setExpanded] = react.useState(false);
|
|
@@ -2826,7 +2976,7 @@ function ExpertToolBlock({ tc }) {
|
|
|
2826
2976
|
}
|
|
2827
2977
|
void submit("up");
|
|
2828
2978
|
};
|
|
2829
|
-
const args =
|
|
2979
|
+
const args = parseArgs(tc.args) ?? {};
|
|
2830
2980
|
const expertName = args.expert ?? null;
|
|
2831
2981
|
const question = args.question ?? args.prompt ?? "";
|
|
2832
2982
|
const result = parseExpertResult(tc.result);
|
|
@@ -2938,7 +3088,7 @@ function ExpertToolBlock({ tc }) {
|
|
|
2938
3088
|
}
|
|
2939
3089
|
function parseExpertResult(result) {
|
|
2940
3090
|
if (!result) return null;
|
|
2941
|
-
const parsed =
|
|
3091
|
+
const parsed = parseArgs(result);
|
|
2942
3092
|
if (parsed) {
|
|
2943
3093
|
return {
|
|
2944
3094
|
...parsed,
|
|
@@ -3045,11 +3195,11 @@ function ReasonForm({
|
|
|
3045
3195
|
] });
|
|
3046
3196
|
}
|
|
3047
3197
|
function SkillsListBlock({ tc }) {
|
|
3048
|
-
const args =
|
|
3198
|
+
const args = parseArgs(tc.args) ?? {};
|
|
3049
3199
|
const filter = args.category ? `category: ${args.category}` : "all";
|
|
3050
3200
|
let summary = "";
|
|
3051
3201
|
if (tc.result) {
|
|
3052
|
-
const parsed =
|
|
3202
|
+
const parsed = parseArgs(tc.result);
|
|
3053
3203
|
if (parsed?.count !== void 0) {
|
|
3054
3204
|
summary = `${parsed.count} skill${parsed.count === 1 ? "" : "s"}`;
|
|
3055
3205
|
}
|
|
@@ -3064,11 +3214,11 @@ function SkillsListBlock({ tc }) {
|
|
|
3064
3214
|
] });
|
|
3065
3215
|
}
|
|
3066
3216
|
function SkillViewBlock({ tc }) {
|
|
3067
|
-
const args =
|
|
3217
|
+
const args = parseArgs(tc.args) ?? {};
|
|
3068
3218
|
const target = args.file_path ? `${args.name ?? "?"}/${args.file_path}` : args.name ?? "?";
|
|
3069
3219
|
let summary = "";
|
|
3070
3220
|
if (tc.result) {
|
|
3071
|
-
const parsed =
|
|
3221
|
+
const parsed = parseArgs(tc.result);
|
|
3072
3222
|
if (parsed?.staged_at) {
|
|
3073
3223
|
summary = `staged at ${parsed.staged_at}`;
|
|
3074
3224
|
} else if (parsed?.token_estimate) {
|
|
@@ -3084,6 +3234,12 @@ function SkillViewBlock({ tc }) {
|
|
|
3084
3234
|
] })
|
|
3085
3235
|
] });
|
|
3086
3236
|
}
|
|
3237
|
+
|
|
3238
|
+
// src/components/chat/tools/clarify-tool.tsx
|
|
3239
|
+
init_utils();
|
|
3240
|
+
|
|
3241
|
+
// src/components/ui/input.tsx
|
|
3242
|
+
init_utils();
|
|
3087
3243
|
function Input({ className, type, ...props }) {
|
|
3088
3244
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3089
3245
|
"input",
|
|
@@ -3115,7 +3271,7 @@ function buildAnswer(q, sel) {
|
|
|
3115
3271
|
}
|
|
3116
3272
|
function ClarifyToolBlock({ tc }) {
|
|
3117
3273
|
const { adapter, sessionId } = useAgentChatAdapterContext();
|
|
3118
|
-
const args = react.useMemo(() =>
|
|
3274
|
+
const args = react.useMemo(() => parseArgs(tc.args), [tc.args]);
|
|
3119
3275
|
const questions = args?.questions ?? [];
|
|
3120
3276
|
const [active, setActive] = react.useState(0);
|
|
3121
3277
|
const [selections, setSelections] = react.useState(
|
|
@@ -3397,21 +3553,24 @@ function ClarifyLocked({
|
|
|
3397
3553
|
] });
|
|
3398
3554
|
}
|
|
3399
3555
|
function ArtifactToolBlock({ tc }) {
|
|
3400
|
-
const args =
|
|
3556
|
+
const args = parseArgs(tc.args) ?? {};
|
|
3401
3557
|
const status = effectiveStatus(tc);
|
|
3402
|
-
const label = status === "running" ? "Creating artifact\u2026" : status === "error" ? "
|
|
3558
|
+
const label = status === "running" ? "Creating artifact\u2026" : status === "error" ? "Creating artifact\u2026" : "Created";
|
|
3403
3559
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-sm ", children: [
|
|
3404
3560
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: label }),
|
|
3405
3561
|
args.name && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground truncate", children: args.name })
|
|
3406
3562
|
] });
|
|
3407
3563
|
}
|
|
3564
|
+
|
|
3565
|
+
// src/components/chat/tools/delegate-tool.tsx
|
|
3566
|
+
init_utils();
|
|
3408
3567
|
function firstLine(s) {
|
|
3409
3568
|
const idx = s.indexOf("\n");
|
|
3410
3569
|
return idx === -1 ? s : s.slice(0, idx);
|
|
3411
3570
|
}
|
|
3412
3571
|
function DelegateToolBlock({ tc }) {
|
|
3413
3572
|
const [expanded, setExpanded] = react.useState(false);
|
|
3414
|
-
const args =
|
|
3573
|
+
const args = parseArgs(tc.args);
|
|
3415
3574
|
const goal = args?.goal ?? "";
|
|
3416
3575
|
const context = args?.context ?? "";
|
|
3417
3576
|
const agentType = args?.agent_type;
|
|
@@ -3505,6 +3664,7 @@ function DelegateToolBlock({ tc }) {
|
|
|
3505
3664
|
] })
|
|
3506
3665
|
] });
|
|
3507
3666
|
}
|
|
3667
|
+
init_utils();
|
|
3508
3668
|
var ACTION_VERB = {
|
|
3509
3669
|
add: "Saved",
|
|
3510
3670
|
replace: "Updated",
|
|
@@ -3521,8 +3681,8 @@ var TARGET_LABEL = {
|
|
|
3521
3681
|
};
|
|
3522
3682
|
function MemoryToolBlock({ tc }) {
|
|
3523
3683
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
3524
|
-
const args =
|
|
3525
|
-
const result = tc.result ?
|
|
3684
|
+
const args = parseArgs(tc.args) ?? {};
|
|
3685
|
+
const result = tc.result ? parseArgs(tc.result) : null;
|
|
3526
3686
|
const action = args.action ?? "add";
|
|
3527
3687
|
const target = args.target ?? "memory";
|
|
3528
3688
|
const verb = ACTION_VERB[action] ?? action;
|
|
@@ -3600,8 +3760,8 @@ var ACTION_LABEL = {
|
|
|
3600
3760
|
remove_file: "Remove skill file"
|
|
3601
3761
|
};
|
|
3602
3762
|
function SkillManageToolBlock({ tc }) {
|
|
3603
|
-
const args =
|
|
3604
|
-
const result = tc.result ?
|
|
3763
|
+
const args = parseArgs(tc.args) ?? {};
|
|
3764
|
+
const result = tc.result ? parseArgs(tc.result) : null;
|
|
3605
3765
|
const action = args.action ?? "manage";
|
|
3606
3766
|
const label = ACTION_LABEL[action] ?? "Manage skill";
|
|
3607
3767
|
const target = args.file_path ? `${args.name ?? "?"}/${args.file_path}` : args.name ?? "?";
|
|
@@ -3622,8 +3782,8 @@ function firstLine2(value) {
|
|
|
3622
3782
|
return (index === -1 ? value : value.slice(0, index)).trim();
|
|
3623
3783
|
}
|
|
3624
3784
|
function CoordinatorToolBlock({ tc }) {
|
|
3625
|
-
const args =
|
|
3626
|
-
const result = tc.result ?
|
|
3785
|
+
const args = parseArgs(tc.args) ?? {};
|
|
3786
|
+
const result = tc.result ? parseArgs(tc.result) : null;
|
|
3627
3787
|
const failed = Boolean(result?.error);
|
|
3628
3788
|
let label = "Worker";
|
|
3629
3789
|
let target = "";
|
|
@@ -3656,6 +3816,9 @@ function CoordinatorToolBlock({ tc }) {
|
|
|
3656
3816
|
] })
|
|
3657
3817
|
] });
|
|
3658
3818
|
}
|
|
3819
|
+
|
|
3820
|
+
// src/components/chat/tools/default-tool.tsx
|
|
3821
|
+
init_utils();
|
|
3659
3822
|
var TOOL_LABELS = {
|
|
3660
3823
|
kb_list_pages: "Knowledge Base",
|
|
3661
3824
|
kb_read_page: "Read KB Page",
|
|
@@ -3810,6 +3973,9 @@ function AssistantMessage({
|
|
|
3810
3973
|
] })
|
|
3811
3974
|
] }) });
|
|
3812
3975
|
}
|
|
3976
|
+
|
|
3977
|
+
// src/components/ui/hover-card.tsx
|
|
3978
|
+
init_utils();
|
|
3813
3979
|
function HoverCard({
|
|
3814
3980
|
...props
|
|
3815
3981
|
}) {
|
|
@@ -3840,6 +4006,9 @@ function HoverCardContent({
|
|
|
3840
4006
|
}
|
|
3841
4007
|
) });
|
|
3842
4008
|
}
|
|
4009
|
+
|
|
4010
|
+
// src/components/ui/progress.tsx
|
|
4011
|
+
init_utils();
|
|
3843
4012
|
function Progress({
|
|
3844
4013
|
className,
|
|
3845
4014
|
value,
|
|
@@ -3865,6 +4034,9 @@ function Progress({
|
|
|
3865
4034
|
}
|
|
3866
4035
|
);
|
|
3867
4036
|
}
|
|
4037
|
+
|
|
4038
|
+
// src/components/ai-elements/context.tsx
|
|
4039
|
+
init_utils();
|
|
3868
4040
|
var PERCENT_MAX = 100;
|
|
3869
4041
|
var ICON_RADIUS = 10;
|
|
3870
4042
|
var ICON_VIEWBOX = 24;
|
|
@@ -4129,6 +4301,12 @@ var ContextCacheUsage = ({
|
|
|
4129
4301
|
}
|
|
4130
4302
|
);
|
|
4131
4303
|
};
|
|
4304
|
+
|
|
4305
|
+
// src/components/ui/command.tsx
|
|
4306
|
+
init_utils();
|
|
4307
|
+
|
|
4308
|
+
// src/components/ui/input-group.tsx
|
|
4309
|
+
init_utils();
|
|
4132
4310
|
function InputGroup({ className, ...props }) {
|
|
4133
4311
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4134
4312
|
"div",
|
|
@@ -4313,6 +4491,9 @@ function CommandItem({
|
|
|
4313
4491
|
}
|
|
4314
4492
|
);
|
|
4315
4493
|
}
|
|
4494
|
+
|
|
4495
|
+
// src/components/ui/dropdown-menu.tsx
|
|
4496
|
+
init_utils();
|
|
4316
4497
|
function DropdownMenu({
|
|
4317
4498
|
...props
|
|
4318
4499
|
}) {
|
|
@@ -4366,9 +4547,15 @@ function DropdownMenuItem({
|
|
|
4366
4547
|
}
|
|
4367
4548
|
);
|
|
4368
4549
|
}
|
|
4550
|
+
|
|
4551
|
+
// src/components/ui/spinner.tsx
|
|
4552
|
+
init_utils();
|
|
4369
4553
|
function Spinner({ className, ...props }) {
|
|
4370
4554
|
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2Icon, { role: "status", "aria-label": "Loading", className: cn("size-4 animate-spin", className), ...props });
|
|
4371
4555
|
}
|
|
4556
|
+
|
|
4557
|
+
// src/components/ai-elements/prompt-input.tsx
|
|
4558
|
+
init_utils();
|
|
4372
4559
|
var convertBlobUrlToDataUrl = async (url) => {
|
|
4373
4560
|
try {
|
|
4374
4561
|
const response = await fetch(url);
|
|
@@ -5066,6 +5253,9 @@ var PromptInputSubmit = ({
|
|
|
5066
5253
|
}
|
|
5067
5254
|
);
|
|
5068
5255
|
};
|
|
5256
|
+
|
|
5257
|
+
// src/components/ui/popover.tsx
|
|
5258
|
+
init_utils();
|
|
5069
5259
|
function Popover({
|
|
5070
5260
|
...props
|
|
5071
5261
|
}) {
|
|
@@ -5313,6 +5503,9 @@ function ChatComposerInner({
|
|
|
5313
5503
|
)
|
|
5314
5504
|
] });
|
|
5315
5505
|
}
|
|
5506
|
+
|
|
5507
|
+
// src/components/ai-elements/artifact.tsx
|
|
5508
|
+
init_utils();
|
|
5316
5509
|
var Artifact = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5317
5510
|
"div",
|
|
5318
5511
|
{
|
|
@@ -5433,6 +5626,9 @@ function ArtifactTable({ spec }) {
|
|
|
5433
5626
|
)) })
|
|
5434
5627
|
] }) });
|
|
5435
5628
|
}
|
|
5629
|
+
|
|
5630
|
+
// src/components/chat/artifacts/artifact-html.tsx
|
|
5631
|
+
init_utils();
|
|
5436
5632
|
var DEFAULT_HEIGHT_PX = 480;
|
|
5437
5633
|
var EXPANDED_HEIGHT_PX = 800;
|
|
5438
5634
|
var MIN_ZOOM = 0.5;
|
|
@@ -5574,7 +5770,7 @@ function exportArtifact(payload) {
|
|
|
5574
5770
|
};
|
|
5575
5771
|
case "chart":
|
|
5576
5772
|
return {
|
|
5577
|
-
text: JSON.stringify(payload.spec.
|
|
5773
|
+
text: JSON.stringify(payload.spec.chart_js, null, 2),
|
|
5578
5774
|
mime: "application/json",
|
|
5579
5775
|
extension: "json"
|
|
5580
5776
|
};
|
|
@@ -5760,7 +5956,7 @@ function ArtifactBody({
|
|
|
5760
5956
|
react.Suspense,
|
|
5761
5957
|
{
|
|
5762
5958
|
fallback: /* @__PURE__ */ jsxRuntime.jsx(Shimmer, { duration: 5, className: "text-sm text-muted-foreground", children: "Loading chart\u2026" }),
|
|
5763
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ArtifactChart2, { spec: payload.spec })
|
|
5959
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ArtifactChart2, { spec: payload.spec, fill })
|
|
5764
5960
|
}
|
|
5765
5961
|
);
|
|
5766
5962
|
case "html":
|
|
@@ -5769,6 +5965,7 @@ function ArtifactBody({
|
|
|
5769
5965
|
return /* @__PURE__ */ jsxRuntime.jsx(ArtifactSvg, { spec: payload.spec });
|
|
5770
5966
|
}
|
|
5771
5967
|
}
|
|
5968
|
+
init_utils();
|
|
5772
5969
|
var ErrorMessage = react.memo(function ErrorMessage2({
|
|
5773
5970
|
errorInfo,
|
|
5774
5971
|
onRetry,
|
|
@@ -5849,6 +6046,9 @@ var ErrorMessage = react.memo(function ErrorMessage2({
|
|
|
5849
6046
|
}
|
|
5850
6047
|
);
|
|
5851
6048
|
});
|
|
6049
|
+
|
|
6050
|
+
// src/components/chat/chat-thread.tsx
|
|
6051
|
+
init_utils();
|
|
5852
6052
|
function messageToEntries(msg, isLast) {
|
|
5853
6053
|
if (msg.role === "system") {
|
|
5854
6054
|
if (msg.systemKind === "skill_invoked") {
|
|
@@ -5980,7 +6180,7 @@ function OrphanSystemMarker({
|
|
|
5980
6180
|
);
|
|
5981
6181
|
}
|
|
5982
6182
|
if (message.systemKind === "error" && message.errorInfo) {
|
|
5983
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto my-2 w-full max-w-4xl
|
|
6183
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto my-2 w-full max-w-4xl", children: /* @__PURE__ */ jsxRuntime.jsx(ErrorMessage, { errorInfo: message.errorInfo, onRetry }) });
|
|
5984
6184
|
}
|
|
5985
6185
|
return null;
|
|
5986
6186
|
}
|
|
@@ -6034,17 +6234,24 @@ function TimelineEntryItem({
|
|
|
6034
6234
|
] });
|
|
6035
6235
|
}
|
|
6036
6236
|
if (entry.kind === "tool") {
|
|
6237
|
+
const rawStatus = effectiveStatus(entry.tc);
|
|
6238
|
+
const hideArtifactFailure = rawStatus === "error" && entry.tc.toolName === "create_artifact";
|
|
6239
|
+
const indicatorStatus = hideArtifactFailure ? "running" : rawStatus;
|
|
6240
|
+
const failureSummary = rawStatus === "error" && !hideArtifactFailure ? toolErrorSummary(entry.tc.result) : "";
|
|
6037
6241
|
return /* @__PURE__ */ jsxRuntime.jsxs(TimelineItem, { step, children: [
|
|
6038
6242
|
/* @__PURE__ */ jsxRuntime.jsxs(TimelineHeader, { children: [
|
|
6039
6243
|
/* @__PURE__ */ jsxRuntime.jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
|
|
6040
6244
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6041
6245
|
TimelineIndicator,
|
|
6042
6246
|
{
|
|
6043
|
-
className: cn("size-2 border-none", statusColorClass(
|
|
6247
|
+
className: cn("size-2 border-none", statusColorClass(indicatorStatus))
|
|
6044
6248
|
}
|
|
6045
6249
|
)
|
|
6046
6250
|
] }),
|
|
6047
|
-
/* @__PURE__ */ jsxRuntime.jsx(TimelineContent, { children: entry.tc.cancelled ? /* @__PURE__ */ jsxRuntime.jsx(CancelledToolRow, { tc: entry.tc }) : /* @__PURE__ */ jsxRuntime.
|
|
6251
|
+
/* @__PURE__ */ jsxRuntime.jsx(TimelineContent, { children: entry.tc.cancelled ? /* @__PURE__ */ jsxRuntime.jsx(CancelledToolRow, { tc: entry.tc }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
6252
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolCallBlock, { tc: entry.tc, onFileSelect }),
|
|
6253
|
+
failureSummary ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-full truncate text-xs text-destructive", title: failureSummary, children: failureSummary }) : null
|
|
6254
|
+
] }) })
|
|
6048
6255
|
] });
|
|
6049
6256
|
}
|
|
6050
6257
|
if (entry.kind === "text") {
|
|
@@ -6095,13 +6302,14 @@ function TimelineEntryItem({
|
|
|
6095
6302
|
/* @__PURE__ */ jsxRuntime.jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
|
|
6096
6303
|
/* @__PURE__ */ jsxRuntime.jsx(TimelineIndicator, { className: "size-2 border-none bg-primary animate-pulse" })
|
|
6097
6304
|
] }),
|
|
6098
|
-
/* @__PURE__ */ jsxRuntime.jsx(TimelineContent, { children: /* @__PURE__ */ jsxRuntime.jsx(Shimmer, { duration:
|
|
6305
|
+
/* @__PURE__ */ jsxRuntime.jsx(TimelineContent, { children: /* @__PURE__ */ jsxRuntime.jsx(Shimmer, { duration: 3, spread: 3, className: "text-sm", children: "Working on it..." }) })
|
|
6099
6306
|
] });
|
|
6100
6307
|
}
|
|
6101
6308
|
function AssistantGroup({
|
|
6102
6309
|
messages,
|
|
6103
6310
|
lastGlobalIndex,
|
|
6104
6311
|
totalMessages,
|
|
6312
|
+
isRunning,
|
|
6105
6313
|
sessionId,
|
|
6106
6314
|
onFileSelect,
|
|
6107
6315
|
onRetry
|
|
@@ -6111,6 +6319,15 @@ function AssistantGroup({
|
|
|
6111
6319
|
const isLast = i === messages.length - 1 && lastGlobalIndex === totalMessages - 1;
|
|
6112
6320
|
entries.push(...messageToEntries(messages[i], isLast));
|
|
6113
6321
|
}
|
|
6322
|
+
const isTailGroup = lastGlobalIndex === totalMessages - 1;
|
|
6323
|
+
const lastEntry = entries[entries.length - 1];
|
|
6324
|
+
const hasRunningTool = entries.some(
|
|
6325
|
+
(e) => e.kind === "tool" && e.tc.status === "running"
|
|
6326
|
+
);
|
|
6327
|
+
const tailMsg = messages[messages.length - 1];
|
|
6328
|
+
if (isTailGroup && isRunning && !hasRunningTool && lastEntry?.kind !== "thinking") {
|
|
6329
|
+
entries.push({ kind: "thinking", key: `${tailMsg.id}-tail-thinking` });
|
|
6330
|
+
}
|
|
6114
6331
|
const tail = messages[messages.length - 1];
|
|
6115
6332
|
const showErrorInfo = tail && tail.role === "assistant" && tail.status === "error" && !!tail.errorInfo;
|
|
6116
6333
|
return /* @__PURE__ */ jsxRuntime.jsx(Message, { from: "assistant", children: /* @__PURE__ */ jsxRuntime.jsxs(MessageContent, { children: [
|
|
@@ -6162,6 +6379,7 @@ function ChatThread({
|
|
|
6162
6379
|
sessionId,
|
|
6163
6380
|
messages,
|
|
6164
6381
|
isRunning,
|
|
6382
|
+
isLoadingHistory = false,
|
|
6165
6383
|
onSend,
|
|
6166
6384
|
onStop,
|
|
6167
6385
|
onFileSelect,
|
|
@@ -6184,7 +6402,14 @@ function ChatThread({
|
|
|
6184
6402
|
}, [messages]);
|
|
6185
6403
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col overflow-hidden bg-background text-sm", children: [
|
|
6186
6404
|
/* @__PURE__ */ jsxRuntime.jsxs(Conversation, { className: "relative flex-1 min-h-0", children: [
|
|
6187
|
-
/* @__PURE__ */ jsxRuntime.jsx(ConversationContent, { className: "mx-auto w-full max-w-
|
|
6405
|
+
/* @__PURE__ */ jsxRuntime.jsx(ConversationContent, { className: "mx-auto w-full max-w-4xl", children: messages.length === 0 && isLoadingHistory ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6406
|
+
ConversationEmptyState,
|
|
6407
|
+
{
|
|
6408
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquareIcon, { className: "size-8 opacity-40" }),
|
|
6409
|
+
title: "Loading conversation",
|
|
6410
|
+
description: "Fetching the session history."
|
|
6411
|
+
}
|
|
6412
|
+
) : messages.length === 0 && !disabled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6188
6413
|
ConversationEmptyState,
|
|
6189
6414
|
{
|
|
6190
6415
|
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquareIcon, { className: "size-8 opacity-40" }),
|
|
@@ -6226,6 +6451,7 @@ function ChatThread({
|
|
|
6226
6451
|
messages: group.messages,
|
|
6227
6452
|
lastGlobalIndex: group.lastGlobalIndex,
|
|
6228
6453
|
totalMessages: messages.length,
|
|
6454
|
+
isRunning,
|
|
6229
6455
|
sessionId,
|
|
6230
6456
|
onFileSelect,
|
|
6231
6457
|
onRetry: groupRetry
|
|
@@ -6233,11 +6459,11 @@ function ChatThread({
|
|
|
6233
6459
|
group.messages[0].id
|
|
6234
6460
|
);
|
|
6235
6461
|
}),
|
|
6236
|
-
isRunning && messages.length > 0 && messages[messages.length - 1].role === "user" && /* @__PURE__ */ jsxRuntime.jsx(Message, { from: "assistant", children: /* @__PURE__ */ jsxRuntime.jsx(MessageContent, { children: /* @__PURE__ */ jsxRuntime.jsx(Shimmer, { duration:
|
|
6462
|
+
isRunning && messages.length > 0 && messages[messages.length - 1].role === "user" && /* @__PURE__ */ jsxRuntime.jsx(Message, { from: "assistant", children: /* @__PURE__ */ jsxRuntime.jsx(MessageContent, { children: /* @__PURE__ */ jsxRuntime.jsx(Shimmer, { duration: 3, spread: 3, className: "text-sm", children: "Working on it..." }) }) })
|
|
6237
6463
|
] }) }),
|
|
6238
6464
|
/* @__PURE__ */ jsxRuntime.jsx(ConversationScrollButton, {})
|
|
6239
6465
|
] }),
|
|
6240
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto w-full max-w-
|
|
6466
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto w-full max-w-4xl px-6 pb-5 pt-3", children: [
|
|
6241
6467
|
retryIndicator && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsx(RetryBanner, { indicator: retryIndicator }) }),
|
|
6242
6468
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6243
6469
|
ChatComposer,
|
|
@@ -6252,6 +6478,9 @@ function ChatThread({
|
|
|
6252
6478
|
] })
|
|
6253
6479
|
] });
|
|
6254
6480
|
}
|
|
6481
|
+
|
|
6482
|
+
// src/components/ai-elements/file-tree.tsx
|
|
6483
|
+
init_utils();
|
|
6255
6484
|
var noop = () => {
|
|
6256
6485
|
};
|
|
6257
6486
|
var FileTreeContext = react.createContext({
|
|
@@ -6418,6 +6647,9 @@ function FileTreeFile({
|
|
|
6418
6647
|
}
|
|
6419
6648
|
);
|
|
6420
6649
|
}
|
|
6650
|
+
|
|
6651
|
+
// src/components/ui/skeleton.tsx
|
|
6652
|
+
init_utils();
|
|
6421
6653
|
function Skeleton({ className, ...props }) {
|
|
6422
6654
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6423
6655
|
"div",
|
|
@@ -6428,6 +6660,9 @@ function Skeleton({ className, ...props }) {
|
|
|
6428
6660
|
);
|
|
6429
6661
|
}
|
|
6430
6662
|
|
|
6663
|
+
// src/components/workspace/workspace-panel.tsx
|
|
6664
|
+
init_utils();
|
|
6665
|
+
|
|
6431
6666
|
// src/lib/format.ts
|
|
6432
6667
|
function formatFileSize(bytes) {
|
|
6433
6668
|
if (bytes < 1024) return `${bytes} B`;
|
|
@@ -6838,7 +7073,7 @@ function formatPdfPreviewError(error) {
|
|
|
6838
7073
|
return error instanceof Error ? error.message : "Failed to render PDF preview.";
|
|
6839
7074
|
}
|
|
6840
7075
|
var SKELETON_WIDTHS2 = [75, 60, 90, 65, 80, 70, 85, 55];
|
|
6841
|
-
var DEFAULT_WIDTH =
|
|
7076
|
+
var DEFAULT_WIDTH = 400;
|
|
6842
7077
|
var MIN_WIDTH = 300;
|
|
6843
7078
|
var MAX_WIDTH = 900;
|
|
6844
7079
|
function collectExpandedPaths(entries, depth = 0) {
|
|
@@ -6920,6 +7155,9 @@ function WorkspacePanel({
|
|
|
6920
7155
|
sessionId,
|
|
6921
7156
|
selectedPath,
|
|
6922
7157
|
onSelectedPathChange,
|
|
7158
|
+
collapsed = false,
|
|
7159
|
+
onCollapsedChange,
|
|
7160
|
+
refreshSignal = 0,
|
|
6923
7161
|
disabled = false
|
|
6924
7162
|
}) {
|
|
6925
7163
|
const fileInputRef = react.useRef(null);
|
|
@@ -6999,6 +7237,13 @@ function WorkspacePanel({
|
|
|
6999
7237
|
react.useEffect(() => {
|
|
7000
7238
|
void fetchTree();
|
|
7001
7239
|
}, [fetchTree]);
|
|
7240
|
+
react.useEffect(() => {
|
|
7241
|
+
if (!sessionId || refreshSignal === 0) return;
|
|
7242
|
+
const timer = setTimeout(() => {
|
|
7243
|
+
void fetchTree();
|
|
7244
|
+
}, 300);
|
|
7245
|
+
return () => clearTimeout(timer);
|
|
7246
|
+
}, [refreshSignal, sessionId, fetchTree]);
|
|
7002
7247
|
react.useEffect(() => {
|
|
7003
7248
|
if (!sessionId) {
|
|
7004
7249
|
setFile(null);
|
|
@@ -7114,6 +7359,25 @@ function WorkspacePanel({
|
|
|
7114
7359
|
window.removeEventListener("mouseup", onMouseUp);
|
|
7115
7360
|
};
|
|
7116
7361
|
}, []);
|
|
7362
|
+
if (collapsed) {
|
|
7363
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7364
|
+
"aside",
|
|
7365
|
+
{
|
|
7366
|
+
role: "button",
|
|
7367
|
+
tabIndex: 0,
|
|
7368
|
+
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",
|
|
7369
|
+
"aria-label": "Expand workspace",
|
|
7370
|
+
onClick: () => onCollapsedChange?.(false),
|
|
7371
|
+
onKeyDown: (event) => {
|
|
7372
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
7373
|
+
event.preventDefault();
|
|
7374
|
+
onCollapsedChange?.(false);
|
|
7375
|
+
}
|
|
7376
|
+
},
|
|
7377
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FolderOpenIcon, { className: "size-4 text-amber-500" })
|
|
7378
|
+
}
|
|
7379
|
+
);
|
|
7380
|
+
}
|
|
7117
7381
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7118
7382
|
"aside",
|
|
7119
7383
|
{
|
|
@@ -7146,6 +7410,19 @@ function WorkspacePanel({
|
|
|
7146
7410
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-sm font-medium text-foreground", children: rootName }),
|
|
7147
7411
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-xs text-faint", children: "Workspace" })
|
|
7148
7412
|
] }),
|
|
7413
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
7414
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7415
|
+
Button,
|
|
7416
|
+
{
|
|
7417
|
+
variant: "ghost",
|
|
7418
|
+
size: "icon-sm",
|
|
7419
|
+
onClick: () => onCollapsedChange?.(true),
|
|
7420
|
+
"aria-label": "Collapse workspace",
|
|
7421
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "size-4" })
|
|
7422
|
+
}
|
|
7423
|
+
) }),
|
|
7424
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "bottom", children: "Collapse" })
|
|
7425
|
+
] }),
|
|
7149
7426
|
/* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
7150
7427
|
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7151
7428
|
Button,
|
|
@@ -7307,6 +7584,12 @@ function ConfirmDialog({
|
|
|
7307
7584
|
}
|
|
7308
7585
|
|
|
7309
7586
|
// src/runtime/events.ts
|
|
7587
|
+
var WORKSPACE_MUTATING_TOOLS = /* @__PURE__ */ new Set([
|
|
7588
|
+
"terminal",
|
|
7589
|
+
"write_file",
|
|
7590
|
+
"patch",
|
|
7591
|
+
"execute_code"
|
|
7592
|
+
]);
|
|
7310
7593
|
var AGENT_CHAT_LISTENED_EVENTS = [
|
|
7311
7594
|
"user.message",
|
|
7312
7595
|
"llm.request",
|
|
@@ -7345,21 +7628,24 @@ var EMPTY_TOKEN_USAGE = {
|
|
|
7345
7628
|
contextWindow: 0,
|
|
7346
7629
|
model: ""
|
|
7347
7630
|
};
|
|
7348
|
-
function createInitialAgentChatState() {
|
|
7631
|
+
function createInitialAgentChatState(options = {}) {
|
|
7349
7632
|
return {
|
|
7350
7633
|
messages: [],
|
|
7351
7634
|
isRunning: false,
|
|
7635
|
+
isLoadingHistory: options.isLoadingHistory ?? false,
|
|
7352
7636
|
tokenUsage: EMPTY_TOKEN_USAGE,
|
|
7353
7637
|
retryIndicator: null,
|
|
7354
7638
|
lastEventId: 0,
|
|
7355
7639
|
sessionDone: false,
|
|
7356
7640
|
hadDeltas: false,
|
|
7357
|
-
terminal: false
|
|
7641
|
+
terminal: false,
|
|
7642
|
+
workspaceRefreshKey: 0
|
|
7358
7643
|
};
|
|
7359
7644
|
}
|
|
7360
7645
|
function applyAgentChatEvent(state, event) {
|
|
7361
7646
|
let nextState = {
|
|
7362
7647
|
...state,
|
|
7648
|
+
isLoadingHistory: false,
|
|
7363
7649
|
lastEventId: Math.max(state.lastEventId, event.eventId),
|
|
7364
7650
|
sessionDone: state.sessionDone || event.type === "session.done"
|
|
7365
7651
|
};
|
|
@@ -7415,11 +7701,17 @@ function applyAgentChatEvent(state, event) {
|
|
|
7415
7701
|
return applyLlmThinking(nextState, event);
|
|
7416
7702
|
case "tool.call":
|
|
7417
7703
|
return applyToolCall(nextState, event);
|
|
7418
|
-
case "tool.result":
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
);
|
|
7704
|
+
case "tool.result": {
|
|
7705
|
+
const toolCallId = stringValue(event.data.tool_call_id);
|
|
7706
|
+
const toolName = findToolNameById(nextState.messages, toolCallId);
|
|
7707
|
+
const messages = applyToolResult(nextState.messages, event.data);
|
|
7708
|
+
const mutatesWorkspace = toolName !== null && WORKSPACE_MUTATING_TOOLS.has(toolName);
|
|
7709
|
+
return {
|
|
7710
|
+
...nextState,
|
|
7711
|
+
messages,
|
|
7712
|
+
workspaceRefreshKey: mutatesWorkspace ? nextState.workspaceRefreshKey + 1 : nextState.workspaceRefreshKey
|
|
7713
|
+
};
|
|
7714
|
+
}
|
|
7423
7715
|
case "harness.wake":
|
|
7424
7716
|
case "llm.request":
|
|
7425
7717
|
return nextState.terminal ? nextState : { ...nextState, isRunning: true };
|
|
@@ -7859,6 +8151,14 @@ function hasUserAfterIndex(messages, idx) {
|
|
|
7859
8151
|
}
|
|
7860
8152
|
return false;
|
|
7861
8153
|
}
|
|
8154
|
+
function findToolNameById(messages, toolCallId) {
|
|
8155
|
+
if (!toolCallId) return null;
|
|
8156
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
8157
|
+
const tc = messages[i]?.toolCalls?.find((c) => c.id === toolCallId);
|
|
8158
|
+
if (tc) return tc.toolName;
|
|
8159
|
+
}
|
|
8160
|
+
return null;
|
|
8161
|
+
}
|
|
7862
8162
|
function findLatestConsultExpertCall(messages) {
|
|
7863
8163
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
7864
8164
|
const msg = messages[i];
|
|
@@ -7893,11 +8193,12 @@ function useAgentChatRuntime({
|
|
|
7893
8193
|
onSessionChange
|
|
7894
8194
|
}) {
|
|
7895
8195
|
const [state, setState] = react.useState(
|
|
7896
|
-
() => createInitialAgentChatState()
|
|
8196
|
+
() => createInitialAgentChatState({ isLoadingHistory: Boolean(sessionId) })
|
|
7897
8197
|
);
|
|
7898
8198
|
const stateRef = react.useRef(state);
|
|
7899
8199
|
const streamRef = react.useRef(null);
|
|
7900
8200
|
const reconnectTimerRef = react.useRef(null);
|
|
8201
|
+
const previousSessionIdRef = react.useRef(sessionId);
|
|
7901
8202
|
react.useEffect(() => {
|
|
7902
8203
|
stateRef.current = state;
|
|
7903
8204
|
}, [state]);
|
|
@@ -7913,6 +8214,8 @@ function useAgentChatRuntime({
|
|
|
7913
8214
|
stream?.close();
|
|
7914
8215
|
}, []);
|
|
7915
8216
|
react.useEffect(() => {
|
|
8217
|
+
const previousSessionId = previousSessionIdRef.current;
|
|
8218
|
+
previousSessionIdRef.current = sessionId;
|
|
7916
8219
|
clearReconnectTimer();
|
|
7917
8220
|
closeStream();
|
|
7918
8221
|
if (!sessionId) {
|
|
@@ -7920,11 +8223,11 @@ function useAgentChatRuntime({
|
|
|
7920
8223
|
return;
|
|
7921
8224
|
}
|
|
7922
8225
|
let cancelled = false;
|
|
7923
|
-
const connect = () => {
|
|
8226
|
+
const connect = (after) => {
|
|
7924
8227
|
if (cancelled) return;
|
|
7925
8228
|
const stream = adapter.openEventStream({
|
|
7926
8229
|
sessionId,
|
|
7927
|
-
after: stateRef.current.lastEventId
|
|
8230
|
+
after: after ?? stateRef.current.lastEventId
|
|
7928
8231
|
});
|
|
7929
8232
|
streamRef.current = stream;
|
|
7930
8233
|
for (const eventType of AGENT_CHAT_LISTENED_EVENTS) {
|
|
@@ -7947,14 +8250,32 @@ function useAgentChatRuntime({
|
|
|
7947
8250
|
streamRef.current = null;
|
|
7948
8251
|
}
|
|
7949
8252
|
if (!stateRef.current.sessionDone && !cancelled) {
|
|
7950
|
-
reconnectTimerRef.current = setTimeout(connect, 3e3);
|
|
8253
|
+
reconnectTimerRef.current = setTimeout(() => connect(), 3e3);
|
|
7951
8254
|
}
|
|
7952
8255
|
};
|
|
7953
8256
|
};
|
|
7954
|
-
|
|
7955
|
-
|
|
8257
|
+
const currentState = stateRef.current;
|
|
8258
|
+
const preservePendingFirstMessage = previousSessionId === null && currentState.isRunning && currentState.messages.some(
|
|
8259
|
+
(message) => message.role === "user" && message.id.startsWith("local-")
|
|
8260
|
+
);
|
|
8261
|
+
const initialState = preservePendingFirstMessage ? {
|
|
8262
|
+
...createInitialAgentChatState({ isLoadingHistory: false }),
|
|
8263
|
+
messages: currentState.messages,
|
|
8264
|
+
isRunning: true
|
|
8265
|
+
} : createInitialAgentChatState({
|
|
8266
|
+
isLoadingHistory: true
|
|
8267
|
+
});
|
|
8268
|
+
stateRef.current = initialState;
|
|
8269
|
+
setState(initialState);
|
|
8270
|
+
connect(0);
|
|
7956
8271
|
adapter.getSession({ sessionId }).then((session) => {
|
|
7957
8272
|
if (cancelled) return;
|
|
8273
|
+
if (session.messageCount === 0) {
|
|
8274
|
+
setState((prev) => ({
|
|
8275
|
+
...prev,
|
|
8276
|
+
isLoadingHistory: false
|
|
8277
|
+
}));
|
|
8278
|
+
}
|
|
7958
8279
|
if (isTerminalStatus(session.status)) {
|
|
7959
8280
|
setState((prev) => ({
|
|
7960
8281
|
...prev,
|
|
@@ -8037,13 +8358,18 @@ function useAgentChatRuntime({
|
|
|
8037
8358
|
}, []);
|
|
8038
8359
|
const send = react.useCallback(
|
|
8039
8360
|
async (content) => {
|
|
8361
|
+
markSending(content);
|
|
8040
8362
|
if (!sessionId) {
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8363
|
+
try {
|
|
8364
|
+
const session = await adapter.createSession({ agentId });
|
|
8365
|
+
onSessionChange?.(session.id);
|
|
8366
|
+
await adapter.sendMessage({ sessionId: session.id, content });
|
|
8367
|
+
} catch (error) {
|
|
8368
|
+
markSendError(error instanceof Error ? error.message : "send failed");
|
|
8369
|
+
throw error;
|
|
8370
|
+
}
|
|
8044
8371
|
return;
|
|
8045
8372
|
}
|
|
8046
|
-
markSending(content);
|
|
8047
8373
|
try {
|
|
8048
8374
|
await adapter.sendMessage({ sessionId, content });
|
|
8049
8375
|
} catch (error) {
|
|
@@ -8080,8 +8406,10 @@ function useAgentChatRuntime({
|
|
|
8080
8406
|
return {
|
|
8081
8407
|
messages: state.messages,
|
|
8082
8408
|
isRunning: state.isRunning,
|
|
8409
|
+
isLoadingHistory: state.isLoadingHistory,
|
|
8083
8410
|
tokenUsage: state.tokenUsage,
|
|
8084
8411
|
retryIndicator: state.retryIndicator,
|
|
8412
|
+
workspaceRefreshKey: state.workspaceRefreshKey,
|
|
8085
8413
|
send,
|
|
8086
8414
|
stop,
|
|
8087
8415
|
retry,
|
|
@@ -8116,6 +8444,7 @@ function AgentChat({
|
|
|
8116
8444
|
disabled
|
|
8117
8445
|
}) {
|
|
8118
8446
|
const [workspacePath, setWorkspacePath] = react.useState(null);
|
|
8447
|
+
const [workspaceCollapsed, setWorkspaceCollapsed] = react.useState(false);
|
|
8119
8448
|
const runtime = useAgentChatRuntime({
|
|
8120
8449
|
adapter,
|
|
8121
8450
|
agentId,
|
|
@@ -8147,6 +8476,7 @@ function AgentChat({
|
|
|
8147
8476
|
sessionId,
|
|
8148
8477
|
messages: runtime.messages,
|
|
8149
8478
|
isRunning: runtime.isRunning,
|
|
8479
|
+
isLoadingHistory: runtime.isLoadingHistory,
|
|
8150
8480
|
onSend: (content) => void runtime.send(content),
|
|
8151
8481
|
onStop: () => void runtime.stop(),
|
|
8152
8482
|
onRetry: runtime.retry,
|
|
@@ -8163,6 +8493,9 @@ function AgentChat({
|
|
|
8163
8493
|
sessionId,
|
|
8164
8494
|
selectedPath: workspacePath,
|
|
8165
8495
|
onSelectedPathChange: setWorkspacePath,
|
|
8496
|
+
collapsed: workspaceCollapsed,
|
|
8497
|
+
onCollapsedChange: setWorkspaceCollapsed,
|
|
8498
|
+
refreshSignal: runtime.workspaceRefreshKey,
|
|
8166
8499
|
disabled
|
|
8167
8500
|
}
|
|
8168
8501
|
)
|
|
@@ -8170,6 +8503,7 @@ function AgentChat({
|
|
|
8170
8503
|
}
|
|
8171
8504
|
);
|
|
8172
8505
|
}
|
|
8506
|
+
init_utils();
|
|
8173
8507
|
var POLL_INTERVAL_ACTIVE_MS = 4e3;
|
|
8174
8508
|
var POLL_INTERVAL_IDLE_MS = 3e4;
|
|
8175
8509
|
var DEFAULT_SESSION_LIST_LIMIT = 50;
|
|
@@ -8233,6 +8567,20 @@ function mergeTreeNodes(groups) {
|
|
|
8233
8567
|
}
|
|
8234
8568
|
return Array.from(byId.values());
|
|
8235
8569
|
}
|
|
8570
|
+
function pruneDeletedSessionNodes(nodes, deletedSessionId) {
|
|
8571
|
+
const deletedIds = /* @__PURE__ */ new Set([deletedSessionId]);
|
|
8572
|
+
let changed = true;
|
|
8573
|
+
while (changed) {
|
|
8574
|
+
changed = false;
|
|
8575
|
+
for (const node of nodes) {
|
|
8576
|
+
if (node.parentId && deletedIds.has(node.parentId) && !deletedIds.has(node.id)) {
|
|
8577
|
+
deletedIds.add(node.id);
|
|
8578
|
+
changed = true;
|
|
8579
|
+
}
|
|
8580
|
+
}
|
|
8581
|
+
}
|
|
8582
|
+
return nodes.filter((node) => !deletedIds.has(node.id));
|
|
8583
|
+
}
|
|
8236
8584
|
function formatSessionTime(value) {
|
|
8237
8585
|
const date = new Date(value);
|
|
8238
8586
|
if (Number.isNaN(date.getTime())) return "";
|
|
@@ -8253,6 +8601,7 @@ function TreeNodeRow({
|
|
|
8253
8601
|
const hasChildren = entry.children.length > 0;
|
|
8254
8602
|
const isActive = entry.id === activeSessionId;
|
|
8255
8603
|
const isRunning = entry.status === "active";
|
|
8604
|
+
const isSubAgent = entry.parentId != null;
|
|
8256
8605
|
const title = entry.title ?? "New session";
|
|
8257
8606
|
const subtitle = [
|
|
8258
8607
|
entry.model ?? "default",
|
|
@@ -8292,7 +8641,7 @@ function TreeNodeRow({
|
|
|
8292
8641
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm truncate", children: title }),
|
|
8293
8642
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-faint truncate", children: subtitle })
|
|
8294
8643
|
] }),
|
|
8295
|
-
isRunning && canStop && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8644
|
+
isRunning && canStop && isSubAgent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8296
8645
|
"button",
|
|
8297
8646
|
{
|
|
8298
8647
|
type: "button",
|
|
@@ -8349,11 +8698,12 @@ function SessionTreePanel({
|
|
|
8349
8698
|
title = "Running",
|
|
8350
8699
|
sessionListLimit = DEFAULT_SESSION_LIST_LIMIT,
|
|
8351
8700
|
hideRoot = false,
|
|
8701
|
+
hideHeader = false,
|
|
8702
|
+
loadList = false,
|
|
8352
8703
|
onSessionSelect,
|
|
8353
8704
|
onSessionDelete
|
|
8354
8705
|
}) {
|
|
8355
8706
|
const [nodes, setNodes] = react.useState([]);
|
|
8356
|
-
const [loading, setLoading] = react.useState(false);
|
|
8357
8707
|
const [error, setError] = react.useState(null);
|
|
8358
8708
|
const [hasEverLoaded, setHasEverLoaded] = react.useState(false);
|
|
8359
8709
|
const [deletingSessionId, setDeletingSessionId] = react.useState(
|
|
@@ -8365,18 +8715,16 @@ function SessionTreePanel({
|
|
|
8365
8715
|
const resetContext = react.useRef(null);
|
|
8366
8716
|
const refetch = react.useCallback(
|
|
8367
8717
|
async (opts) => {
|
|
8368
|
-
const canLoadSessionList = Boolean(
|
|
8718
|
+
const canLoadSessionList = Boolean(loadList && adapter.listSessions);
|
|
8369
8719
|
const canLoadSessionTree = Boolean(sessionId && adapter.getSessionTree);
|
|
8370
8720
|
if (!canLoadSessionList && !canLoadSessionTree) {
|
|
8371
8721
|
setNodes([]);
|
|
8372
8722
|
setHasEverLoaded(true);
|
|
8373
|
-
setLoading(false);
|
|
8374
8723
|
return;
|
|
8375
8724
|
}
|
|
8376
8725
|
const currentRequestId = ++requestId.current;
|
|
8377
|
-
if (!opts?.silent) setLoading(true);
|
|
8378
8726
|
try {
|
|
8379
|
-
const sessionListPromise =
|
|
8727
|
+
const sessionListPromise = loadList && adapter.listSessions ? adapter.listSessions({
|
|
8380
8728
|
agentId,
|
|
8381
8729
|
limit: sessionListLimit
|
|
8382
8730
|
}) : Promise.resolve(null);
|
|
@@ -8402,13 +8750,9 @@ function SessionTreePanel({
|
|
|
8402
8750
|
if (!opts?.silent) {
|
|
8403
8751
|
setError(e instanceof Error ? e.message : "Failed to load tree");
|
|
8404
8752
|
}
|
|
8405
|
-
} finally {
|
|
8406
|
-
if (mounted.current && currentRequestId === requestId.current && !opts?.silent) {
|
|
8407
|
-
setLoading(false);
|
|
8408
|
-
}
|
|
8409
8753
|
}
|
|
8410
8754
|
},
|
|
8411
|
-
[adapter, agentId, sessionId, sessionListLimit]
|
|
8755
|
+
[adapter, agentId, loadList, sessionId, sessionListLimit]
|
|
8412
8756
|
);
|
|
8413
8757
|
react.useEffect(() => {
|
|
8414
8758
|
mounted.current = true;
|
|
@@ -8418,8 +8762,8 @@ function SessionTreePanel({
|
|
|
8418
8762
|
}, []);
|
|
8419
8763
|
react.useEffect(() => {
|
|
8420
8764
|
const previous = resetContext.current;
|
|
8421
|
-
const shouldReset = !previous || previous.
|
|
8422
|
-
resetContext.current = {
|
|
8765
|
+
const shouldReset = !previous || previous.loadList !== loadList || previous.agentId !== agentId || previous.sessionListLimit !== sessionListLimit;
|
|
8766
|
+
resetContext.current = { loadList, agentId, sessionListLimit };
|
|
8423
8767
|
if (shouldReset) {
|
|
8424
8768
|
setNodes([]);
|
|
8425
8769
|
setHasEverLoaded(false);
|
|
@@ -8427,7 +8771,7 @@ function SessionTreePanel({
|
|
|
8427
8771
|
}
|
|
8428
8772
|
setError(null);
|
|
8429
8773
|
void refetch();
|
|
8430
|
-
}, [adapter, agentId, refetch, sessionListLimit]);
|
|
8774
|
+
}, [adapter, agentId, loadList, refetch, sessionListLimit]);
|
|
8431
8775
|
const runningCount = react.useMemo(
|
|
8432
8776
|
() => nodes.filter((n) => n.status === "active").length,
|
|
8433
8777
|
[nodes]
|
|
@@ -8464,6 +8808,11 @@ function SessionTreePanel({
|
|
|
8464
8808
|
setDeletingSessionId(id);
|
|
8465
8809
|
try {
|
|
8466
8810
|
await adapter.deleteSession({ sessionId: id });
|
|
8811
|
+
setNodes((current) => {
|
|
8812
|
+
const next = pruneDeletedSessionNodes(current, id);
|
|
8813
|
+
lastFingerprint.current = treeFingerprint(next);
|
|
8814
|
+
return next;
|
|
8815
|
+
});
|
|
8467
8816
|
onSessionDelete?.(id);
|
|
8468
8817
|
await refetch({ silent: true });
|
|
8469
8818
|
} catch (e) {
|
|
@@ -8478,24 +8827,12 @@ function SessionTreePanel({
|
|
|
8478
8827
|
if (nodes.length === 0) return null;
|
|
8479
8828
|
const topLevel = hideRoot ? roots.flatMap((r) => r.children) : roots;
|
|
8480
8829
|
if (topLevel.length === 0) return null;
|
|
8481
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8482
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 px-3 py-2 text-xs font-semibold uppercase tracking-wide", children: [
|
|
8830
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8831
|
+
!hideHeader && /* @__PURE__ */ jsxRuntime.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: [
|
|
8483
8832
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.UsersIcon, { className: "w-3.5 h-3.5" }),
|
|
8484
8833
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: title }),
|
|
8485
8834
|
runningCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", className: "h-4 px-1.5 text-[10px] ml-auto", children: runningCount })
|
|
8486
8835
|
] }),
|
|
8487
|
-
loading && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8488
|
-
"div",
|
|
8489
|
-
{
|
|
8490
|
-
className: "px-3 py-2",
|
|
8491
|
-
role: "status",
|
|
8492
|
-
"aria-label": "Loading sessions",
|
|
8493
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
8494
|
-
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-3.5 w-28" }),
|
|
8495
|
-
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-3 w-20" })
|
|
8496
|
-
] })
|
|
8497
|
-
}
|
|
8498
|
-
),
|
|
8499
8836
|
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 text-xs text-destructive", children: error }),
|
|
8500
8837
|
!error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-1 pb-2", children: topLevel.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8501
8838
|
TreeNodeRow,
|