@tangle-network/ui 5.0.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 +17 -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-5VPTNXX7.js → chunk-O6NUUCT2.js} +1 -1
- package/dist/{chunk-CMX2I43A.js → chunk-PN3S2MTV.js} +1 -1
- package/dist/{chunk-KT5RNO7N.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 +14 -6
- package/src/run/run-group.tsx +52 -48
- package/src/run/tool-call-step.tsx +48 -150
- package/dist/chunk-4CLN43XT.js +0 -45
- package/dist/chunk-DGW77LD7.js +0 -186
- package/dist/chunk-JBPWIYTQ.js +0 -754
package/dist/run.js
CHANGED
|
@@ -2,20 +2,19 @@ import "./chunk-LQS34IGP.js";
|
|
|
2
2
|
import {
|
|
3
3
|
ToolCallFeed,
|
|
4
4
|
parseToolEvent
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-O6NUUCT2.js";
|
|
6
6
|
import {
|
|
7
|
-
ExpandedToolDetail,
|
|
8
7
|
InlineThinkingItem,
|
|
9
|
-
InlineToolItem,
|
|
10
|
-
LiveDuration,
|
|
11
8
|
RunGroup
|
|
12
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LASW7CYH.js";
|
|
13
10
|
import {
|
|
11
|
+
ExpandedToolDetail,
|
|
12
|
+
InlineToolItem,
|
|
13
|
+
LiveDuration,
|
|
14
14
|
ToolCallGroup,
|
|
15
15
|
ToolCallStep
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-BX6AQMUS.js";
|
|
16
|
+
} from "./chunk-EOGJX2TU.js";
|
|
17
|
+
import "./chunk-ULDNFLIM.js";
|
|
19
18
|
import "./chunk-AAUNOHVL.js";
|
|
20
19
|
import "./chunk-52Y3FMFI.js";
|
|
21
20
|
import "./chunk-GYPQXTJU.js";
|
package/dist/sdk-hooks.js
CHANGED
|
@@ -5,16 +5,18 @@ import {
|
|
|
5
5
|
useSSEStream,
|
|
6
6
|
useSdkSession,
|
|
7
7
|
useToolCallStream
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-PN3S2MTV.js";
|
|
9
9
|
import "./chunk-OEX7NZE3.js";
|
|
10
10
|
import {
|
|
11
11
|
useAutoScroll,
|
|
12
12
|
useRunCollapseState,
|
|
13
13
|
useRunGroups
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-AZWDI2JG.js";
|
|
15
|
+
import "./chunk-O6NUUCT2.js";
|
|
16
|
+
import "./chunk-EOGJX2TU.js";
|
|
17
|
+
import "./chunk-ULDNFLIM.js";
|
|
18
|
+
import "./chunk-AAUNOHVL.js";
|
|
19
|
+
import "./chunk-ZRVH3WCA.js";
|
|
18
20
|
import "./chunk-FJBTCTZM.js";
|
|
19
21
|
import "./chunk-WUQDUBJG.js";
|
|
20
22
|
import "./chunk-RQHJBTEU.js";
|
package/dist/utils.js
CHANGED
|
@@ -3,17 +3,15 @@ import {
|
|
|
3
3
|
timeAgo
|
|
4
4
|
} from "./chunk-XGKULLYE.js";
|
|
5
5
|
import {
|
|
6
|
+
TOOL_CATEGORY_ICONS,
|
|
6
7
|
formatBytes,
|
|
7
8
|
formatDuration,
|
|
8
9
|
formatUptime,
|
|
9
|
-
truncateText
|
|
10
|
-
} from "./chunk-4CLN43XT.js";
|
|
11
|
-
import {
|
|
12
|
-
TOOL_CATEGORY_ICONS,
|
|
13
10
|
getToolCategory,
|
|
14
11
|
getToolDisplayMetadata,
|
|
15
|
-
getToolErrorText
|
|
16
|
-
|
|
12
|
+
getToolErrorText,
|
|
13
|
+
truncateText
|
|
14
|
+
} from "./chunk-ULDNFLIM.js";
|
|
17
15
|
import {
|
|
18
16
|
cn
|
|
19
17
|
} from "./chunk-RQHJBTEU.js";
|
package/package.json
CHANGED
|
@@ -53,6 +53,10 @@ export interface InlineToolItemProps {
|
|
|
53
53
|
className?: string;
|
|
54
54
|
contentClassName?: string;
|
|
55
55
|
actions?: ReactNode;
|
|
56
|
+
/** Override the derived title (default: from `getToolDisplayMetadata`). */
|
|
57
|
+
title?: string;
|
|
58
|
+
/** Override the derived inline description. */
|
|
59
|
+
description?: string;
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
/**
|
|
@@ -68,9 +72,13 @@ export const InlineToolItem = memo(
|
|
|
68
72
|
className,
|
|
69
73
|
contentClassName,
|
|
70
74
|
actions,
|
|
75
|
+
title: titleOverride,
|
|
76
|
+
description: descriptionOverride,
|
|
71
77
|
}: InlineToolItemProps) => {
|
|
72
78
|
const [open, setOpen] = useState(false);
|
|
73
79
|
const meta = getToolDisplayMetadata(part);
|
|
80
|
+
const title = titleOverride ?? meta.title;
|
|
81
|
+
const description = descriptionOverride ?? meta.description;
|
|
74
82
|
const { status } = part.state;
|
|
75
83
|
const errorText = getToolErrorText(part);
|
|
76
84
|
|
|
@@ -101,8 +109,8 @@ export const InlineToolItem = memo(
|
|
|
101
109
|
<button
|
|
102
110
|
className={cn(
|
|
103
111
|
"w-full border text-left transition-colors",
|
|
104
|
-
"border-border bg-card hover:border-
|
|
105
|
-
open && "border-border bg-accent/
|
|
112
|
+
"border-[var(--border-subtle)] bg-card/40 hover:border-border hover:bg-accent/25",
|
|
113
|
+
open && "border-border bg-accent/20",
|
|
106
114
|
shapeClass,
|
|
107
115
|
className,
|
|
108
116
|
)}
|
|
@@ -127,11 +135,11 @@ export const InlineToolItem = memo(
|
|
|
127
135
|
</div>
|
|
128
136
|
|
|
129
137
|
<span className="truncate text-xs font-medium text-foreground">
|
|
130
|
-
{
|
|
138
|
+
{title}
|
|
131
139
|
</span>
|
|
132
|
-
{
|
|
140
|
+
{description ? (
|
|
133
141
|
<span className="hidden truncate text-xs font-mono text-muted-foreground sm:inline">
|
|
134
|
-
{
|
|
142
|
+
{description}
|
|
135
143
|
</span>
|
|
136
144
|
) : null}
|
|
137
145
|
|
|
@@ -179,7 +187,7 @@ export const InlineToolItem = memo(
|
|
|
179
187
|
</div>
|
|
180
188
|
|
|
181
189
|
<Collapsible.Content className="overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp">
|
|
182
|
-
<div className={cn("mt-2 pl-
|
|
190
|
+
<div className={cn("mt-1.5 ml-2.5 border-l-2 border-primary/15 pl-3.5", contentClassName)}>
|
|
183
191
|
{renderToolDetail?.(part) ?? <ExpandedToolDetail part={part} />}
|
|
184
192
|
</div>
|
|
185
193
|
</Collapsible.Content>
|
package/src/run/run-group.tsx
CHANGED
|
@@ -58,9 +58,9 @@ function AssistantShell({
|
|
|
58
58
|
children: ReactNode;
|
|
59
59
|
}) {
|
|
60
60
|
return (
|
|
61
|
-
<div className="flex gap-
|
|
62
|
-
<div className="mt-
|
|
63
|
-
<Bot className="h-
|
|
61
|
+
<div className="flex gap-2.5">
|
|
62
|
+
<div className="mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[var(--brand-primary)] text-white">
|
|
63
|
+
<Bot className="h-3.5 w-3.5" />
|
|
64
64
|
</div>
|
|
65
65
|
|
|
66
66
|
<div className={ASSISTANT_SHELL}>
|
|
@@ -402,7 +402,7 @@ export const RunGroup = memo(
|
|
|
402
402
|
<Collapsible.Root open={!collapsed} onOpenChange={() => onToggle()}>
|
|
403
403
|
<div className="rounded-[28px] border border-[var(--border-subtle)] bg-[var(--bg-card)] shadow-none">
|
|
404
404
|
{/* Header */}
|
|
405
|
-
<div className="flex items-start gap-3 px-
|
|
405
|
+
<div className="flex items-start gap-3 px-3 py-2.5">
|
|
406
406
|
<Collapsible.Trigger asChild>
|
|
407
407
|
<button
|
|
408
408
|
className={cn(
|
|
@@ -410,13 +410,13 @@ export const RunGroup = memo(
|
|
|
410
410
|
"bg-transparent hover:bg-transparent",
|
|
411
411
|
)}
|
|
412
412
|
>
|
|
413
|
-
<div className="flex items-center gap-2
|
|
413
|
+
<div className="flex items-center gap-2">
|
|
414
414
|
<div
|
|
415
415
|
className={cn(
|
|
416
|
-
"flex h-
|
|
416
|
+
"flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[var(--brand-primary)] text-white",
|
|
417
417
|
)}
|
|
418
418
|
>
|
|
419
|
-
<Bot className="h-
|
|
419
|
+
<Bot className="h-3.5 w-3.5" />
|
|
420
420
|
</div>
|
|
421
421
|
|
|
422
422
|
<span className={cn("text-sm font-semibold", branding.textClass)}>
|
|
@@ -473,10 +473,24 @@ export const RunGroup = memo(
|
|
|
473
473
|
|
|
474
474
|
{/* Expanded content */}
|
|
475
475
|
<Collapsible.Content className="overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp">
|
|
476
|
-
<div className={cn("
|
|
476
|
+
<div className={cn("border-t border-[var(--border-subtle)] px-4 pb-4 pt-3")}>
|
|
477
477
|
{allParts.map(({ part, msgId, index }, partIndex) => {
|
|
478
478
|
const key = `${msgId}-${index}`;
|
|
479
479
|
|
|
480
|
+
// Consecutive (non-OpenUI) tool calls connect into one block —
|
|
481
|
+
// `getToolGroupPosition` already gives them joined radii, so they
|
|
482
|
+
// get no vertical gap; every other transition keeps a normal gap.
|
|
483
|
+
const prev = allParts[partIndex - 1]?.part;
|
|
484
|
+
const connectedTool =
|
|
485
|
+
part.type === "tool" &&
|
|
486
|
+
prev?.type === "tool" &&
|
|
487
|
+
!isOpenUITool(part as ToolPart) &&
|
|
488
|
+
!isOpenUITool(prev as ToolPart);
|
|
489
|
+
const gapClass =
|
|
490
|
+
partIndex === 0 ? "" : connectedTool ? "mt-px" : "mt-3";
|
|
491
|
+
|
|
492
|
+
let node: ReactNode = null;
|
|
493
|
+
|
|
480
494
|
if (part.type === "tool") {
|
|
481
495
|
if (isOpenUITool(part as ToolPart)) {
|
|
482
496
|
const toolPart = part as ToolPart;
|
|
@@ -484,11 +498,8 @@ export const RunGroup = memo(
|
|
|
484
498
|
const summary = getOpenUISummary(toolPart.state.output);
|
|
485
499
|
|
|
486
500
|
if (toolPart.state.status === "completed" && schema) {
|
|
487
|
-
|
|
488
|
-
<div
|
|
489
|
-
key={key}
|
|
490
|
-
className="overflow-hidden rounded-[24px] border border-[var(--border-subtle)] bg-[var(--bg-card)]"
|
|
491
|
-
>
|
|
501
|
+
node = (
|
|
502
|
+
<div className="overflow-hidden rounded-[24px] border border-[var(--border-subtle)] bg-[var(--bg-card)]">
|
|
492
503
|
{summary ? (
|
|
493
504
|
<div className="border-b border-[var(--border-subtle)] px-4 py-3">
|
|
494
505
|
<div className="text-[11px] font-semibold uppercase tracking-[0.14em] text-muted-foreground">
|
|
@@ -502,14 +513,9 @@ export const RunGroup = memo(
|
|
|
502
513
|
</div>
|
|
503
514
|
</div>
|
|
504
515
|
);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
return (
|
|
509
|
-
<div
|
|
510
|
-
key={key}
|
|
511
|
-
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"
|
|
512
|
-
>
|
|
516
|
+
} else if (toolPart.state.status === "running") {
|
|
517
|
+
node = (
|
|
518
|
+
<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">
|
|
513
519
|
<Loader2 className="h-4 w-4 animate-spin text-primary" />
|
|
514
520
|
Building view…
|
|
515
521
|
</div>
|
|
@@ -517,47 +523,45 @@ export const RunGroup = memo(
|
|
|
517
523
|
}
|
|
518
524
|
}
|
|
519
525
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
return (
|
|
526
|
+
if (node === null) {
|
|
527
|
+
node = (
|
|
528
|
+
<InlineToolItem
|
|
529
|
+
part={part as ToolPart}
|
|
530
|
+
renderToolDetail={renderToolDetail}
|
|
531
|
+
groupPosition={getToolGroupPosition(partIndex, allParts)}
|
|
532
|
+
actions={renderToolActions?.(part as ToolPart, {
|
|
533
|
+
run,
|
|
534
|
+
messageId: msgId,
|
|
535
|
+
partIndex: index,
|
|
536
|
+
})}
|
|
537
|
+
/>
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
} else if (part.type === "reasoning") {
|
|
541
|
+
node = (
|
|
537
542
|
<InlineThinkingItem
|
|
538
|
-
key={key}
|
|
539
543
|
part={part as ReasoningPart}
|
|
540
544
|
defaultOpen={isStreaming}
|
|
541
545
|
/>
|
|
542
546
|
);
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
if (
|
|
547
|
+
} else if (
|
|
546
548
|
part.type === "text" &&
|
|
547
549
|
!part.synthetic &&
|
|
548
550
|
part.text.trim()
|
|
549
551
|
) {
|
|
550
|
-
|
|
551
|
-
<div
|
|
552
|
-
key={key}
|
|
553
|
-
className="px-1 py-1"
|
|
554
|
-
>
|
|
552
|
+
node = (
|
|
553
|
+
<div className="px-1 py-1">
|
|
555
554
|
<Markdown className="tangle-prose text-[15px] leading-7">{part.text}</Markdown>
|
|
556
555
|
</div>
|
|
557
556
|
);
|
|
558
557
|
}
|
|
559
558
|
|
|
560
|
-
return null;
|
|
559
|
+
if (!node) return null;
|
|
560
|
+
return (
|
|
561
|
+
<div key={key} className={gapClass}>
|
|
562
|
+
{node}
|
|
563
|
+
</div>
|
|
564
|
+
);
|
|
561
565
|
})}
|
|
562
566
|
</div>
|
|
563
567
|
</Collapsible.Content>
|
|
@@ -1,26 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ToolCallStep —
|
|
2
|
+
* ToolCallStep — a single agent tool invocation as a collapsible activity step.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Now a thin adapter over the canonical `InlineToolItem`: it maps the flat
|
|
5
|
+
* `ToolCallData`-style props (label / status / detail / output / duration) onto
|
|
6
|
+
* a `ToolPart` and delegates rendering, so the timeline feed (`AgentTimeline`,
|
|
7
|
+
* `ToolCallFeed`) and the run group share ONE row implementation and one look.
|
|
8
|
+
* The bespoke row markup is gone; only the prop adapter remains.
|
|
6
9
|
*/
|
|
7
10
|
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
Terminal,
|
|
11
|
-
FileText,
|
|
12
|
-
FileCode,
|
|
13
|
-
Search,
|
|
14
|
-
CheckCircle,
|
|
15
|
-
ChevronRight,
|
|
16
|
-
Loader2,
|
|
17
|
-
FolderOpen,
|
|
18
|
-
Download,
|
|
19
|
-
Pencil,
|
|
20
|
-
Eye,
|
|
21
|
-
} from "lucide-react";
|
|
22
|
-
import { cn } from "../lib/utils";
|
|
11
|
+
import { type ReactNode } from "react";
|
|
23
12
|
import { CodeBlock } from "../markdown/code-block";
|
|
13
|
+
import type { ToolPart, ToolStatus } from "../types/parts";
|
|
14
|
+
import { InlineToolItem } from "./inline-tool-item";
|
|
24
15
|
|
|
25
16
|
export type ToolCallType =
|
|
26
17
|
| "bash"
|
|
@@ -64,52 +55,19 @@ const EXT_LANGUAGE: Record<string, string> = {
|
|
|
64
55
|
go: "go",
|
|
65
56
|
sql: "sql",
|
|
66
57
|
xml: "xml",
|
|
67
|
-
}
|
|
58
|
+
};
|
|
68
59
|
|
|
69
60
|
function inferLanguage(detail?: string, language?: string): string | undefined {
|
|
70
|
-
if (language) return language
|
|
71
|
-
if (!detail) return undefined
|
|
72
|
-
const ext = detail.split(".").pop()?.toLowerCase()
|
|
73
|
-
return ext ? EXT_LANGUAGE[ext] : undefined
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function isFilePath(detail: string): boolean {
|
|
77
|
-
return /[/\\]/.test(detail) || /\.\w{1,6}$/.test(detail)
|
|
61
|
+
if (language) return language;
|
|
62
|
+
if (!detail) return undefined;
|
|
63
|
+
const ext = detail.split(".").pop()?.toLowerCase();
|
|
64
|
+
return ext ? EXT_LANGUAGE[ext] : undefined;
|
|
78
65
|
}
|
|
79
66
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<div className="flex items-center gap-1.5 rounded-[var(--radius-sm)] border border-border bg-background px-2.5 py-1.5 font-mono text-xs min-w-0">
|
|
86
|
-
<FileCode className="h-3.5 w-3.5 shrink-0 text-primary" />
|
|
87
|
-
{dir && (
|
|
88
|
-
<span className="truncate text-muted-foreground">{dir}</span>
|
|
89
|
-
)}
|
|
90
|
-
<span className="shrink-0 font-semibold text-foreground">{filename}</span>
|
|
91
|
-
</div>
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const ICONS: Record<ToolCallType, typeof Terminal> = {
|
|
96
|
-
bash: Terminal,
|
|
97
|
-
read: Eye,
|
|
98
|
-
write: FileText,
|
|
99
|
-
edit: Pencil,
|
|
100
|
-
glob: FolderOpen,
|
|
101
|
-
grep: Search,
|
|
102
|
-
list: FolderOpen,
|
|
103
|
-
download: Download,
|
|
104
|
-
inspect: Search,
|
|
105
|
-
audit: CheckCircle,
|
|
106
|
-
unknown: FileCode,
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const STATUS_COLORS: Record<ToolCallStatus, string> = {
|
|
110
|
-
running: "text-primary",
|
|
111
|
-
success: "text-[var(--code-success)]",
|
|
112
|
-
error: "text-[var(--code-error)]",
|
|
67
|
+
const STATUS_MAP: Record<ToolCallStatus, ToolStatus> = {
|
|
68
|
+
running: "running",
|
|
69
|
+
success: "completed",
|
|
70
|
+
error: "error",
|
|
113
71
|
};
|
|
114
72
|
|
|
115
73
|
export function ToolCallStep({
|
|
@@ -122,98 +80,38 @@ export function ToolCallStep({
|
|
|
122
80
|
duration,
|
|
123
81
|
className,
|
|
124
82
|
}: ToolCallStepProps) {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
83
|
+
const part: ToolPart = {
|
|
84
|
+
type: "tool",
|
|
85
|
+
id: `${type}:${label}`,
|
|
86
|
+
tool: type,
|
|
87
|
+
state: {
|
|
88
|
+
status: STATUS_MAP[status],
|
|
89
|
+
input: detail ? { detail } : undefined,
|
|
90
|
+
output,
|
|
91
|
+
time: duration != null ? { start: 0, end: duration } : undefined,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
128
95
|
const lang = inferLanguage(detail, language);
|
|
129
96
|
|
|
130
97
|
return (
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
<div
|
|
149
|
-
className={cn(
|
|
150
|
-
"flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border",
|
|
151
|
-
status === "running" && "border-[var(--border-accent)] bg-[var(--accent-surface-soft)] text-primary",
|
|
152
|
-
status === "success" && "border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]",
|
|
153
|
-
status === "error" && "border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)]",
|
|
154
|
-
)}
|
|
155
|
-
>
|
|
156
|
-
{status === "running" ? (
|
|
157
|
-
<Loader2 className="h-3 w-3 animate-spin shrink-0" />
|
|
158
|
-
) : (
|
|
159
|
-
<Icon className={cn("h-3 w-3 shrink-0", STATUS_COLORS[status])} />
|
|
160
|
-
)}
|
|
161
|
-
</div>
|
|
162
|
-
|
|
163
|
-
{/* Label */}
|
|
164
|
-
<span className="truncate flex-1 font-sans text-foreground">
|
|
165
|
-
{label}
|
|
166
|
-
</span>
|
|
167
|
-
|
|
168
|
-
<span
|
|
169
|
-
className={cn(
|
|
170
|
-
"rounded-full border px-2 py-0.5 text-[11px] font-semibold uppercase tracking-[0.06em]",
|
|
171
|
-
status === "running" &&
|
|
172
|
-
"border-border bg-[var(--accent-surface-soft)] text-primary",
|
|
173
|
-
status === "success" &&
|
|
174
|
-
"border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]",
|
|
175
|
-
status === "error" && "border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)]",
|
|
176
|
-
)}
|
|
177
|
-
>
|
|
178
|
-
{status}
|
|
179
|
-
</span>
|
|
180
|
-
|
|
181
|
-
{/* Duration */}
|
|
182
|
-
{duration !== undefined && status !== "running" && (
|
|
183
|
-
<span className="shrink-0 text-xs tabular-nums text-muted-foreground">
|
|
184
|
-
{duration < 1000 ? `${duration}ms` : `${(duration / 1000).toFixed(1)}s`}
|
|
185
|
-
</span>
|
|
186
|
-
)}
|
|
187
|
-
|
|
188
|
-
{/* Expand chevron */}
|
|
189
|
-
{hasExpandable && (
|
|
190
|
-
<ChevronRight
|
|
191
|
-
className={cn(
|
|
192
|
-
"h-3 w-3 text-muted-foreground transition-transform shrink-0",
|
|
193
|
-
expanded && "rotate-90",
|
|
194
|
-
)}
|
|
195
|
-
/>
|
|
196
|
-
)}
|
|
197
|
-
</button>
|
|
198
|
-
|
|
199
|
-
{/* Expandable content */}
|
|
200
|
-
{expanded && (detail || output) && (
|
|
201
|
-
<div className="space-y-2 border-t border-border bg-muted px-3 py-2.5">
|
|
202
|
-
{detail && (
|
|
203
|
-
isFilePath(detail)
|
|
204
|
-
? <FilePathChip path={detail} />
|
|
205
|
-
: <div className="text-xs font-mono text-muted-foreground">{detail}</div>
|
|
206
|
-
)}
|
|
207
|
-
{output && (
|
|
208
|
-
<CodeBlock
|
|
209
|
-
code={output}
|
|
210
|
-
language={lang}
|
|
211
|
-
className="max-h-72 overflow-auto text-xs"
|
|
212
|
-
/>
|
|
213
|
-
)}
|
|
214
|
-
</div>
|
|
215
|
-
)}
|
|
216
|
-
</div>
|
|
98
|
+
<InlineToolItem
|
|
99
|
+
part={part}
|
|
100
|
+
title={label}
|
|
101
|
+
description={detail}
|
|
102
|
+
className={className}
|
|
103
|
+
renderToolDetail={
|
|
104
|
+
output
|
|
105
|
+
? () => (
|
|
106
|
+
<CodeBlock
|
|
107
|
+
code={output}
|
|
108
|
+
language={lang}
|
|
109
|
+
className="max-h-72 overflow-auto text-xs"
|
|
110
|
+
/>
|
|
111
|
+
)
|
|
112
|
+
: () => null
|
|
113
|
+
}
|
|
114
|
+
/>
|
|
217
115
|
);
|
|
218
116
|
}
|
|
219
117
|
|
|
@@ -228,7 +126,7 @@ export interface ToolCallGroupProps {
|
|
|
228
126
|
|
|
229
127
|
export function ToolCallGroup({ title, children, className }: ToolCallGroupProps) {
|
|
230
128
|
return (
|
|
231
|
-
<div className={
|
|
129
|
+
<div className={["my-2 space-y-2", className].filter(Boolean).join(" ")}>
|
|
232
130
|
{title && (
|
|
233
131
|
<div className="mb-1 px-1 text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
|
234
132
|
{title}
|
package/dist/chunk-4CLN43XT.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// src/utils/format.ts
|
|
2
|
-
function formatDuration(ms) {
|
|
3
|
-
if (ms < 1e3) return "<1s";
|
|
4
|
-
const seconds = Math.floor(ms / 1e3);
|
|
5
|
-
if (seconds < 60) return `${seconds}s`;
|
|
6
|
-
const minutes = Math.floor(seconds / 60);
|
|
7
|
-
const remaining = seconds % 60;
|
|
8
|
-
return remaining > 0 ? `${minutes}m ${remaining}s` : `${minutes}m`;
|
|
9
|
-
}
|
|
10
|
-
function truncateText(text, max) {
|
|
11
|
-
const cleaned = text.replace(/\s+/g, " ").trim();
|
|
12
|
-
if (cleaned.length <= max) return cleaned;
|
|
13
|
-
return cleaned.slice(0, max).trim() + "...";
|
|
14
|
-
}
|
|
15
|
-
function formatUptime(ms) {
|
|
16
|
-
if (!Number.isFinite(ms) || ms < 0) return "\u2014";
|
|
17
|
-
const totalSeconds = Math.floor(ms / 1e3);
|
|
18
|
-
if (totalSeconds < 60) return `${totalSeconds}s`;
|
|
19
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
20
|
-
const seconds = totalSeconds % 60;
|
|
21
|
-
if (minutes < 60) return `${minutes}m ${seconds}s`;
|
|
22
|
-
const hours = Math.floor(minutes / 60);
|
|
23
|
-
const remMinutes = minutes % 60;
|
|
24
|
-
if (hours < 24) return `${hours}h ${remMinutes}m`;
|
|
25
|
-
const days = Math.floor(hours / 24);
|
|
26
|
-
const remHours = hours % 24;
|
|
27
|
-
return `${days}d ${remHours}h`;
|
|
28
|
-
}
|
|
29
|
-
function formatBytes(bytes) {
|
|
30
|
-
if (!Number.isFinite(bytes) || bytes < 0) return "\u2014";
|
|
31
|
-
if (bytes < 1024) return `${Math.round(bytes)} B`;
|
|
32
|
-
const kb = bytes / 1024;
|
|
33
|
-
if (kb < 1024) return `${kb < 10 ? kb.toFixed(1) : Math.round(kb)} KB`;
|
|
34
|
-
const mb = kb / 1024;
|
|
35
|
-
if (mb < 1024) return `${mb < 10 ? mb.toFixed(1) : Math.round(mb)} MB`;
|
|
36
|
-
const gb = mb / 1024;
|
|
37
|
-
return `${gb < 10 ? gb.toFixed(2) : gb.toFixed(1)} GB`;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export {
|
|
41
|
-
formatDuration,
|
|
42
|
-
truncateText,
|
|
43
|
-
formatUptime,
|
|
44
|
-
formatBytes
|
|
45
|
-
};
|