@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.
@@ -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
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ToolCallGroup,
3
3
  ToolCallStep
4
- } from "./chunk-3O4XJCOE.js";
4
+ } from "./chunk-EOGJX2TU.js";
5
5
  import {
6
6
  Markdown
7
7
  } from "./chunk-FJBTCTZM.js";
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-OEX7NZE3.js";
12
12
  import {
13
13
  parseToolEvent
14
- } from "./chunk-U4YRT6MT.js";
14
+ } from "./chunk-O6NUUCT2.js";
15
15
 
16
16
  // src/hooks/use-dropdown-menu.ts
17
17
  import { useEffect, useRef, useState } from "react";
@@ -2,18 +2,18 @@ import {
2
2
  useAutoScroll,
3
3
  useRunCollapseState,
4
4
  useRunGroups
5
- } from "./chunk-54SQQMMM.js";
5
+ } from "./chunk-AZWDI2JG.js";
6
6
  import {
7
7
  InlineThinkingItem,
8
8
  RunGroup
9
- } from "./chunk-TAWY3KOH.js";
9
+ } from "./chunk-LASW7CYH.js";
10
10
  import {
11
11
  ToolCallGroup,
12
12
  ToolCallStep
13
- } from "./chunk-3O4XJCOE.js";
13
+ } from "./chunk-EOGJX2TU.js";
14
14
  import {
15
15
  getToolDisplayMetadata
16
- } from "./chunk-BX6AQMUS.js";
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-CJJMKDNN.js";
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-54SQQMMM.js";
21
- import "./chunk-U4YRT6MT.js";
22
- import "./chunk-3O4XJCOE.js";
23
- import "./chunk-BX6AQMUS.js";
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-CJJMKDNN.js";
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-FKDZOA4S.js";
141
+ } from "./chunk-SJ6IL4HI.js";
142
142
  import {
143
143
  useAutoScroll,
144
144
  useRunCollapseState,
145
145
  useRunGroups
146
- } from "./chunk-54SQQMMM.js";
146
+ } from "./chunk-AZWDI2JG.js";
147
147
  import "./chunk-LQS34IGP.js";
148
148
  import {
149
149
  ToolCallFeed,
150
150
  parseToolEvent
151
- } from "./chunk-U4YRT6MT.js";
151
+ } from "./chunk-O6NUUCT2.js";
152
152
  import {
153
- ExpandedToolDetail,
154
153
  InlineThinkingItem,
155
- InlineToolItem,
156
- LiveDuration,
157
154
  RunGroup
158
- } from "./chunk-TAWY3KOH.js";
155
+ } from "./chunk-LASW7CYH.js";
159
156
  import {
157
+ ExpandedToolDetail,
158
+ InlineToolItem,
159
+ LiveDuration,
160
160
  ToolCallGroup,
161
161
  ToolCallStep
162
- } from "./chunk-3O4XJCOE.js";
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
- } from "./chunk-BX6AQMUS.js";
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;