@tangle-network/ui 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/chat.js +5 -6
- package/dist/{chunk-54SQQMMM.js → chunk-AZWDI2JG.js} +1 -1
- package/dist/chunk-EOGJX2TU.js +366 -0
- package/dist/chunk-LASW7CYH.js +473 -0
- package/dist/{chunk-U4YRT6MT.js → chunk-O6NUUCT2.js} +1 -1
- package/dist/{chunk-CJJMKDNN.js → chunk-PN3S2MTV.js} +1 -1
- package/dist/{chunk-FKDZOA4S.js → chunk-SJ6IL4HI.js} +4 -4
- package/dist/{chunk-BX6AQMUS.js → chunk-ULDNFLIM.js} +44 -1
- package/dist/hooks.js +7 -5
- package/dist/index.js +13 -15
- package/dist/run.d.ts +5 -1
- package/dist/run.js +7 -8
- package/dist/sdk-hooks.js +7 -5
- package/dist/utils.js +4 -6
- package/package.json +1 -1
- package/src/run/inline-tool-item.tsx +11 -3
- package/src/run/tool-call-step.tsx +48 -146
- package/dist/chunk-3O4XJCOE.js +0 -176
- package/dist/chunk-4CLN43XT.js +0 -45
- package/dist/chunk-TAWY3KOH.js +0 -735
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InlineToolItem,
|
|
3
|
+
LiveDuration
|
|
4
|
+
} from "./chunk-EOGJX2TU.js";
|
|
5
|
+
import {
|
|
6
|
+
formatDuration,
|
|
7
|
+
truncateText
|
|
8
|
+
} from "./chunk-ULDNFLIM.js";
|
|
9
|
+
import {
|
|
10
|
+
OpenUIArtifactRenderer
|
|
11
|
+
} from "./chunk-52Y3FMFI.js";
|
|
12
|
+
import {
|
|
13
|
+
Markdown
|
|
14
|
+
} from "./chunk-FJBTCTZM.js";
|
|
15
|
+
import {
|
|
16
|
+
cn
|
|
17
|
+
} from "./chunk-RQHJBTEU.js";
|
|
18
|
+
|
|
19
|
+
// src/run/inline-thinking-item.tsx
|
|
20
|
+
import { memo, useEffect, useRef, useState } from "react";
|
|
21
|
+
import * as Collapsible from "@radix-ui/react-collapsible";
|
|
22
|
+
import { Brain, ChevronRight } from "lucide-react";
|
|
23
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
24
|
+
var InlineThinkingItem = memo(
|
|
25
|
+
({
|
|
26
|
+
part,
|
|
27
|
+
defaultOpen = false,
|
|
28
|
+
autoCollapse = true,
|
|
29
|
+
className,
|
|
30
|
+
contentClassName
|
|
31
|
+
}) => {
|
|
32
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
33
|
+
const autoCollapsedRef = useRef(false);
|
|
34
|
+
const startTime = part.time?.start;
|
|
35
|
+
const endTime = part.time?.end;
|
|
36
|
+
const durationMs = startTime && endTime ? endTime - startTime : void 0;
|
|
37
|
+
const isActive = startTime != null && endTime == null;
|
|
38
|
+
const preview = part.text ? truncateText(part.text, 120) : void 0;
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (isActive) {
|
|
41
|
+
autoCollapsedRef.current = false;
|
|
42
|
+
setOpen(true);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (autoCollapse && !autoCollapsedRef.current && durationMs != null) {
|
|
46
|
+
const timer = window.setTimeout(() => {
|
|
47
|
+
setOpen(false);
|
|
48
|
+
autoCollapsedRef.current = true;
|
|
49
|
+
}, 900);
|
|
50
|
+
return () => window.clearTimeout(timer);
|
|
51
|
+
}
|
|
52
|
+
}, [autoCollapse, durationMs, isActive]);
|
|
53
|
+
return /* @__PURE__ */ jsx(Collapsible.Root, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(
|
|
54
|
+
"div",
|
|
55
|
+
{
|
|
56
|
+
className: cn(
|
|
57
|
+
"overflow-hidden rounded-[var(--radius-lg)] border bg-card transition-colors",
|
|
58
|
+
isActive ? "border-[var(--border-accent)]" : "border-border hover:border-[var(--border-accent)]",
|
|
59
|
+
className
|
|
60
|
+
),
|
|
61
|
+
children: [
|
|
62
|
+
/* @__PURE__ */ jsx(Collapsible.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
63
|
+
"button",
|
|
64
|
+
{
|
|
65
|
+
className: "flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm cursor-pointer",
|
|
66
|
+
children: [
|
|
67
|
+
/* @__PURE__ */ jsx(
|
|
68
|
+
"div",
|
|
69
|
+
{
|
|
70
|
+
className: cn(
|
|
71
|
+
"flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border",
|
|
72
|
+
isActive ? "border-[var(--border-accent)] bg-[var(--accent-surface-soft)] text-primary" : "border-border bg-muted text-muted-foreground"
|
|
73
|
+
),
|
|
74
|
+
children: /* @__PURE__ */ jsx(Brain, { className: cn("h-3 w-3 shrink-0", isActive && "animate-pulse") })
|
|
75
|
+
}
|
|
76
|
+
),
|
|
77
|
+
/* @__PURE__ */ jsx("p", { className: "min-w-0 flex-1 truncate font-[var(--font-sans)] text-muted-foreground", children: preview ?? (isActive ? "Thinking\u2026" : "Reasoning") }),
|
|
78
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
79
|
+
isActive && startTime ? /* @__PURE__ */ jsx(LiveDuration, { startTime }) : null,
|
|
80
|
+
!isActive && durationMs != null ? /* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs tabular-nums text-muted-foreground", children: formatDuration(durationMs) }) : null,
|
|
81
|
+
/* @__PURE__ */ jsx(
|
|
82
|
+
ChevronRight,
|
|
83
|
+
{
|
|
84
|
+
className: cn(
|
|
85
|
+
"h-3 w-3 text-muted-foreground transition-transform shrink-0",
|
|
86
|
+
open && "rotate-90"
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
] })
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
) }),
|
|
94
|
+
/* @__PURE__ */ jsx(Collapsible.Content, { className: "overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp", children: part.text ? /* @__PURE__ */ jsx(
|
|
95
|
+
"div",
|
|
96
|
+
{
|
|
97
|
+
className: cn(
|
|
98
|
+
"max-h-60 overflow-y-auto border-t border-border bg-muted px-3 py-3 text-sm leading-relaxed text-muted-foreground",
|
|
99
|
+
contentClassName
|
|
100
|
+
),
|
|
101
|
+
children: /* @__PURE__ */ jsx(Markdown, { children: part.text })
|
|
102
|
+
}
|
|
103
|
+
) : /* @__PURE__ */ jsx("div", { className: "border-t border-border bg-muted px-3 py-2.5 text-xs text-muted-foreground", children: "No reasoning text provided." }) })
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
) });
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
InlineThinkingItem.displayName = "InlineThinkingItem";
|
|
110
|
+
|
|
111
|
+
// src/run/run-group.tsx
|
|
112
|
+
import { memo as memo2, useMemo } from "react";
|
|
113
|
+
import * as Collapsible2 from "@radix-ui/react-collapsible";
|
|
114
|
+
import {
|
|
115
|
+
Bot,
|
|
116
|
+
Loader2,
|
|
117
|
+
ChevronDown,
|
|
118
|
+
ChevronRight as ChevronRight2,
|
|
119
|
+
Terminal,
|
|
120
|
+
FileEdit,
|
|
121
|
+
FileSearch,
|
|
122
|
+
Search,
|
|
123
|
+
PencilLine,
|
|
124
|
+
Globe,
|
|
125
|
+
ClipboardList,
|
|
126
|
+
Settings,
|
|
127
|
+
Sparkles
|
|
128
|
+
} from "lucide-react";
|
|
129
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
130
|
+
var DEFAULT_BRANDING = {
|
|
131
|
+
label: "Agent",
|
|
132
|
+
accentClass: "text-primary",
|
|
133
|
+
bgClass: "bg-[var(--accent-surface-soft)]",
|
|
134
|
+
containerBgClass: "bg-muted",
|
|
135
|
+
borderClass: "border-border",
|
|
136
|
+
iconClass: "",
|
|
137
|
+
textClass: "text-primary"
|
|
138
|
+
};
|
|
139
|
+
var ASSISTANT_SHELL = "min-w-0 flex-1 space-y-3 rounded-[26px] border border-[var(--border-subtle)] bg-[color:color-mix(in_srgb,var(--bg-card)_94%,transparent)] px-5 py-4 shadow-[0_1px_2px_rgba(15,23,42,0.04)]";
|
|
140
|
+
function AssistantShell({
|
|
141
|
+
branding,
|
|
142
|
+
isStreaming,
|
|
143
|
+
children
|
|
144
|
+
}) {
|
|
145
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex gap-2.5", children: [
|
|
146
|
+
/* @__PURE__ */ jsx2("div", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[var(--brand-primary)] text-white", children: /* @__PURE__ */ jsx2(Bot, { className: "h-3.5 w-3.5" }) }),
|
|
147
|
+
/* @__PURE__ */ jsxs2("div", { className: ASSISTANT_SHELL, children: [
|
|
148
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.14em] text-[var(--text-muted)]", children: [
|
|
149
|
+
/* @__PURE__ */ jsx2("span", { children: branding.label }),
|
|
150
|
+
isStreaming ? /* @__PURE__ */ jsxs2("span", { className: "inline-flex items-center gap-1.5 text-[var(--text-muted)]", children: [
|
|
151
|
+
/* @__PURE__ */ jsx2(Loader2, { className: "h-3 w-3 animate-spin" }),
|
|
152
|
+
"Thinking"
|
|
153
|
+
] }) : null
|
|
154
|
+
] }),
|
|
155
|
+
children
|
|
156
|
+
] })
|
|
157
|
+
] });
|
|
158
|
+
}
|
|
159
|
+
var CATEGORY_ICON_MAP = {
|
|
160
|
+
command: Terminal,
|
|
161
|
+
write: FileEdit,
|
|
162
|
+
read: FileSearch,
|
|
163
|
+
search: Search,
|
|
164
|
+
edit: PencilLine,
|
|
165
|
+
task: Bot,
|
|
166
|
+
web: Globe,
|
|
167
|
+
todo: ClipboardList,
|
|
168
|
+
other: Settings
|
|
169
|
+
};
|
|
170
|
+
var CATEGORY_ORDER = [
|
|
171
|
+
"command",
|
|
172
|
+
"write",
|
|
173
|
+
"edit",
|
|
174
|
+
"read",
|
|
175
|
+
"search",
|
|
176
|
+
"web",
|
|
177
|
+
"task",
|
|
178
|
+
"todo",
|
|
179
|
+
"other"
|
|
180
|
+
];
|
|
181
|
+
var OPENUI_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
182
|
+
"heading",
|
|
183
|
+
"text",
|
|
184
|
+
"badge",
|
|
185
|
+
"stat",
|
|
186
|
+
"key_value",
|
|
187
|
+
"code",
|
|
188
|
+
"markdown",
|
|
189
|
+
"table",
|
|
190
|
+
"actions",
|
|
191
|
+
"separator",
|
|
192
|
+
"stack",
|
|
193
|
+
"grid",
|
|
194
|
+
"card"
|
|
195
|
+
]);
|
|
196
|
+
function isOpenUINode(value) {
|
|
197
|
+
return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string" && OPENUI_NODE_TYPES.has(value.type);
|
|
198
|
+
}
|
|
199
|
+
function extractOpenUISchema(output) {
|
|
200
|
+
if (output == null) return null;
|
|
201
|
+
if (isOpenUINode(output)) return [output];
|
|
202
|
+
if (Array.isArray(output) && output.length > 0 && output.every(isOpenUINode)) {
|
|
203
|
+
return output;
|
|
204
|
+
}
|
|
205
|
+
if (typeof output === "object" && !Array.isArray(output)) {
|
|
206
|
+
const obj = output;
|
|
207
|
+
for (const key of ["openui", "schema", "ui"]) {
|
|
208
|
+
if (obj[key] == null) continue;
|
|
209
|
+
const inner = obj[key];
|
|
210
|
+
if (typeof inner === "string") {
|
|
211
|
+
try {
|
|
212
|
+
const parsed = JSON.parse(inner);
|
|
213
|
+
return extractOpenUISchema(parsed);
|
|
214
|
+
} catch {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const nested = extractOpenUISchema(inner);
|
|
219
|
+
if (nested) return nested;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (typeof output === "string") {
|
|
223
|
+
try {
|
|
224
|
+
return extractOpenUISchema(JSON.parse(output));
|
|
225
|
+
} catch {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
function getOpenUISummary(output) {
|
|
232
|
+
if (!output || typeof output !== "object" || Array.isArray(output)) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
const summary = output.summary;
|
|
236
|
+
return typeof summary === "string" && summary.trim() ? summary.trim() : null;
|
|
237
|
+
}
|
|
238
|
+
function isOpenUITool(part) {
|
|
239
|
+
const normalized = part.tool.toLowerCase().replace(/^tool:/, "");
|
|
240
|
+
return normalized.includes("openui");
|
|
241
|
+
}
|
|
242
|
+
function CategoryBadges({ categories }) {
|
|
243
|
+
const sorted = useMemo(
|
|
244
|
+
() => CATEGORY_ORDER.filter((category) => categories.has(category)),
|
|
245
|
+
[categories]
|
|
246
|
+
);
|
|
247
|
+
if (sorted.length === 0) return null;
|
|
248
|
+
return /* @__PURE__ */ jsx2("div", { className: "flex items-center gap-1", children: sorted.map((cat) => {
|
|
249
|
+
const Icon = CATEGORY_ICON_MAP[cat] ?? Settings;
|
|
250
|
+
return /* @__PURE__ */ jsx2(
|
|
251
|
+
"span",
|
|
252
|
+
{
|
|
253
|
+
title: cat,
|
|
254
|
+
className: "flex h-5 w-5 items-center justify-center rounded border border-border text-muted-foreground",
|
|
255
|
+
children: /* @__PURE__ */ jsx2(Icon, { className: "h-3 w-3" })
|
|
256
|
+
},
|
|
257
|
+
cat
|
|
258
|
+
);
|
|
259
|
+
}) });
|
|
260
|
+
}
|
|
261
|
+
function renderSummary(run) {
|
|
262
|
+
const parts = [];
|
|
263
|
+
if (run.stats.toolCount > 0) {
|
|
264
|
+
parts.push(`${run.stats.toolCount} tool${run.stats.toolCount === 1 ? "" : "s"}`);
|
|
265
|
+
}
|
|
266
|
+
if (run.stats.textPartCount > 0) {
|
|
267
|
+
parts.push(`${run.stats.textPartCount} response${run.stats.textPartCount === 1 ? "" : "s"}`);
|
|
268
|
+
}
|
|
269
|
+
if (run.stats.thinkingDurationMs > 0) {
|
|
270
|
+
parts.push(`${formatDuration(run.stats.thinkingDurationMs)} thinking`);
|
|
271
|
+
}
|
|
272
|
+
return parts.join(", ");
|
|
273
|
+
}
|
|
274
|
+
function getToolGroupPosition(currentIndex, parts) {
|
|
275
|
+
const previous = parts[currentIndex - 1]?.part;
|
|
276
|
+
const next = parts[currentIndex + 1]?.part;
|
|
277
|
+
const previousIsTool = previous?.type === "tool";
|
|
278
|
+
const nextIsTool = next?.type === "tool";
|
|
279
|
+
if (previousIsTool && nextIsTool) return "middle";
|
|
280
|
+
if (previousIsTool) return "last";
|
|
281
|
+
if (nextIsTool) return "first";
|
|
282
|
+
return "single";
|
|
283
|
+
}
|
|
284
|
+
var RunGroup = memo2(
|
|
285
|
+
({
|
|
286
|
+
run,
|
|
287
|
+
partMap,
|
|
288
|
+
collapsed,
|
|
289
|
+
onToggle,
|
|
290
|
+
branding = DEFAULT_BRANDING,
|
|
291
|
+
renderToolDetail,
|
|
292
|
+
headerActions,
|
|
293
|
+
renderToolActions
|
|
294
|
+
}) => {
|
|
295
|
+
const allParts = useMemo(() => {
|
|
296
|
+
const parts = [];
|
|
297
|
+
for (const msg of run.messages) {
|
|
298
|
+
const msgParts = partMap[msg.id] ?? [];
|
|
299
|
+
msgParts.forEach((part, index) => {
|
|
300
|
+
parts.push({ part, msgId: msg.id, index });
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
return parts;
|
|
304
|
+
}, [run.messages, partMap]);
|
|
305
|
+
const { stats, isStreaming } = run;
|
|
306
|
+
const hasRenderableParts = allParts.some(({ part }) => {
|
|
307
|
+
if (part.type === "tool" || part.type === "reasoning") {
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
return part.type === "text" && !part.synthetic && part.text.trim().length > 0;
|
|
311
|
+
});
|
|
312
|
+
if (!hasRenderableParts) {
|
|
313
|
+
if (!isStreaming) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
return /* @__PURE__ */ jsx2(AssistantShell, { branding, isStreaming: true, children: /* @__PURE__ */ jsx2("div", { className: "flex items-center gap-2 px-0.5 py-0.5 text-sm text-[var(--text-muted)]", children: /* @__PURE__ */ jsxs2("span", { className: "flex gap-[5px]", children: [
|
|
317
|
+
/* @__PURE__ */ jsx2("span", { className: "h-2 w-2 animate-bounce rounded-full bg-[var(--brand-glow)]", style: { animationDelay: "0ms" } }),
|
|
318
|
+
/* @__PURE__ */ jsx2("span", { className: "h-2 w-2 animate-bounce rounded-full bg-[var(--brand-glow)]", style: { animationDelay: "150ms" } }),
|
|
319
|
+
/* @__PURE__ */ jsx2("span", { className: "h-2 w-2 animate-bounce rounded-full bg-[var(--brand-glow)]", style: { animationDelay: "300ms" } })
|
|
320
|
+
] }) }) });
|
|
321
|
+
}
|
|
322
|
+
const showTraceChrome = allParts.some(({ part }) => {
|
|
323
|
+
if (part.type === "reasoning") {
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
if (part.type === "tool") {
|
|
327
|
+
return !isOpenUITool(part);
|
|
328
|
+
}
|
|
329
|
+
return false;
|
|
330
|
+
});
|
|
331
|
+
if (!showTraceChrome) {
|
|
332
|
+
return /* @__PURE__ */ jsx2(AssistantShell, { branding, isStreaming, children: allParts.map(({ part, msgId, index }) => {
|
|
333
|
+
const key = `${msgId}-${index}`;
|
|
334
|
+
if (part.type === "tool" && isOpenUITool(part)) {
|
|
335
|
+
const toolPart = part;
|
|
336
|
+
const schema = extractOpenUISchema(toolPart.state.output);
|
|
337
|
+
const summary = getOpenUISummary(toolPart.state.output);
|
|
338
|
+
if (toolPart.state.status === "completed" && schema) {
|
|
339
|
+
return /* @__PURE__ */ jsxs2(
|
|
340
|
+
"div",
|
|
341
|
+
{
|
|
342
|
+
className: "overflow-hidden rounded-[22px] border border-[var(--border-subtle)] bg-[var(--bg-root)]",
|
|
343
|
+
children: [
|
|
344
|
+
summary ? /* @__PURE__ */ jsx2("div", { className: "border-b border-[var(--border-subtle)] px-4 py-3 text-sm leading-6 text-foreground", children: summary }) : null,
|
|
345
|
+
/* @__PURE__ */ jsx2("div", { className: "p-4", children: /* @__PURE__ */ jsx2(OpenUIArtifactRenderer, { schema }) })
|
|
346
|
+
]
|
|
347
|
+
},
|
|
348
|
+
key
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
if (toolPart.state.status === "running") {
|
|
352
|
+
return /* @__PURE__ */ jsxs2(
|
|
353
|
+
"div",
|
|
354
|
+
{
|
|
355
|
+
className: "flex items-center gap-2 rounded-[18px] border border-[var(--border-subtle)] bg-[var(--bg-root)] px-4 py-3 text-sm text-muted-foreground",
|
|
356
|
+
children: [
|
|
357
|
+
/* @__PURE__ */ jsx2(Loader2, { className: "h-4 w-4 animate-spin text-primary" }),
|
|
358
|
+
"Building view\u2026"
|
|
359
|
+
]
|
|
360
|
+
},
|
|
361
|
+
key
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (part.type === "text" && !part.synthetic && part.text.trim()) {
|
|
366
|
+
return /* @__PURE__ */ jsx2("div", { className: "px-0.5", children: /* @__PURE__ */ jsx2(Markdown, { className: "tangle-prose text-[15px] leading-7 text-[var(--text-primary)]", children: part.text }) }, key);
|
|
367
|
+
}
|
|
368
|
+
return null;
|
|
369
|
+
}) });
|
|
370
|
+
}
|
|
371
|
+
return /* @__PURE__ */ jsx2(Collapsible2.Root, { open: !collapsed, onOpenChange: () => onToggle(), children: /* @__PURE__ */ jsxs2("div", { className: "rounded-[28px] border border-[var(--border-subtle)] bg-[var(--bg-card)] shadow-none", children: [
|
|
372
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-start gap-3 px-3 py-2.5", children: [
|
|
373
|
+
/* @__PURE__ */ jsx2(Collapsible2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx2(
|
|
374
|
+
"button",
|
|
375
|
+
{
|
|
376
|
+
className: cn(
|
|
377
|
+
"w-full rounded-[20px] px-0 py-0 text-left transition-colors",
|
|
378
|
+
"bg-transparent hover:bg-transparent"
|
|
379
|
+
),
|
|
380
|
+
children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
|
|
381
|
+
/* @__PURE__ */ jsx2(
|
|
382
|
+
"div",
|
|
383
|
+
{
|
|
384
|
+
className: cn(
|
|
385
|
+
"flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[var(--brand-primary)] text-white"
|
|
386
|
+
),
|
|
387
|
+
children: /* @__PURE__ */ jsx2(Bot, { className: "h-3.5 w-3.5" })
|
|
388
|
+
}
|
|
389
|
+
),
|
|
390
|
+
/* @__PURE__ */ jsx2("span", { className: cn("text-sm font-semibold", branding.textClass), children: branding.label }),
|
|
391
|
+
renderSummary(run) ? /* @__PURE__ */ jsx2("span", { className: "text-[11px] text-muted-foreground", children: renderSummary(run) }) : null,
|
|
392
|
+
collapsed && run.summaryText ? /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate text-[11px] text-foreground/70", children: run.summaryText }) : null,
|
|
393
|
+
/* @__PURE__ */ jsxs2("div", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [
|
|
394
|
+
/* @__PURE__ */ jsx2(CategoryBadges, { categories: stats.toolCategories }),
|
|
395
|
+
isStreaming ? /* @__PURE__ */ jsxs2("span", { className: "inline-flex items-center gap-1 rounded-full border border-[var(--border-accent)] bg-[var(--accent-surface-soft)] px-2 py-px text-[10px] font-semibold uppercase text-[var(--accent-text)]", children: [
|
|
396
|
+
/* @__PURE__ */ jsx2(Loader2, { className: "h-2.5 w-2.5 animate-spin" }),
|
|
397
|
+
"Running"
|
|
398
|
+
] }) : /* @__PURE__ */ jsxs2("span", { className: "inline-flex items-center gap-1 rounded-full border border-border px-2 py-px text-[10px] font-semibold uppercase text-muted-foreground", children: [
|
|
399
|
+
/* @__PURE__ */ jsx2(Sparkles, { className: "h-2.5 w-2.5" }),
|
|
400
|
+
"Done"
|
|
401
|
+
] }),
|
|
402
|
+
!collapsed ? /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" }) : /* @__PURE__ */ jsx2(ChevronRight2, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
403
|
+
] })
|
|
404
|
+
] })
|
|
405
|
+
}
|
|
406
|
+
) }),
|
|
407
|
+
headerActions ? /* @__PURE__ */ jsx2("div", { className: "flex shrink-0 flex-wrap items-center justify-end gap-1.5 pt-1", children: headerActions }) : null
|
|
408
|
+
] }),
|
|
409
|
+
collapsed && run.summaryText && /* @__PURE__ */ jsx2("div", { className: "px-4 pb-4 text-sm leading-6 text-muted-foreground line-clamp-2", children: run.summaryText }),
|
|
410
|
+
/* @__PURE__ */ jsx2(Collapsible2.Content, { className: "overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp", children: /* @__PURE__ */ jsx2("div", { className: cn("border-t border-[var(--border-subtle)] px-4 pb-4 pt-3"), children: allParts.map(({ part, msgId, index }, partIndex) => {
|
|
411
|
+
const key = `${msgId}-${index}`;
|
|
412
|
+
const prev = allParts[partIndex - 1]?.part;
|
|
413
|
+
const connectedTool = part.type === "tool" && prev?.type === "tool" && !isOpenUITool(part) && !isOpenUITool(prev);
|
|
414
|
+
const gapClass = partIndex === 0 ? "" : connectedTool ? "mt-px" : "mt-3";
|
|
415
|
+
let node = null;
|
|
416
|
+
if (part.type === "tool") {
|
|
417
|
+
if (isOpenUITool(part)) {
|
|
418
|
+
const toolPart = part;
|
|
419
|
+
const schema = extractOpenUISchema(toolPart.state.output);
|
|
420
|
+
const summary = getOpenUISummary(toolPart.state.output);
|
|
421
|
+
if (toolPart.state.status === "completed" && schema) {
|
|
422
|
+
node = /* @__PURE__ */ jsxs2("div", { className: "overflow-hidden rounded-[24px] border border-[var(--border-subtle)] bg-[var(--bg-card)]", children: [
|
|
423
|
+
summary ? /* @__PURE__ */ jsxs2("div", { className: "border-b border-[var(--border-subtle)] px-4 py-3", children: [
|
|
424
|
+
/* @__PURE__ */ jsx2("div", { className: "text-[11px] font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: "View" }),
|
|
425
|
+
/* @__PURE__ */ jsx2("div", { className: "mt-1 text-sm leading-6 text-foreground", children: summary })
|
|
426
|
+
] }) : null,
|
|
427
|
+
/* @__PURE__ */ jsx2("div", { className: "p-4", children: /* @__PURE__ */ jsx2(OpenUIArtifactRenderer, { schema }) })
|
|
428
|
+
] });
|
|
429
|
+
} else if (toolPart.state.status === "running") {
|
|
430
|
+
node = /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3 rounded-[20px] border border-[var(--border-subtle)] bg-[var(--bg-card)] px-4 py-3 text-sm text-muted-foreground", children: [
|
|
431
|
+
/* @__PURE__ */ jsx2(Loader2, { className: "h-4 w-4 animate-spin text-primary" }),
|
|
432
|
+
"Building view\u2026"
|
|
433
|
+
] });
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (node === null) {
|
|
437
|
+
node = /* @__PURE__ */ jsx2(
|
|
438
|
+
InlineToolItem,
|
|
439
|
+
{
|
|
440
|
+
part,
|
|
441
|
+
renderToolDetail,
|
|
442
|
+
groupPosition: getToolGroupPosition(partIndex, allParts),
|
|
443
|
+
actions: renderToolActions?.(part, {
|
|
444
|
+
run,
|
|
445
|
+
messageId: msgId,
|
|
446
|
+
partIndex: index
|
|
447
|
+
})
|
|
448
|
+
}
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
} else if (part.type === "reasoning") {
|
|
452
|
+
node = /* @__PURE__ */ jsx2(
|
|
453
|
+
InlineThinkingItem,
|
|
454
|
+
{
|
|
455
|
+
part,
|
|
456
|
+
defaultOpen: isStreaming
|
|
457
|
+
}
|
|
458
|
+
);
|
|
459
|
+
} else if (part.type === "text" && !part.synthetic && part.text.trim()) {
|
|
460
|
+
node = /* @__PURE__ */ jsx2("div", { className: "px-1 py-1", children: /* @__PURE__ */ jsx2(Markdown, { className: "tangle-prose text-[15px] leading-7", children: part.text }) });
|
|
461
|
+
}
|
|
462
|
+
if (!node) return null;
|
|
463
|
+
return /* @__PURE__ */ jsx2("div", { className: gapClass, children: node }, key);
|
|
464
|
+
}) }) })
|
|
465
|
+
] }) });
|
|
466
|
+
}
|
|
467
|
+
);
|
|
468
|
+
RunGroup.displayName = "RunGroup";
|
|
469
|
+
|
|
470
|
+
export {
|
|
471
|
+
InlineThinkingItem,
|
|
472
|
+
RunGroup
|
|
473
|
+
};
|
|
@@ -2,18 +2,18 @@ import {
|
|
|
2
2
|
useAutoScroll,
|
|
3
3
|
useRunCollapseState,
|
|
4
4
|
useRunGroups
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AZWDI2JG.js";
|
|
6
6
|
import {
|
|
7
7
|
InlineThinkingItem,
|
|
8
8
|
RunGroup
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LASW7CYH.js";
|
|
10
10
|
import {
|
|
11
11
|
ToolCallGroup,
|
|
12
12
|
ToolCallStep
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-EOGJX2TU.js";
|
|
14
14
|
import {
|
|
15
15
|
getToolDisplayMetadata
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-ULDNFLIM.js";
|
|
17
17
|
import {
|
|
18
18
|
OpenUIArtifactRenderer
|
|
19
19
|
} from "./chunk-52Y3FMFI.js";
|
|
@@ -175,9 +175,52 @@ function getToolErrorText(part, fallback) {
|
|
|
175
175
|
return part.state.error || fallback;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
// src/utils/format.ts
|
|
179
|
+
function formatDuration(ms) {
|
|
180
|
+
if (ms < 1e3) return "<1s";
|
|
181
|
+
const seconds = Math.floor(ms / 1e3);
|
|
182
|
+
if (seconds < 60) return `${seconds}s`;
|
|
183
|
+
const minutes = Math.floor(seconds / 60);
|
|
184
|
+
const remaining = seconds % 60;
|
|
185
|
+
return remaining > 0 ? `${minutes}m ${remaining}s` : `${minutes}m`;
|
|
186
|
+
}
|
|
187
|
+
function truncateText(text, max) {
|
|
188
|
+
const cleaned = text.replace(/\s+/g, " ").trim();
|
|
189
|
+
if (cleaned.length <= max) return cleaned;
|
|
190
|
+
return cleaned.slice(0, max).trim() + "...";
|
|
191
|
+
}
|
|
192
|
+
function formatUptime(ms) {
|
|
193
|
+
if (!Number.isFinite(ms) || ms < 0) return "\u2014";
|
|
194
|
+
const totalSeconds = Math.floor(ms / 1e3);
|
|
195
|
+
if (totalSeconds < 60) return `${totalSeconds}s`;
|
|
196
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
197
|
+
const seconds = totalSeconds % 60;
|
|
198
|
+
if (minutes < 60) return `${minutes}m ${seconds}s`;
|
|
199
|
+
const hours = Math.floor(minutes / 60);
|
|
200
|
+
const remMinutes = minutes % 60;
|
|
201
|
+
if (hours < 24) return `${hours}h ${remMinutes}m`;
|
|
202
|
+
const days = Math.floor(hours / 24);
|
|
203
|
+
const remHours = hours % 24;
|
|
204
|
+
return `${days}d ${remHours}h`;
|
|
205
|
+
}
|
|
206
|
+
function formatBytes(bytes) {
|
|
207
|
+
if (!Number.isFinite(bytes) || bytes < 0) return "\u2014";
|
|
208
|
+
if (bytes < 1024) return `${Math.round(bytes)} B`;
|
|
209
|
+
const kb = bytes / 1024;
|
|
210
|
+
if (kb < 1024) return `${kb < 10 ? kb.toFixed(1) : Math.round(kb)} KB`;
|
|
211
|
+
const mb = kb / 1024;
|
|
212
|
+
if (mb < 1024) return `${mb < 10 ? mb.toFixed(1) : Math.round(mb)} MB`;
|
|
213
|
+
const gb = mb / 1024;
|
|
214
|
+
return `${gb < 10 ? gb.toFixed(2) : gb.toFixed(1)} GB`;
|
|
215
|
+
}
|
|
216
|
+
|
|
178
217
|
export {
|
|
179
218
|
TOOL_CATEGORY_ICONS,
|
|
180
219
|
getToolCategory,
|
|
181
220
|
getToolDisplayMetadata,
|
|
182
|
-
getToolErrorText
|
|
221
|
+
getToolErrorText,
|
|
222
|
+
formatDuration,
|
|
223
|
+
truncateText,
|
|
224
|
+
formatUptime,
|
|
225
|
+
formatBytes
|
|
183
226
|
};
|
package/dist/hooks.js
CHANGED
|
@@ -11,16 +11,18 @@ import {
|
|
|
11
11
|
useSSEStream,
|
|
12
12
|
useSdkSession,
|
|
13
13
|
useToolCallStream
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-PN3S2MTV.js";
|
|
15
15
|
import "./chunk-OEX7NZE3.js";
|
|
16
16
|
import {
|
|
17
17
|
useAutoScroll,
|
|
18
18
|
useRunCollapseState,
|
|
19
19
|
useRunGroups
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-AZWDI2JG.js";
|
|
21
|
+
import "./chunk-O6NUUCT2.js";
|
|
22
|
+
import "./chunk-EOGJX2TU.js";
|
|
23
|
+
import "./chunk-ULDNFLIM.js";
|
|
24
|
+
import "./chunk-AAUNOHVL.js";
|
|
25
|
+
import "./chunk-ZRVH3WCA.js";
|
|
24
26
|
import "./chunk-FJBTCTZM.js";
|
|
25
27
|
import "./chunk-WUQDUBJG.js";
|
|
26
28
|
import "./chunk-RQHJBTEU.js";
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
useSSEStream,
|
|
18
18
|
useSdkSession,
|
|
19
19
|
useToolCallStream
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-PN3S2MTV.js";
|
|
21
21
|
import {
|
|
22
22
|
addMessage,
|
|
23
23
|
addParts,
|
|
@@ -138,40 +138,38 @@ import {
|
|
|
138
138
|
MessageList,
|
|
139
139
|
ThinkingIndicator,
|
|
140
140
|
UserMessage
|
|
141
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-SJ6IL4HI.js";
|
|
142
142
|
import {
|
|
143
143
|
useAutoScroll,
|
|
144
144
|
useRunCollapseState,
|
|
145
145
|
useRunGroups
|
|
146
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-AZWDI2JG.js";
|
|
147
147
|
import "./chunk-LQS34IGP.js";
|
|
148
148
|
import {
|
|
149
149
|
ToolCallFeed,
|
|
150
150
|
parseToolEvent
|
|
151
|
-
} from "./chunk-
|
|
151
|
+
} from "./chunk-O6NUUCT2.js";
|
|
152
152
|
import {
|
|
153
|
-
ExpandedToolDetail,
|
|
154
153
|
InlineThinkingItem,
|
|
155
|
-
InlineToolItem,
|
|
156
|
-
LiveDuration,
|
|
157
154
|
RunGroup
|
|
158
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-LASW7CYH.js";
|
|
159
156
|
import {
|
|
157
|
+
ExpandedToolDetail,
|
|
158
|
+
InlineToolItem,
|
|
159
|
+
LiveDuration,
|
|
160
160
|
ToolCallGroup,
|
|
161
161
|
ToolCallStep
|
|
162
|
-
} from "./chunk-
|
|
162
|
+
} from "./chunk-EOGJX2TU.js";
|
|
163
163
|
import {
|
|
164
|
+
TOOL_CATEGORY_ICONS,
|
|
164
165
|
formatBytes,
|
|
165
166
|
formatDuration,
|
|
166
167
|
formatUptime,
|
|
167
|
-
truncateText
|
|
168
|
-
} from "./chunk-4CLN43XT.js";
|
|
169
|
-
import {
|
|
170
|
-
TOOL_CATEGORY_ICONS,
|
|
171
168
|
getToolCategory,
|
|
172
169
|
getToolDisplayMetadata,
|
|
173
|
-
getToolErrorText
|
|
174
|
-
|
|
170
|
+
getToolErrorText,
|
|
171
|
+
truncateText
|
|
172
|
+
} from "./chunk-ULDNFLIM.js";
|
|
175
173
|
import {
|
|
176
174
|
CommandPreview,
|
|
177
175
|
DiffPreview,
|
package/dist/run.d.ts
CHANGED
|
@@ -35,13 +35,17 @@ interface InlineToolItemProps {
|
|
|
35
35
|
className?: string;
|
|
36
36
|
contentClassName?: string;
|
|
37
37
|
actions?: ReactNode;
|
|
38
|
+
/** Override the derived title (default: from `getToolDisplayMetadata`). */
|
|
39
|
+
title?: string;
|
|
40
|
+
/** Override the derived inline description. */
|
|
41
|
+
description?: string;
|
|
38
42
|
}
|
|
39
43
|
/**
|
|
40
44
|
* Compact single-line tool call display (32px height).
|
|
41
45
|
* Shows icon, title, description, duration, and status indicator.
|
|
42
46
|
* Expands on click to show ExpandedToolDetail.
|
|
43
47
|
*/
|
|
44
|
-
declare const InlineToolItem: React.MemoExoticComponent<({ part, renderToolDetail, groupPosition, className, contentClassName, actions, }: InlineToolItemProps) => react_jsx_runtime.JSX.Element>;
|
|
48
|
+
declare const InlineToolItem: React.MemoExoticComponent<({ part, renderToolDetail, groupPosition, className, contentClassName, actions, title: titleOverride, description: descriptionOverride, }: InlineToolItemProps) => react_jsx_runtime.JSX.Element>;
|
|
45
49
|
|
|
46
50
|
interface InlineThinkingItemProps {
|
|
47
51
|
part: ReasoningPart;
|