@tangle-network/ui 11.10.0 → 11.11.1
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 +14 -0
- package/README.md +4 -1
- package/dist/active-sessions-store-Gt1R0rFG.js +262 -0
- package/dist/{active-sessions-store-CeOmXgv5.d.ts → active-sessions-store-nl70ZnMC.d.ts} +40 -41
- package/dist/artifact-pane-BL_DFWNl.d.ts +32 -0
- package/dist/artifact-pane-DMXT9a8U.js +70 -0
- package/dist/auth-DOETfnd9.js +154 -0
- package/dist/auth.d.ts +2 -74
- package/dist/auth.js +2 -16
- package/dist/branding-26d5ARIr.d.ts +14 -0
- package/dist/button-C87nEe2R.js +78 -0
- package/dist/button-yoIv77e2.d.ts +16 -0
- package/dist/chat-D4jAfEmj.js +667 -0
- package/dist/chat.d.ts +2 -201
- package/dist/chat.js +2 -31
- package/dist/code-block-B36KVUSN.js +165 -0
- package/dist/code-block-B9miUPht.d.ts +23 -0
- package/dist/diff-preview-BcK3nRXb.js +533 -0
- package/dist/document-editor-pane-BcoABlhn.d.ts +131 -0
- package/dist/document-editor-pane-BxlPjaTP.js +1287 -0
- package/dist/dropdown-menu-BpcLa5vF.js +101 -0
- package/dist/editor.d.ts +76 -78
- package/dist/editor.js +2 -34
- package/dist/file-format-BgXbr-Ib.js +160 -0
- package/dist/files-Bug33qCl.js +743 -0
- package/dist/files.d.ts +2 -243
- package/dist/files.js +3 -41
- package/dist/focus-BcE_SHqz.js +57 -0
- package/dist/format-DfcLWqMa.js +54 -0
- package/dist/hooks.d.ts +30 -37
- package/dist/hooks.js +111 -46
- package/dist/index-2UntyjBb.d.ts +52 -0
- package/dist/index-BgUHilZm.d.ts +108 -0
- package/dist/index-COgqsFAQ.d.ts +42 -0
- package/dist/index-CPDET_s1.d.ts +549 -0
- package/dist/index-CUhfHT_V.d.ts +204 -0
- package/dist/index-Cg6gYAqh.d.ts +73 -0
- package/dist/index-Cq-EJzqW.d.ts +16 -0
- package/dist/index-DhYmSaLF.d.ts +245 -0
- package/dist/index-DjKxO357.d.ts +128 -0
- package/dist/index.d.ts +26 -43
- package/dist/index.js +35 -472
- package/dist/markdown-BGqicV82.js +45 -0
- package/dist/markdown.d.ts +3 -18
- package/dist/markdown.js +3 -15
- package/dist/message-vhUI0c5G.d.ts +16 -0
- package/dist/nav.d.ts +6 -8
- package/dist/nav.js +29 -11
- package/dist/openui-artifact-renderer-D3E5bIAI.d.ts +114 -0
- package/dist/openui-artifact-renderer-DrU1AdVk.js +266 -0
- package/dist/openui.d.ts +2 -115
- package/dist/openui.js +2 -13
- package/dist/parts-5mhy9yJ3.d.ts +37 -0
- package/dist/primitives-Cb8GGVKr.js +1239 -0
- package/dist/primitives.d.ts +5 -525
- package/dist/primitives.js +9 -212
- package/dist/redaction-CGGB2ENG.js +74 -0
- package/dist/redaction.d.ts +2 -42
- package/dist/redaction.js +2 -7
- package/dist/run-OyWmIDqu.d.ts +41 -0
- package/dist/run-ZsIKPA6J.js +17 -0
- package/dist/run-group-BACLbCFl.js +410 -0
- package/dist/run.d.ts +3 -126
- package/dist/run.js +5 -40
- package/dist/sdk-hooks.d.ts +2 -285
- package/dist/sdk-hooks.js +3 -36
- package/dist/stores.d.ts +13 -14
- package/dist/stores.js +34 -76
- package/dist/table-Bss73DhB.js +146 -0
- package/dist/tabs-BVHR6NkO.js +40 -0
- package/dist/text-shimmer-BUUo6I-g.js +64 -0
- package/dist/tool-call-feed-BeB1_4pX.d.ts +47 -0
- package/dist/tool-call-feed-Djt2q11V.js +109 -0
- package/dist/tool-call-step-DNebqhmX.js +434 -0
- package/dist/tool-display-BAuAVa43.js +158 -0
- package/dist/{tool-display-z4JcDmMQ.d.ts → tool-display-DgmL5rIU.d.ts} +16 -16
- package/dist/tool-previews.d.ts +2 -48
- package/dist/tool-previews.js +2 -23
- package/dist/types.d.ts +6 -19
- package/dist/types.js +0 -1
- package/dist/use-auto-scroll-C5Pjeqon.js +153 -0
- package/dist/use-sse-stream-BVgO1QBN.js +884 -0
- package/dist/use-sse-stream-Dm6R5YWz.d.ts +282 -0
- package/dist/utils-Bl_CZ0Qp.js +37 -0
- package/dist/{chunk-RQHJBTEU.js → utils-C_uf36nf.js} +4 -6
- package/dist/utils.d.ts +2 -104
- package/dist/utils.js +6 -44
- package/package.json +39 -41
- package/src/lib/focus.ts +2 -1
- package/dist/artifact-pane-DpuWcAiF.d.ts +0 -33
- package/dist/button-CMQuQEW_.d.ts +0 -17
- package/dist/chunk-34A66VBG.js +0 -214
- package/dist/chunk-3OI2QKFD.js +0 -0
- package/dist/chunk-3XXBZL53.js +0 -174
- package/dist/chunk-42PAH5D2.js +0 -112
- package/dist/chunk-4CLN43XT.js +0 -45
- package/dist/chunk-55WHV7SS.js +0 -1604
- package/dist/chunk-565EATZZ.js +0 -156
- package/dist/chunk-5Z5ZYMOJ.js +0 -0
- package/dist/chunk-6BGQA4BQ.js +0 -0
- package/dist/chunk-BEBXZPHW.js +0 -299
- package/dist/chunk-C5WF4WMV.js +0 -734
- package/dist/chunk-HFL6R6IF.js +0 -37
- package/dist/chunk-HGML45QH.js +0 -104
- package/dist/chunk-HMAPIH7L.js +0 -595
- package/dist/chunk-K5XFRUS4.js +0 -1401
- package/dist/chunk-KFQGHD73.js +0 -198
- package/dist/chunk-L57WRIND.js +0 -59
- package/dist/chunk-LTEKI7YJ.js +0 -59
- package/dist/chunk-M3QZK62R.js +0 -233
- package/dist/chunk-ND3ZFXQK.js +0 -179
- package/dist/chunk-OEX7NZE3.js +0 -321
- package/dist/chunk-OL5GYLHV.js +0 -60
- package/dist/chunk-QGFYBNSO.js +0 -133
- package/dist/chunk-R7B3UWPF.js +0 -550
- package/dist/chunk-R7SUY4E3.js +0 -65
- package/dist/chunk-REJESC5U.js +0 -117
- package/dist/chunk-RQGKSCEZ.js +0 -0
- package/dist/chunk-SNLR2AEA.js +0 -40
- package/dist/chunk-WKWBTL2V.js +0 -15
- package/dist/chunk-X7CU776B.js +0 -1048
- package/dist/chunk-XU3HB5QL.js +0 -127
- package/dist/chunk-YTO5V6QS.js +0 -19
- package/dist/chunk-YU4E5J2N.js +0 -437
- package/dist/chunk-YZ6AK25N.js +0 -886
- package/dist/code-block-0kSpWMnf.d.ts +0 -25
- package/dist/document-editor-pane-IAEQn_Dl.d.ts +0 -128
- package/dist/document-editor-pane-QHDOBA43.js +0 -13
- package/dist/message-BHWbxBtT.d.ts +0 -15
- package/dist/parts-dj7AcUg0.d.ts +0 -36
- package/dist/run-PfLmDAox.d.ts +0 -41
- package/dist/tool-call-feed-D9iofJgW.d.ts +0 -46
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { t as cn } from "./utils-C_uf36nf.js";
|
|
2
|
+
import { useEffect, useLayoutEffect } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/primitives/text-shimmer.tsx
|
|
5
|
+
const CLASS_NAME = "tangle-text-shimmer";
|
|
6
|
+
const STYLE_ID = "tangle-text-shimmer-styles";
|
|
7
|
+
/**
|
|
8
|
+
* The sweep is a MASK over the text's own colour, not a gradient background
|
|
9
|
+
* clipped to the glyphs: if this stylesheet is missing the text still renders
|
|
10
|
+
* in its normal colour instead of disappearing (`color: transparent`).
|
|
11
|
+
*
|
|
12
|
+
* Mask geometry mirrors the background variant: a 250%-wide tile whose bright
|
|
13
|
+
* band sits at 45–60%, slid from 150% to -50% so one band crosses the text per
|
|
14
|
+
* cycle. The tile repeats, so the .72 floor covers every glyph at every frame —
|
|
15
|
+
* the label reads at ~72% foreground opacity with a brighter sweep through it.
|
|
16
|
+
*/
|
|
17
|
+
const SHIMMER_CSS = `
|
|
18
|
+
@keyframes ${CLASS_NAME} {
|
|
19
|
+
from { -webkit-mask-position: 150% center; mask-position: 150% center; }
|
|
20
|
+
to { -webkit-mask-position: -50% center; mask-position: -50% center; }
|
|
21
|
+
}
|
|
22
|
+
.${CLASS_NAME} {
|
|
23
|
+
-webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,0.72) 0%, #000 45%, rgba(0,0,0,0.72) 60%);
|
|
24
|
+
mask-image: linear-gradient(90deg, rgba(0,0,0,0.72) 0%, #000 45%, rgba(0,0,0,0.72) 60%);
|
|
25
|
+
-webkit-mask-size: 250% 100%;
|
|
26
|
+
mask-size: 250% 100%;
|
|
27
|
+
animation: ${CLASS_NAME} 1.4s linear infinite;
|
|
28
|
+
}
|
|
29
|
+
@media (prefers-reduced-motion: reduce) {
|
|
30
|
+
.${CLASS_NAME} {
|
|
31
|
+
animation: none;
|
|
32
|
+
-webkit-mask-image: none;
|
|
33
|
+
mask-image: none;
|
|
34
|
+
text-decoration: underline dotted currentColor;
|
|
35
|
+
text-underline-offset: 3px;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
/** Inject the shimmer stylesheet once per document. A no-op on the server. */
|
|
40
|
+
function ensureShimmerStyles() {
|
|
41
|
+
if (typeof document === "undefined") return;
|
|
42
|
+
if (document.getElementById(STYLE_ID)) return;
|
|
43
|
+
const style = document.createElement("style");
|
|
44
|
+
style.id = STYLE_ID;
|
|
45
|
+
style.textContent = SHIMMER_CSS;
|
|
46
|
+
document.head.appendChild(style);
|
|
47
|
+
}
|
|
48
|
+
const useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
|
|
49
|
+
/**
|
|
50
|
+
* Inline text with a gradient-mask sweep — the in-flight signal for a run row
|
|
51
|
+
* label ("Thinking…", a tool verb while its call is running). Carries the
|
|
52
|
+
* styles it needs, so a consumer that only scans this package for Tailwind
|
|
53
|
+
* classes still gets the animation.
|
|
54
|
+
*/
|
|
55
|
+
function TextShimmer({ children, className, durationMs = 1400 }) {
|
|
56
|
+
useIsomorphicLayoutEffect(ensureShimmerStyles, []);
|
|
57
|
+
return /* @__PURE__ */ jsx("span", {
|
|
58
|
+
className: cn(CLASS_NAME, "text-foreground", className),
|
|
59
|
+
style: { animationDuration: `${durationMs}ms` },
|
|
60
|
+
children
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { TextShimmer as t };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/run/tool-call-step.d.ts
|
|
3
|
+
type ToolCallType = "bash" | "read" | "write" | "edit" | "glob" | "grep" | "list" | "download" | "inspect" | "audit" | "unknown";
|
|
4
|
+
type ToolCallStatus = "running" | "success" | "error";
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region src/run/tool-call-feed.d.ts
|
|
7
|
+
interface ToolCallData {
|
|
8
|
+
id: string;
|
|
9
|
+
type: ToolCallType;
|
|
10
|
+
label: string;
|
|
11
|
+
status: ToolCallStatus;
|
|
12
|
+
detail?: string;
|
|
13
|
+
output?: string;
|
|
14
|
+
duration?: number;
|
|
15
|
+
}
|
|
16
|
+
type FeedSegment = {
|
|
17
|
+
kind: "text";
|
|
18
|
+
content: string;
|
|
19
|
+
} | {
|
|
20
|
+
kind: "tool_call";
|
|
21
|
+
call: ToolCallData;
|
|
22
|
+
} | {
|
|
23
|
+
kind: "tool_group";
|
|
24
|
+
title?: string;
|
|
25
|
+
calls: ToolCallData[];
|
|
26
|
+
};
|
|
27
|
+
interface ToolCallFeedProps {
|
|
28
|
+
segments: FeedSegment[];
|
|
29
|
+
className?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Renders a feed of interleaved text and tool calls.
|
|
33
|
+
*/
|
|
34
|
+
declare function ToolCallFeed({ segments, className }: ToolCallFeedProps): import("react").JSX.Element | null;
|
|
35
|
+
/**
|
|
36
|
+
* Parse raw SSE tool events into FeedSegments.
|
|
37
|
+
*
|
|
38
|
+
* This is the bridge between the orchestrator's SSE stream format
|
|
39
|
+
* and the ToolCallFeed component. Consumers call this in their
|
|
40
|
+
* useToolCallStream hook.
|
|
41
|
+
*/
|
|
42
|
+
declare function parseToolEvent(event: {
|
|
43
|
+
type: string;
|
|
44
|
+
data: Record<string, unknown>;
|
|
45
|
+
}): ToolCallData | null;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { parseToolEvent as a, ToolCallFeedProps as i, ToolCallData as n, ToolCallStatus as o, ToolCallFeed as r, ToolCallType as s, FeedSegment as t };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { t as cn } from "./utils-C_uf36nf.js";
|
|
2
|
+
import { n as ToolCallStep, t as ToolCallGroup } from "./tool-call-step-DNebqhmX.js";
|
|
3
|
+
import { t as Markdown } from "./markdown-BGqicV82.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/run/tool-call-feed.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Renders a feed of interleaved text and tool calls.
|
|
8
|
+
*/
|
|
9
|
+
function ToolCallFeed({ segments, className }) {
|
|
10
|
+
if (segments.length === 0) return null;
|
|
11
|
+
return /* @__PURE__ */ jsx("div", {
|
|
12
|
+
className: cn("space-y-1", className),
|
|
13
|
+
children: segments.map((segment, i) => {
|
|
14
|
+
if (segment.kind === "text") return segment.content.trim() ? /* @__PURE__ */ jsx(Markdown, { children: segment.content }, i) : null;
|
|
15
|
+
if (segment.kind === "tool_call") return /* @__PURE__ */ jsx(ToolCallStep, {
|
|
16
|
+
type: segment.call.type,
|
|
17
|
+
label: segment.call.label,
|
|
18
|
+
status: segment.call.status,
|
|
19
|
+
detail: segment.call.detail,
|
|
20
|
+
output: segment.call.output,
|
|
21
|
+
duration: segment.call.duration
|
|
22
|
+
}, segment.call.id || i);
|
|
23
|
+
if (segment.kind === "tool_group") return /* @__PURE__ */ jsx(ToolCallGroup, {
|
|
24
|
+
title: segment.title,
|
|
25
|
+
children: segment.calls.map((call) => /* @__PURE__ */ jsx(ToolCallStep, {
|
|
26
|
+
type: call.type,
|
|
27
|
+
label: call.label,
|
|
28
|
+
status: call.status,
|
|
29
|
+
detail: call.detail,
|
|
30
|
+
output: call.output,
|
|
31
|
+
duration: call.duration
|
|
32
|
+
}, call.id))
|
|
33
|
+
}, i);
|
|
34
|
+
return null;
|
|
35
|
+
})
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Parse raw SSE tool events into FeedSegments.
|
|
40
|
+
*
|
|
41
|
+
* This is the bridge between the orchestrator's SSE stream format
|
|
42
|
+
* and the ToolCallFeed component. Consumers call this in their
|
|
43
|
+
* useToolCallStream hook.
|
|
44
|
+
*/
|
|
45
|
+
function parseToolEvent(event) {
|
|
46
|
+
const { type, data } = event;
|
|
47
|
+
if (type === "tool.invocation" || type === "tool_use") {
|
|
48
|
+
const toolName = data.name || data.tool || "unknown";
|
|
49
|
+
const input = data.input;
|
|
50
|
+
return {
|
|
51
|
+
id: data.id || data.toolUseId || createId(),
|
|
52
|
+
type: mapToolName(toolName),
|
|
53
|
+
label: formatToolLabel(toolName, input),
|
|
54
|
+
status: "running",
|
|
55
|
+
detail: input ? formatToolInput(toolName, input) : void 0
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (type === "tool.result" || type === "tool_result") return {
|
|
59
|
+
id: data.id || data.toolUseId || "",
|
|
60
|
+
type: mapToolName(data.name || data.tool || "unknown"),
|
|
61
|
+
label: formatToolLabel(data.name || data.tool || "unknown"),
|
|
62
|
+
status: data.error ? "error" : "success",
|
|
63
|
+
output: truncate(data.output || data.result || "", 500),
|
|
64
|
+
duration: data.duration
|
|
65
|
+
};
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
function createId() {
|
|
69
|
+
if (typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.randomUUID === "function") try {
|
|
70
|
+
return globalThis.crypto.randomUUID();
|
|
71
|
+
} catch {}
|
|
72
|
+
return `tool_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
73
|
+
}
|
|
74
|
+
function mapToolName(name) {
|
|
75
|
+
const lower = name.toLowerCase();
|
|
76
|
+
if (lower.includes("bash") || lower.includes("terminal") || lower.includes("exec")) return "bash";
|
|
77
|
+
if (lower.includes("read") || lower.includes("cat")) return "read";
|
|
78
|
+
if (lower.includes("write") || lower.includes("create")) return "write";
|
|
79
|
+
if (lower.includes("edit") || lower.includes("replace")) return "edit";
|
|
80
|
+
if (lower.includes("glob") || lower.includes("find")) return "glob";
|
|
81
|
+
if (lower.includes("grep") || lower.includes("search")) return "grep";
|
|
82
|
+
if (lower.includes("list") || lower.includes("ls")) return "list";
|
|
83
|
+
if (lower.includes("inspect")) return "inspect";
|
|
84
|
+
if (lower.includes("audit")) return "audit";
|
|
85
|
+
return "unknown";
|
|
86
|
+
}
|
|
87
|
+
function formatToolLabel(toolName, input) {
|
|
88
|
+
const lower = toolName.toLowerCase();
|
|
89
|
+
if (lower.includes("bash") && input?.command) {
|
|
90
|
+
const cmd = String(input.command);
|
|
91
|
+
return cmd.length > 80 ? `${cmd.slice(0, 77)}...` : cmd;
|
|
92
|
+
}
|
|
93
|
+
if ((lower.includes("read") || lower.includes("cat")) && input?.path) return `Read ${input.path}`;
|
|
94
|
+
if (lower.includes("write") && input?.path) return `Write ${input.path}`;
|
|
95
|
+
if (lower.includes("edit") && input?.path) return `Edit ${input.path}`;
|
|
96
|
+
if (lower.includes("glob") && input?.pattern) return `Find ${input.pattern}`;
|
|
97
|
+
if (lower.includes("grep") && input?.pattern) return `Search for ${input.pattern}`;
|
|
98
|
+
return toolName;
|
|
99
|
+
}
|
|
100
|
+
function formatToolInput(toolName, input) {
|
|
101
|
+
if (input.command) return String(input.command);
|
|
102
|
+
if (input.path) return String(input.path);
|
|
103
|
+
return JSON.stringify(input, null, 2).slice(0, 300);
|
|
104
|
+
}
|
|
105
|
+
function truncate(text, max) {
|
|
106
|
+
return text.length > max ? text.slice(0, max - 3) + "..." : text;
|
|
107
|
+
}
|
|
108
|
+
//#endregion
|
|
109
|
+
export { parseToolEvent as n, ToolCallFeed as t };
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
import { t as cn } from "./utils-C_uf36nf.js";
|
|
2
|
+
import { t as TextShimmer } from "./text-shimmer-BUUo6I-g.js";
|
|
3
|
+
import { t as CodeBlock } from "./code-block-B36KVUSN.js";
|
|
4
|
+
import { i as getToolErrorText, n as getToolCategory, r as getToolDisplayMetadata } from "./tool-display-BAuAVa43.js";
|
|
5
|
+
import { n as formatDuration } from "./format-DfcLWqMa.js";
|
|
6
|
+
import { a as GrepResultsPreview, i as GlobResultsPreview, n as QuestionPreview, o as WriteFilePreview, r as WebSearchPreview, s as CommandPreview, t as DiffPreview } from "./diff-preview-BcK3nRXb.js";
|
|
7
|
+
import { memo, useEffect, useRef, useState } from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { AlertCircle, ArrowLeft, ArrowRight, Bot, ChevronRight, ClipboardList, FileEdit, FileSearch, FileText, Globe, Loader2, PencilLine, Search, Settings, Terminal } from "lucide-react";
|
|
10
|
+
import * as Collapsible from "@radix-ui/react-collapsible";
|
|
11
|
+
//#region src/run/expandable-content.tsx
|
|
12
|
+
/**
|
|
13
|
+
* Clamps tall content to a fixed height with a bottom fade and a
|
|
14
|
+
* "Show more / Show less" toggle. Content shorter than the cap renders
|
|
15
|
+
* as-is with no toggle.
|
|
16
|
+
*/
|
|
17
|
+
function ExpandableContent({ children, collapsedMaxPx = 180, fadeClassName = "from-muted", className }) {
|
|
18
|
+
const [expanded, setExpanded] = useState(false);
|
|
19
|
+
const [overflowing, setOverflowing] = useState(false);
|
|
20
|
+
const contentRef = useRef(null);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const el = contentRef.current;
|
|
23
|
+
if (!el) return;
|
|
24
|
+
const measure = () => setOverflowing(el.scrollHeight > collapsedMaxPx + 4);
|
|
25
|
+
measure();
|
|
26
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
27
|
+
const observer = new ResizeObserver(measure);
|
|
28
|
+
observer.observe(el);
|
|
29
|
+
return () => observer.disconnect();
|
|
30
|
+
}, [collapsedMaxPx]);
|
|
31
|
+
const clamped = overflowing && !expanded;
|
|
32
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
33
|
+
className,
|
|
34
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
35
|
+
ref: contentRef,
|
|
36
|
+
className: "relative overflow-hidden",
|
|
37
|
+
style: clamped ? { maxHeight: collapsedMaxPx } : void 0,
|
|
38
|
+
children: [children, clamped ? /* @__PURE__ */ jsx("div", { className: cn("pointer-events-none absolute inset-x-0 bottom-0 h-10 bg-gradient-to-t to-transparent", fadeClassName) }) : null]
|
|
39
|
+
}), overflowing ? /* @__PURE__ */ jsx("button", {
|
|
40
|
+
type: "button",
|
|
41
|
+
onClick: () => setExpanded((value) => !value),
|
|
42
|
+
className: "mt-1 text-[11px] font-medium text-muted-foreground transition-colors hover:text-foreground",
|
|
43
|
+
children: expanded ? "Show less" : "Show more"
|
|
44
|
+
}) : null]
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/run/expanded-tool-detail.tsx
|
|
49
|
+
const EXT_LANG = {
|
|
50
|
+
ts: "typescript",
|
|
51
|
+
tsx: "tsx",
|
|
52
|
+
js: "javascript",
|
|
53
|
+
jsx: "jsx",
|
|
54
|
+
rs: "rust",
|
|
55
|
+
py: "python",
|
|
56
|
+
go: "go",
|
|
57
|
+
rb: "ruby",
|
|
58
|
+
json: "json",
|
|
59
|
+
yaml: "yaml",
|
|
60
|
+
yml: "yaml",
|
|
61
|
+
toml: "toml",
|
|
62
|
+
md: "markdown",
|
|
63
|
+
css: "css",
|
|
64
|
+
scss: "scss",
|
|
65
|
+
html: "html",
|
|
66
|
+
sh: "bash",
|
|
67
|
+
bash: "bash",
|
|
68
|
+
zsh: "bash",
|
|
69
|
+
sql: "sql",
|
|
70
|
+
sol: "solidity",
|
|
71
|
+
proto: "protobuf"
|
|
72
|
+
};
|
|
73
|
+
function langFromPath(path) {
|
|
74
|
+
if (!path) return void 0;
|
|
75
|
+
const ext = path.split(".").pop()?.toLowerCase();
|
|
76
|
+
return ext ? EXT_LANG[ext] : void 0;
|
|
77
|
+
}
|
|
78
|
+
/** Format an unknown value as a displayable string. */
|
|
79
|
+
function formatOutput(value) {
|
|
80
|
+
if (value == null) return "";
|
|
81
|
+
if (typeof value === "string") return value;
|
|
82
|
+
try {
|
|
83
|
+
return JSON.stringify(value, null, 2);
|
|
84
|
+
} catch {
|
|
85
|
+
return String(value);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Renders full tool details when a tool item is expanded.
|
|
90
|
+
* Dispatches to specialised previews (CommandPreview, WriteFilePreview)
|
|
91
|
+
* or falls back to a generic input/output code view.
|
|
92
|
+
*/
|
|
93
|
+
const ExpandedToolDetail = memo(({ part }) => {
|
|
94
|
+
const meta = getToolDisplayMetadata(part);
|
|
95
|
+
const { status, input, output, error } = part.state;
|
|
96
|
+
if (meta.displayVariant === "command") return /* @__PURE__ */ jsx(CommandPreview, { part });
|
|
97
|
+
if (meta.displayVariant === "write-file") return /* @__PURE__ */ jsx(WriteFilePreview, { part });
|
|
98
|
+
if (meta.displayVariant === "grep") return /* @__PURE__ */ jsx(GrepResultsPreview, { part });
|
|
99
|
+
if (meta.displayVariant === "glob") return /* @__PURE__ */ jsx(GlobResultsPreview, { part });
|
|
100
|
+
if (meta.displayVariant === "web-search") return /* @__PURE__ */ jsx(WebSearchPreview, { part });
|
|
101
|
+
if (meta.displayVariant === "question") return /* @__PURE__ */ jsx(QuestionPreview, { part });
|
|
102
|
+
if (meta.displayVariant === "diff") return /* @__PURE__ */ jsx(DiffPreview, { part });
|
|
103
|
+
if (meta.displayVariant === "read-file") return /* @__PURE__ */ jsxs("div", {
|
|
104
|
+
className: "overflow-hidden rounded-[var(--radius-lg)] border border-border bg-card shadow-[var(--shadow-card)]",
|
|
105
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
106
|
+
className: "flex items-center gap-2.5 border-b border-border bg-card px-3 py-2",
|
|
107
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
108
|
+
className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border border-[var(--border-accent)] bg-muted text-primary",
|
|
109
|
+
children: /* @__PURE__ */ jsx(FileText, { className: "h-3.5 w-3.5" })
|
|
110
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
111
|
+
className: "min-w-0 flex items-center gap-2",
|
|
112
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
113
|
+
className: "text-xs font-semibold text-foreground",
|
|
114
|
+
children: "Read file"
|
|
115
|
+
}), meta.targetPath ? /* @__PURE__ */ jsx("span", {
|
|
116
|
+
className: "truncate text-xs font-mono text-muted-foreground",
|
|
117
|
+
children: meta.targetPath
|
|
118
|
+
}) : null]
|
|
119
|
+
})]
|
|
120
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
121
|
+
className: "space-y-2 px-3 py-2.5",
|
|
122
|
+
children: [typeof output === "string" ? /* @__PURE__ */ jsx(CodeBlock, {
|
|
123
|
+
code: output,
|
|
124
|
+
language: langFromPath(meta.targetPath) ?? "text",
|
|
125
|
+
className: "rounded-[var(--radius-md)]"
|
|
126
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
127
|
+
className: "rounded-[var(--radius-md)] border border-dashed border-border bg-muted px-3 py-4 text-sm text-muted-foreground",
|
|
128
|
+
children: "No readable file content was returned."
|
|
129
|
+
}), error ? /* @__PURE__ */ jsx("div", {
|
|
130
|
+
className: "rounded-[var(--radius-md)] border border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] px-3 py-3 text-sm text-[var(--surface-danger-text)]",
|
|
131
|
+
children: error
|
|
132
|
+
}) : null]
|
|
133
|
+
})]
|
|
134
|
+
});
|
|
135
|
+
const inputStr = formatOutput(input);
|
|
136
|
+
const outputStr = formatOutput(output);
|
|
137
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
138
|
+
className: "space-y-3",
|
|
139
|
+
children: [
|
|
140
|
+
inputStr && /* @__PURE__ */ jsxs("div", {
|
|
141
|
+
className: "overflow-hidden rounded-[var(--radius-lg)] border border-border bg-card",
|
|
142
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
143
|
+
className: "flex items-center gap-2 border-b border-border bg-background px-3 py-2",
|
|
144
|
+
children: [/* @__PURE__ */ jsx(ArrowRight, { className: "h-3 w-3 text-primary" }), /* @__PURE__ */ jsx("span", {
|
|
145
|
+
className: "text-xs font-medium uppercase tracking-[0.08em] text-muted-foreground",
|
|
146
|
+
children: "Input"
|
|
147
|
+
})]
|
|
148
|
+
}), /* @__PURE__ */ jsx(CodeBlock, {
|
|
149
|
+
code: inputStr,
|
|
150
|
+
language: "json",
|
|
151
|
+
className: "rounded-none border-0"
|
|
152
|
+
})]
|
|
153
|
+
}),
|
|
154
|
+
status === "completed" && outputStr && /* @__PURE__ */ jsxs("div", {
|
|
155
|
+
className: "overflow-hidden rounded-[var(--radius-lg)] border border-border bg-card",
|
|
156
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
157
|
+
className: "flex items-center gap-2 border-b border-border bg-background px-3 py-2",
|
|
158
|
+
children: [/* @__PURE__ */ jsx(ArrowLeft, { className: "h-3 w-3 text-primary" }), /* @__PURE__ */ jsx("span", {
|
|
159
|
+
className: "text-xs font-medium uppercase tracking-[0.08em] text-muted-foreground",
|
|
160
|
+
children: "Output"
|
|
161
|
+
})]
|
|
162
|
+
}), /* @__PURE__ */ jsx(ExpandableContent, {
|
|
163
|
+
fadeClassName: "from-card",
|
|
164
|
+
children: /* @__PURE__ */ jsx(CodeBlock, {
|
|
165
|
+
code: outputStr.length > 2e3 ? outputStr.slice(0, 2e3) + "\n...(truncated)" : outputStr,
|
|
166
|
+
language: "json",
|
|
167
|
+
className: "rounded-none border-0"
|
|
168
|
+
})
|
|
169
|
+
})]
|
|
170
|
+
}),
|
|
171
|
+
error && /* @__PURE__ */ jsxs("div", {
|
|
172
|
+
className: "overflow-hidden rounded-[var(--radius-lg)] border border-[var(--surface-danger-border)]",
|
|
173
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
174
|
+
className: "flex items-center gap-2 border-b border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] px-3 py-2",
|
|
175
|
+
children: [/* @__PURE__ */ jsx(AlertCircle, { className: "h-3 w-3 text-[var(--surface-danger-text)]" }), /* @__PURE__ */ jsx("span", {
|
|
176
|
+
className: "text-xs font-medium uppercase tracking-[0.08em] text-[var(--surface-danger-text)]",
|
|
177
|
+
children: "Error"
|
|
178
|
+
})]
|
|
179
|
+
}), /* @__PURE__ */ jsx(ExpandableContent, {
|
|
180
|
+
fadeClassName: "from-[var(--surface-danger-bg)]",
|
|
181
|
+
children: /* @__PURE__ */ jsx("pre", {
|
|
182
|
+
className: "bg-[var(--surface-danger-bg)] p-3 text-xs font-mono whitespace-pre-wrap break-all text-[var(--surface-danger-text)]",
|
|
183
|
+
children: error
|
|
184
|
+
})
|
|
185
|
+
})]
|
|
186
|
+
}),
|
|
187
|
+
(status === "pending" || status === "running") && /* @__PURE__ */ jsxs("div", {
|
|
188
|
+
className: "flex items-center gap-2 rounded-[var(--radius-md)] border border-border bg-muted px-3 py-3 text-xs text-muted-foreground",
|
|
189
|
+
children: [/* @__PURE__ */ jsx(Loader2, { className: cn("h-3 w-3 animate-spin text-primary") }), "Running…"]
|
|
190
|
+
})
|
|
191
|
+
]
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
ExpandedToolDetail.displayName = "ExpandedToolDetail";
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/run/run-row-shell.tsx
|
|
197
|
+
/**
|
|
198
|
+
* Trailing status indicator shared by every run row. Only `error` draws a
|
|
199
|
+
* mark (a red dot). Success is silence, and a running row carries its state in
|
|
200
|
+
* the title — a `TextShimmer` sweep — so neither renders anything here.
|
|
201
|
+
*/
|
|
202
|
+
function RunRowStatusDot({ status }) {
|
|
203
|
+
if (status !== "error") return null;
|
|
204
|
+
return /* @__PURE__ */ jsx("span", {
|
|
205
|
+
"data-run-row-status": "error",
|
|
206
|
+
className: "h-1.5 w-1.5 shrink-0 rounded-full bg-[var(--surface-danger-text)]"
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
const SHAPE_CLASS = {
|
|
210
|
+
single: "rounded-[var(--radius-lg)]",
|
|
211
|
+
first: "rounded-t-[var(--radius-lg)] rounded-b-[var(--radius-sm)]",
|
|
212
|
+
middle: "rounded-[var(--radius-sm)]",
|
|
213
|
+
last: "rounded-t-[var(--radius-sm)] rounded-b-[var(--radius-lg)]"
|
|
214
|
+
};
|
|
215
|
+
const HEADER_INSET = "px-2 py-1";
|
|
216
|
+
const ERROR_INDENT = "pl-[2.375rem]";
|
|
217
|
+
/**
|
|
218
|
+
* Shared shell for the agent activity rows (reasoning + tool). A quiet
|
|
219
|
+
* one-liner at rest — bare glyph, muted title and description, no fill, no
|
|
220
|
+
* border — that becomes a bordered card only while open. The border is always
|
|
221
|
+
* present (transparent at rest) so hover and expand never shift layout.
|
|
222
|
+
* Both row kinds render through it so they read as one family.
|
|
223
|
+
*/
|
|
224
|
+
function RunRowShell({ icon, title, description, descriptionMono = false, status = "idle", durationMs, groupPosition = "single", collapsedError, actions, open: openProp, onOpenChange, defaultOpen = false, className, contentClassName, children }) {
|
|
225
|
+
const [openState, setOpenState] = useState(defaultOpen);
|
|
226
|
+
const isControlled = openProp !== void 0;
|
|
227
|
+
const open = isControlled ? openProp : openState;
|
|
228
|
+
const setOpen = (next) => {
|
|
229
|
+
if (!isControlled) setOpenState(next);
|
|
230
|
+
onOpenChange?.(next);
|
|
231
|
+
};
|
|
232
|
+
const isRunning = status === "running";
|
|
233
|
+
const expandable = children != null;
|
|
234
|
+
return /* @__PURE__ */ jsx(Collapsible.Root, {
|
|
235
|
+
open,
|
|
236
|
+
onOpenChange: setOpen,
|
|
237
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
238
|
+
className: "flex items-start gap-2",
|
|
239
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
240
|
+
"data-run-row": "",
|
|
241
|
+
"data-state": open ? "open" : "closed",
|
|
242
|
+
className: cn("group min-w-0 flex-1 overflow-hidden border transition-colors", open ? "border-border bg-[var(--md3-surface-container)]" : "border-transparent bg-transparent", expandable && !open && "hover:bg-[var(--md3-surface-container)]", SHAPE_CLASS[groupPosition], className),
|
|
243
|
+
children: [
|
|
244
|
+
/* @__PURE__ */ jsx(Collapsible.Trigger, {
|
|
245
|
+
asChild: true,
|
|
246
|
+
disabled: !expandable,
|
|
247
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
248
|
+
type: "button",
|
|
249
|
+
className: cn("flex w-full items-center gap-2 text-left", HEADER_INSET, expandable ? "cursor-pointer" : "cursor-default"),
|
|
250
|
+
children: [
|
|
251
|
+
/* @__PURE__ */ jsxs("span", {
|
|
252
|
+
"aria-hidden": true,
|
|
253
|
+
className: "flex h-[1.375rem] w-[1.375rem] shrink-0 items-center justify-center text-muted-foreground",
|
|
254
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
255
|
+
"data-run-row-glyph": "",
|
|
256
|
+
className: cn("flex items-center justify-center", expandable && "group-hover:hidden", open && "hidden"),
|
|
257
|
+
children: icon
|
|
258
|
+
}), expandable ? /* @__PURE__ */ jsx(ChevronRight, {
|
|
259
|
+
"data-run-row-chevron": "",
|
|
260
|
+
className: cn("hidden h-3.5 w-3.5 transition-transform group-hover:block", open && "block rotate-90")
|
|
261
|
+
}) : null]
|
|
262
|
+
}),
|
|
263
|
+
/* @__PURE__ */ jsx("span", {
|
|
264
|
+
className: cn("shrink-0 whitespace-nowrap text-sm font-normal text-muted-foreground transition-colors group-hover:text-foreground", open && "text-foreground"),
|
|
265
|
+
children: title
|
|
266
|
+
}),
|
|
267
|
+
description ? /* @__PURE__ */ jsx("span", {
|
|
268
|
+
className: cn("hidden min-w-0 flex-1 truncate text-sm text-muted-foreground transition-colors group-hover:text-foreground sm:inline", descriptionMono && "font-mono"),
|
|
269
|
+
children: description
|
|
270
|
+
}) : null,
|
|
271
|
+
/* @__PURE__ */ jsxs("span", {
|
|
272
|
+
className: "ml-auto flex shrink-0 items-center gap-1.5",
|
|
273
|
+
children: [!isRunning && durationMs != null ? /* @__PURE__ */ jsx("span", {
|
|
274
|
+
"data-run-row-duration": "",
|
|
275
|
+
className: "font-mono text-[10px] tabular-nums text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100",
|
|
276
|
+
children: formatDuration(durationMs)
|
|
277
|
+
}) : null, /* @__PURE__ */ jsx(RunRowStatusDot, { status })]
|
|
278
|
+
})
|
|
279
|
+
]
|
|
280
|
+
})
|
|
281
|
+
}),
|
|
282
|
+
collapsedError && !open ? /* @__PURE__ */ jsx("div", {
|
|
283
|
+
className: cn("pb-1.5 pr-2 text-xs leading-snug text-[var(--surface-danger-text)]", ERROR_INDENT),
|
|
284
|
+
children: collapsedError
|
|
285
|
+
}) : null,
|
|
286
|
+
expandable ? /* @__PURE__ */ jsx(Collapsible.Content, {
|
|
287
|
+
className: "overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp",
|
|
288
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
289
|
+
className: cn("border-t border-border", contentClassName),
|
|
290
|
+
children
|
|
291
|
+
})
|
|
292
|
+
}) : null
|
|
293
|
+
]
|
|
294
|
+
}), actions ? /* @__PURE__ */ jsx("div", {
|
|
295
|
+
className: "flex shrink-0 flex-wrap items-center justify-end gap-1.5 pt-1",
|
|
296
|
+
onClick: (event) => event.stopPropagation(),
|
|
297
|
+
children: actions
|
|
298
|
+
}) : null]
|
|
299
|
+
})
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
//#endregion
|
|
303
|
+
//#region src/run/inline-tool-item.tsx
|
|
304
|
+
/** Map tool category to a lucide-react icon component. */
|
|
305
|
+
const TOOL_CATEGORY_ICON_MAP = {
|
|
306
|
+
command: Terminal,
|
|
307
|
+
write: FileEdit,
|
|
308
|
+
read: FileSearch,
|
|
309
|
+
search: Search,
|
|
310
|
+
edit: PencilLine,
|
|
311
|
+
task: Bot,
|
|
312
|
+
web: Globe,
|
|
313
|
+
todo: ClipboardList,
|
|
314
|
+
other: Settings
|
|
315
|
+
};
|
|
316
|
+
/** Map the tool part status onto the shared row status vocabulary. */
|
|
317
|
+
function toRowStatus(status) {
|
|
318
|
+
if (status === "pending" || status === "running") return "running";
|
|
319
|
+
if (status === "error") return "error";
|
|
320
|
+
return "success";
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Compact single-line tool call display: a category glyph, the tool verb, and
|
|
324
|
+
* the path or command it acted on. While the call runs the verb shimmers;
|
|
325
|
+
* once it completes the row goes quiet (duration on hover, a red dot only on
|
|
326
|
+
* error). Expands on click to show ExpandedToolDetail. Rendered through the
|
|
327
|
+
* shared RunRowShell so it stays consistent with the reasoning row.
|
|
328
|
+
*/
|
|
329
|
+
const InlineToolItem = memo(({ part, renderToolDetail, groupPosition = "single", className, contentClassName, actions, title: titleOverride, description: descriptionOverride }) => {
|
|
330
|
+
const meta = getToolDisplayMetadata(part);
|
|
331
|
+
const title = titleOverride ?? meta.title;
|
|
332
|
+
const description = descriptionOverride ?? meta.description;
|
|
333
|
+
const errorText = getToolErrorText(part);
|
|
334
|
+
const startTime = part.state.time?.start;
|
|
335
|
+
const endTime = part.state.time?.end;
|
|
336
|
+
const durationMs = startTime != null && endTime != null ? endTime - startTime : void 0;
|
|
337
|
+
const category = getToolCategory(part.tool);
|
|
338
|
+
const DefaultIcon = TOOL_CATEGORY_ICON_MAP[category] ?? Settings;
|
|
339
|
+
const status = toRowStatus(part.state.status);
|
|
340
|
+
return /* @__PURE__ */ jsx(RunRowShell, {
|
|
341
|
+
icon: /* @__PURE__ */ jsx(DefaultIcon, { className: "h-3.5 w-3.5" }),
|
|
342
|
+
title: status === "running" ? /* @__PURE__ */ jsx(TextShimmer, { children: title }) : title,
|
|
343
|
+
description,
|
|
344
|
+
descriptionMono: true,
|
|
345
|
+
status,
|
|
346
|
+
durationMs,
|
|
347
|
+
groupPosition,
|
|
348
|
+
collapsedError: errorText ?? void 0,
|
|
349
|
+
actions,
|
|
350
|
+
className,
|
|
351
|
+
contentClassName: cn("p-2", contentClassName),
|
|
352
|
+
children: renderToolDetail?.(part) ?? /* @__PURE__ */ jsx(ExpandedToolDetail, { part })
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
InlineToolItem.displayName = "InlineToolItem";
|
|
356
|
+
//#endregion
|
|
357
|
+
//#region src/run/tool-call-step.tsx
|
|
358
|
+
const EXT_LANGUAGE = {
|
|
359
|
+
ts: "typescript",
|
|
360
|
+
tsx: "typescript",
|
|
361
|
+
js: "javascript",
|
|
362
|
+
jsx: "javascript",
|
|
363
|
+
mjs: "javascript",
|
|
364
|
+
cjs: "javascript",
|
|
365
|
+
css: "css",
|
|
366
|
+
scss: "scss",
|
|
367
|
+
json: "json",
|
|
368
|
+
jsonc: "json",
|
|
369
|
+
md: "markdown",
|
|
370
|
+
mdx: "markdown",
|
|
371
|
+
py: "python",
|
|
372
|
+
sh: "bash",
|
|
373
|
+
bash: "bash",
|
|
374
|
+
zsh: "bash",
|
|
375
|
+
html: "html",
|
|
376
|
+
htm: "html",
|
|
377
|
+
yaml: "yaml",
|
|
378
|
+
yml: "yaml",
|
|
379
|
+
toml: "toml",
|
|
380
|
+
rs: "rust",
|
|
381
|
+
go: "go",
|
|
382
|
+
sql: "sql",
|
|
383
|
+
xml: "xml"
|
|
384
|
+
};
|
|
385
|
+
function inferLanguage(detail, language) {
|
|
386
|
+
if (language) return language;
|
|
387
|
+
if (!detail) return void 0;
|
|
388
|
+
const ext = detail.split(".").pop()?.toLowerCase();
|
|
389
|
+
return ext ? EXT_LANGUAGE[ext] : void 0;
|
|
390
|
+
}
|
|
391
|
+
const STATUS_MAP = {
|
|
392
|
+
running: "running",
|
|
393
|
+
success: "completed",
|
|
394
|
+
error: "error"
|
|
395
|
+
};
|
|
396
|
+
function ToolCallStep({ type, label, status, detail, output, language, duration, className, actions, part }) {
|
|
397
|
+
const resolvedPart = part ?? {
|
|
398
|
+
type: "tool",
|
|
399
|
+
id: `${type}:${label}`,
|
|
400
|
+
tool: type,
|
|
401
|
+
state: {
|
|
402
|
+
status: STATUS_MAP[status],
|
|
403
|
+
input: detail ? { detail } : void 0,
|
|
404
|
+
output,
|
|
405
|
+
time: duration != null ? {
|
|
406
|
+
start: 0,
|
|
407
|
+
end: duration
|
|
408
|
+
} : void 0
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
const lang = inferLanguage(detail, language);
|
|
412
|
+
return /* @__PURE__ */ jsx(InlineToolItem, {
|
|
413
|
+
part: resolvedPart,
|
|
414
|
+
title: label,
|
|
415
|
+
description: detail,
|
|
416
|
+
className,
|
|
417
|
+
actions,
|
|
418
|
+
renderToolDetail: part ? void 0 : output ? () => /* @__PURE__ */ jsx(CodeBlock, {
|
|
419
|
+
code: output,
|
|
420
|
+
language: lang,
|
|
421
|
+
className: "max-h-72 overflow-auto text-xs"
|
|
422
|
+
}) : () => null
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
function ToolCallGroup({ title, children, className }) {
|
|
426
|
+
return /* @__PURE__ */ jsx("div", {
|
|
427
|
+
role: "group",
|
|
428
|
+
"aria-label": title,
|
|
429
|
+
className: cn("flex flex-col gap-1", className),
|
|
430
|
+
children
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
//#endregion
|
|
434
|
+
export { RunRowStatusDot as a, RunRowShell as i, ToolCallStep as n, ExpandedToolDetail as o, InlineToolItem as r, ExpandableContent as s, ToolCallGroup as t };
|