@tangle-network/ui 11.0.0 → 11.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 +30 -0
- package/dist/{artifact-pane-DvJyPWV4.d.ts → artifact-pane-DpuWcAiF.d.ts} +10 -1
- package/dist/chat.d.ts +8 -2
- package/dist/chat.js +5 -5
- package/dist/{chunk-52Y3FMFI.js → chunk-3M7BPSSW.js} +1 -1
- package/dist/chunk-4ORVXSMU.js +507 -0
- package/dist/{chunk-LELGOLFV.js → chunk-GGDYWMFF.js} +15 -7
- package/dist/{chunk-CCM2KRQH.js → chunk-HW4ROISY.js} +1 -1
- package/dist/{chunk-KBOD47AW.js → chunk-J3YZIQNI.js} +2 -2
- package/dist/{chunk-CSAIKY36.js → chunk-LTEKI7YJ.js} +12 -7
- package/dist/{chunk-KHO7DYXH.js → chunk-OTZWQJ5W.js} +107 -72
- package/dist/{chunk-FJBTCTZM.js → chunk-P5F43A65.js} +1 -1
- package/dist/{chunk-SZ44QDA6.js → chunk-RADUPP44.js} +12 -5
- package/dist/{chunk-HHYUPAOJ.js → chunk-SRAKCVPO.js} +49 -81
- package/dist/{document-editor-pane-DyDEX_Zm.d.ts → document-editor-pane-C3cYEDWZ.d.ts} +2 -2
- package/dist/{document-editor-pane-WCTA3ZOE.js → document-editor-pane-OQNGM4RJ.js} +3 -3
- package/dist/editor.d.ts +3 -3
- package/dist/editor.js +3 -3
- package/dist/files.d.ts +5 -3
- package/dist/files.js +3 -3
- package/dist/hooks.js +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +9 -9
- package/dist/markdown.js +1 -1
- package/dist/openui.js +2 -2
- package/dist/primitives.d.ts +1 -1
- package/dist/primitives.js +1 -1
- package/dist/run.d.ts +4 -3
- package/dist/run.js +5 -5
- package/dist/sdk-hooks.js +4 -4
- package/package.json +1 -1
- package/src/chat/agent-timeline.stories.tsx +11 -0
- package/src/chat/agent-timeline.test.tsx +34 -0
- package/src/chat/agent-timeline.tsx +65 -12
- package/src/chat/chat-container.tsx +5 -0
- package/src/editor/document-editor-pane.stories.tsx +74 -0
- package/src/editor/document-editor-pane.tsx +10 -3
- package/src/files/file-artifact-pane.tsx +14 -2
- package/src/files/file-preview.stories.tsx +22 -1
- package/src/files/file-preview.tsx +2 -2
- package/src/markdown/markdown.stories.tsx +55 -1
- package/src/markdown/markdown.test.tsx +23 -0
- package/src/markdown/markdown.tsx +1 -1
- package/src/primitives/artifact-pane.tsx +52 -26
- package/src/run/expandable-content.test.tsx +52 -0
- package/src/run/expandable-content.tsx +73 -0
- package/src/run/expanded-tool-detail.tsx +17 -12
- package/src/run/inline-thinking-item.stories.tsx +30 -1
- package/src/run/inline-thinking-item.tsx +34 -70
- package/src/run/inline-tool-item.tsx +30 -116
- package/src/run/run-row-shell.test.tsx +38 -0
- package/src/run/run-row-shell.tsx +191 -0
- package/dist/chunk-INMWNFAS.js +0 -369
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @tangle-network/ui
|
|
2
2
|
|
|
3
|
+
## 11.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- ac4eaf4: feat(files): host-aligned artifact surface props
|
|
8
|
+
|
|
9
|
+
- `ArtifactPane`: `headerClassName` + `hideTitleBlock` (header row collapses when empty).
|
|
10
|
+
- `FileArtifactPane`: threads both through all render paths; `headerActions` is `undefined` (not an empty fragment) when there are no actions.
|
|
11
|
+
- `DocumentEditorPane`: `previewClassName` now governs the whole preview box (gutter/border/surface/padding), enabling a full-bleed document body.
|
|
12
|
+
- `FilePreview`: text previews sit on `bg-card` for a white surface in light theme.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- c5dfc7d: Use tokenized Tangle prose styling for markdown previews so light themes stay readable.
|
|
17
|
+
|
|
18
|
+
## 11.1.0
|
|
19
|
+
|
|
20
|
+
### Minor Changes
|
|
21
|
+
|
|
22
|
+
- ea6f23e: Unify the agent reasoning and tool rows onto one shared row shell: both keep a
|
|
23
|
+
consistent semantic lead icon with a small trailing status dot/spinner (status
|
|
24
|
+
no longer hijacks the icon), on a calm neutral badge that is uniform across
|
|
25
|
+
reasoning and tool rows. Expanded and open rows read as the same surface as
|
|
26
|
+
their collapsed siblings (no background elevation), the reasoning body inherits
|
|
27
|
+
the card surface and stays readable in dark mode, and the timeline spine dot is
|
|
28
|
+
centered on card rows. Add a per-row content clamp with "Show more/less" for
|
|
29
|
+
long reasoning text and tool output, and an opt-in `collapseAfter` on
|
|
30
|
+
`AgentTimeline` (threaded as `collapseTimelineAfter` on `ChatContainer`) that
|
|
31
|
+
collapses the timeline to the first N steps behind a "Show N more steps" toggle.
|
|
32
|
+
|
|
3
33
|
## 11.0.0
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
|
@@ -14,11 +14,20 @@ interface ArtifactPaneProps {
|
|
|
14
14
|
children?: ReactNode;
|
|
15
15
|
className?: string;
|
|
16
16
|
contentClassName?: string;
|
|
17
|
+
/** Extra classes for the header band (e.g. to align its surface with the host chrome). */
|
|
18
|
+
headerClassName?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Suppress the eyebrow/title/subtitle/meta block. Use when the host already
|
|
21
|
+
* shows the artifact's identity elsewhere (e.g. a surrounding path row), so the
|
|
22
|
+
* pane keeps only its tabs, toolbar, and header actions. The whole header row
|
|
23
|
+
* collapses when nothing else would render in it.
|
|
24
|
+
*/
|
|
25
|
+
hideTitleBlock?: boolean;
|
|
17
26
|
}
|
|
18
27
|
/**
|
|
19
28
|
* ArtifactPane — shared frame for files, previews, documents, inspectors, and
|
|
20
29
|
* other artifact-like surfaces inside sandbox applications.
|
|
21
30
|
*/
|
|
22
|
-
declare function ArtifactPane({ eyebrow, title, subtitle, meta, headerActions, tabs, toolbar, footer, emptyState, children, className, contentClassName, }: ArtifactPaneProps): react_jsx_runtime.JSX.Element;
|
|
31
|
+
declare function ArtifactPane({ eyebrow, title, subtitle, meta, headerActions, tabs, toolbar, footer, emptyState, children, className, contentClassName, headerClassName, hideTitleBlock, }: ArtifactPaneProps): react_jsx_runtime.JSX.Element;
|
|
23
32
|
|
|
24
33
|
export { ArtifactPane as A, type ArtifactPaneProps as a };
|
package/dist/chat.d.ts
CHANGED
|
@@ -42,12 +42,15 @@ interface ChatContainerProps {
|
|
|
42
42
|
/** Optional actions rendered beside individual tool items in the `timeline`
|
|
43
43
|
* presentation, which has no run/message grouping (hence part-only). */
|
|
44
44
|
renderTimelineToolActions?: (part: ToolPart) => ReactNode;
|
|
45
|
+
/** In the `timeline` presentation, collapse to the first N spine rows behind
|
|
46
|
+
* a "Show N more steps" toggle. Omit to always show every row. */
|
|
47
|
+
collapseTimelineAfter?: number;
|
|
45
48
|
}
|
|
46
49
|
/**
|
|
47
50
|
* Chat transcript container: message list + auto-scroll.
|
|
48
51
|
* Orchestrates useRunGroups, useRunCollapseState, and useAutoScroll.
|
|
49
52
|
*/
|
|
50
|
-
declare const ChatContainer: React.MemoExoticComponent<({ messages, partMap, isStreaming, branding, className, renderToolDetail, presentation, onOpenUIAction, enableOpenUI, renderRunActions, renderUserMessageActions, renderToolActions, renderTimelineToolActions, }: ChatContainerProps) => react_jsx_runtime.JSX.Element>;
|
|
53
|
+
declare const ChatContainer: React.MemoExoticComponent<({ messages, partMap, isStreaming, branding, className, renderToolDetail, presentation, onOpenUIAction, enableOpenUI, renderRunActions, renderUserMessageActions, renderToolActions, renderTimelineToolActions, collapseTimelineAfter, }: ChatContainerProps) => react_jsx_runtime.JSX.Element>;
|
|
51
54
|
|
|
52
55
|
interface MessageListProps {
|
|
53
56
|
groups: GroupedMessage[];
|
|
@@ -174,12 +177,15 @@ interface AgentTimelineProps {
|
|
|
174
177
|
/** Optional actions rendered beside each tool item (e.g. "open in artifacts").
|
|
175
178
|
* Receives the source tool part carried on the item. */
|
|
176
179
|
renderToolActions?: (part: ToolPart) => ReactNode;
|
|
180
|
+
/** When set, collapse the timeline to the first N spine rows behind a
|
|
181
|
+
* "Show N more steps" toggle. Omit to always show every row. */
|
|
182
|
+
collapseAfter?: number;
|
|
177
183
|
}
|
|
178
184
|
/**
|
|
179
185
|
* AgentTimeline — unified mixed-content timeline for agent-backed sandbox
|
|
180
186
|
* sessions. Renders messages, tool steps, status cards, and artifact handoffs in
|
|
181
187
|
* a single execution narrative.
|
|
182
188
|
*/
|
|
183
|
-
declare function AgentTimeline({ items, isThinking, emptyState, className, renderToolActions, }: AgentTimelineProps): react_jsx_runtime.JSX.Element | null;
|
|
189
|
+
declare function AgentTimeline({ items, isThinking, emptyState, className, renderToolActions, collapseAfter, }: AgentTimelineProps): react_jsx_runtime.JSX.Element | null;
|
|
184
190
|
|
|
185
191
|
export { AgentTimeline, type AgentTimelineArtifactItem, type AgentTimelineCustomItem, type AgentTimelineItem, type AgentTimelineMessageItem, type AgentTimelineProps, type AgentTimelineStatusItem, type AgentTimelineTone, type AgentTimelineToolGroupItem, type AgentTimelineToolItem, ChatContainer, type ChatContainerProps, ChatMessage, type ChatMessageProps, MessageList, type MessageListProps, type MessageRole, ThinkingIndicator, type ThinkingIndicatorProps, UserMessage, type UserMessageProps };
|
package/dist/chat.js
CHANGED
|
@@ -5,17 +5,17 @@ import {
|
|
|
5
5
|
MessageList,
|
|
6
6
|
ThinkingIndicator,
|
|
7
7
|
UserMessage
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-OTZWQJ5W.js";
|
|
9
9
|
import "./chunk-AZWDI2JG.js";
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-SRAKCVPO.js";
|
|
11
|
+
import "./chunk-4ORVXSMU.js";
|
|
12
12
|
import "./chunk-ULDNFLIM.js";
|
|
13
13
|
import "./chunk-AAUNOHVL.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-3M7BPSSW.js";
|
|
15
15
|
import "./chunk-GYPQXTJU.js";
|
|
16
16
|
import "./chunk-MKTSMWVD.js";
|
|
17
17
|
import "./chunk-ZRVH3WCA.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-P5F43A65.js";
|
|
19
19
|
import "./chunk-WUQDUBJG.js";
|
|
20
20
|
import "./chunk-RQHJBTEU.js";
|
|
21
21
|
export {
|
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatDuration,
|
|
3
|
+
getToolCategory,
|
|
4
|
+
getToolDisplayMetadata,
|
|
5
|
+
getToolErrorText
|
|
6
|
+
} from "./chunk-ULDNFLIM.js";
|
|
7
|
+
import {
|
|
8
|
+
CommandPreview,
|
|
9
|
+
DiffPreview,
|
|
10
|
+
GlobResultsPreview,
|
|
11
|
+
GrepResultsPreview,
|
|
12
|
+
QuestionPreview,
|
|
13
|
+
WebSearchPreview,
|
|
14
|
+
WriteFilePreview
|
|
15
|
+
} from "./chunk-AAUNOHVL.js";
|
|
16
|
+
import {
|
|
17
|
+
CodeBlock
|
|
18
|
+
} from "./chunk-WUQDUBJG.js";
|
|
19
|
+
import {
|
|
20
|
+
cn
|
|
21
|
+
} from "./chunk-RQHJBTEU.js";
|
|
22
|
+
|
|
23
|
+
// src/run/expanded-tool-detail.tsx
|
|
24
|
+
import { memo } from "react";
|
|
25
|
+
import {
|
|
26
|
+
ArrowRight,
|
|
27
|
+
ArrowLeft,
|
|
28
|
+
AlertCircle,
|
|
29
|
+
Loader2,
|
|
30
|
+
FileText
|
|
31
|
+
} from "lucide-react";
|
|
32
|
+
|
|
33
|
+
// src/run/expandable-content.tsx
|
|
34
|
+
import { useEffect, useRef, useState } from "react";
|
|
35
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
36
|
+
function ExpandableContent({
|
|
37
|
+
children,
|
|
38
|
+
collapsedMaxPx = 180,
|
|
39
|
+
fadeClassName = "from-muted",
|
|
40
|
+
className
|
|
41
|
+
}) {
|
|
42
|
+
const [expanded, setExpanded] = useState(false);
|
|
43
|
+
const [overflowing, setOverflowing] = useState(false);
|
|
44
|
+
const contentRef = useRef(null);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
const el = contentRef.current;
|
|
47
|
+
if (!el) return;
|
|
48
|
+
const measure = () => setOverflowing(el.scrollHeight > collapsedMaxPx + 4);
|
|
49
|
+
measure();
|
|
50
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
51
|
+
const observer = new ResizeObserver(measure);
|
|
52
|
+
observer.observe(el);
|
|
53
|
+
return () => observer.disconnect();
|
|
54
|
+
}, [collapsedMaxPx]);
|
|
55
|
+
const clamped = overflowing && !expanded;
|
|
56
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
57
|
+
/* @__PURE__ */ jsxs(
|
|
58
|
+
"div",
|
|
59
|
+
{
|
|
60
|
+
ref: contentRef,
|
|
61
|
+
className: "relative overflow-hidden",
|
|
62
|
+
style: clamped ? { maxHeight: collapsedMaxPx } : void 0,
|
|
63
|
+
children: [
|
|
64
|
+
children,
|
|
65
|
+
clamped ? /* @__PURE__ */ jsx(
|
|
66
|
+
"div",
|
|
67
|
+
{
|
|
68
|
+
className: cn(
|
|
69
|
+
"pointer-events-none absolute inset-x-0 bottom-0 h-10 bg-gradient-to-t to-transparent",
|
|
70
|
+
fadeClassName
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
) : null
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
),
|
|
77
|
+
overflowing ? /* @__PURE__ */ jsx(
|
|
78
|
+
"button",
|
|
79
|
+
{
|
|
80
|
+
type: "button",
|
|
81
|
+
onClick: () => setExpanded((value) => !value),
|
|
82
|
+
className: "mt-1 text-[11px] font-medium text-muted-foreground transition-colors hover:text-foreground",
|
|
83
|
+
children: expanded ? "Show less" : "Show more"
|
|
84
|
+
}
|
|
85
|
+
) : null
|
|
86
|
+
] });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/run/expanded-tool-detail.tsx
|
|
90
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
91
|
+
var EXT_LANG = {
|
|
92
|
+
ts: "typescript",
|
|
93
|
+
tsx: "tsx",
|
|
94
|
+
js: "javascript",
|
|
95
|
+
jsx: "jsx",
|
|
96
|
+
rs: "rust",
|
|
97
|
+
py: "python",
|
|
98
|
+
go: "go",
|
|
99
|
+
rb: "ruby",
|
|
100
|
+
json: "json",
|
|
101
|
+
yaml: "yaml",
|
|
102
|
+
yml: "yaml",
|
|
103
|
+
toml: "toml",
|
|
104
|
+
md: "markdown",
|
|
105
|
+
css: "css",
|
|
106
|
+
scss: "scss",
|
|
107
|
+
html: "html",
|
|
108
|
+
sh: "bash",
|
|
109
|
+
bash: "bash",
|
|
110
|
+
zsh: "bash",
|
|
111
|
+
sql: "sql",
|
|
112
|
+
sol: "solidity",
|
|
113
|
+
proto: "protobuf"
|
|
114
|
+
};
|
|
115
|
+
function langFromPath(path) {
|
|
116
|
+
if (!path) return void 0;
|
|
117
|
+
const ext = path.split(".").pop()?.toLowerCase();
|
|
118
|
+
return ext ? EXT_LANG[ext] : void 0;
|
|
119
|
+
}
|
|
120
|
+
function formatOutput(value) {
|
|
121
|
+
if (value == null) return "";
|
|
122
|
+
if (typeof value === "string") return value;
|
|
123
|
+
try {
|
|
124
|
+
return JSON.stringify(value, null, 2);
|
|
125
|
+
} catch {
|
|
126
|
+
return String(value);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
var ExpandedToolDetail = memo(({ part }) => {
|
|
130
|
+
const meta = getToolDisplayMetadata(part);
|
|
131
|
+
const { status, input, output, error } = part.state;
|
|
132
|
+
if (meta.displayVariant === "command") {
|
|
133
|
+
return /* @__PURE__ */ jsx2(CommandPreview, { part });
|
|
134
|
+
}
|
|
135
|
+
if (meta.displayVariant === "write-file") {
|
|
136
|
+
return /* @__PURE__ */ jsx2(WriteFilePreview, { part });
|
|
137
|
+
}
|
|
138
|
+
if (meta.displayVariant === "grep") {
|
|
139
|
+
return /* @__PURE__ */ jsx2(GrepResultsPreview, { part });
|
|
140
|
+
}
|
|
141
|
+
if (meta.displayVariant === "glob") {
|
|
142
|
+
return /* @__PURE__ */ jsx2(GlobResultsPreview, { part });
|
|
143
|
+
}
|
|
144
|
+
if (meta.displayVariant === "web-search") {
|
|
145
|
+
return /* @__PURE__ */ jsx2(WebSearchPreview, { part });
|
|
146
|
+
}
|
|
147
|
+
if (meta.displayVariant === "question") {
|
|
148
|
+
return /* @__PURE__ */ jsx2(QuestionPreview, { part });
|
|
149
|
+
}
|
|
150
|
+
if (meta.displayVariant === "diff") {
|
|
151
|
+
return /* @__PURE__ */ jsx2(DiffPreview, { part });
|
|
152
|
+
}
|
|
153
|
+
if (meta.displayVariant === "read-file") {
|
|
154
|
+
return /* @__PURE__ */ jsxs2("div", { className: "overflow-hidden rounded-[var(--radius-lg)] border border-border bg-card shadow-[var(--shadow-card)]", children: [
|
|
155
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2.5 border-b border-border bg-card px-3 py-2", children: [
|
|
156
|
+
/* @__PURE__ */ jsx2("div", { 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", children: /* @__PURE__ */ jsx2(FileText, { className: "h-3.5 w-3.5" }) }),
|
|
157
|
+
/* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex items-center gap-2", children: [
|
|
158
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs font-semibold text-foreground", children: "Read file" }),
|
|
159
|
+
meta.targetPath ? /* @__PURE__ */ jsx2("span", { className: "truncate text-xs font-mono text-muted-foreground", children: meta.targetPath }) : null
|
|
160
|
+
] })
|
|
161
|
+
] }),
|
|
162
|
+
/* @__PURE__ */ jsxs2("div", { className: "space-y-2 px-3 py-2.5", children: [
|
|
163
|
+
typeof output === "string" ? /* @__PURE__ */ jsx2(CodeBlock, { code: output, language: langFromPath(meta.targetPath) ?? "text", className: "rounded-[var(--radius-md)]" }) : /* @__PURE__ */ jsx2("div", { className: "rounded-[var(--radius-md)] border border-dashed border-border bg-muted px-3 py-4 text-sm text-muted-foreground", children: "No readable file content was returned." }),
|
|
164
|
+
error ? /* @__PURE__ */ jsx2("div", { 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)]", children: error }) : null
|
|
165
|
+
] })
|
|
166
|
+
] });
|
|
167
|
+
}
|
|
168
|
+
const inputStr = formatOutput(input);
|
|
169
|
+
const outputStr = formatOutput(output);
|
|
170
|
+
return /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
|
|
171
|
+
inputStr && /* @__PURE__ */ jsxs2("div", { className: "overflow-hidden rounded-[var(--radius-lg)] border border-border bg-card", children: [
|
|
172
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 border-b border-border bg-background px-3 py-2", children: [
|
|
173
|
+
/* @__PURE__ */ jsx2(ArrowRight, { className: "h-3 w-3 text-primary" }),
|
|
174
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs font-medium uppercase tracking-[0.08em] text-muted-foreground", children: "Input" })
|
|
175
|
+
] }),
|
|
176
|
+
/* @__PURE__ */ jsx2(CodeBlock, { code: inputStr, language: "json", className: "rounded-none border-0" })
|
|
177
|
+
] }),
|
|
178
|
+
status === "completed" && outputStr && /* @__PURE__ */ jsxs2("div", { className: "overflow-hidden rounded-[var(--radius-lg)] border border-border bg-card", children: [
|
|
179
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 border-b border-border bg-background px-3 py-2", children: [
|
|
180
|
+
/* @__PURE__ */ jsx2(ArrowLeft, { className: "h-3 w-3 text-primary" }),
|
|
181
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs font-medium uppercase tracking-[0.08em] text-muted-foreground", children: "Output" })
|
|
182
|
+
] }),
|
|
183
|
+
/* @__PURE__ */ jsx2(ExpandableContent, { fadeClassName: "from-card", children: /* @__PURE__ */ jsx2(
|
|
184
|
+
CodeBlock,
|
|
185
|
+
{
|
|
186
|
+
code: outputStr.length > 2e3 ? outputStr.slice(0, 2e3) + "\n...(truncated)" : outputStr,
|
|
187
|
+
language: "json",
|
|
188
|
+
className: "rounded-none border-0"
|
|
189
|
+
}
|
|
190
|
+
) })
|
|
191
|
+
] }),
|
|
192
|
+
error && /* @__PURE__ */ jsxs2("div", { className: "overflow-hidden rounded-[var(--radius-lg)] border border-[var(--surface-danger-border)]", children: [
|
|
193
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 border-b border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] px-3 py-2", children: [
|
|
194
|
+
/* @__PURE__ */ jsx2(AlertCircle, { className: "h-3 w-3 text-[var(--surface-danger-text)]" }),
|
|
195
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs font-medium uppercase tracking-[0.08em] text-[var(--surface-danger-text)]", children: "Error" })
|
|
196
|
+
] }),
|
|
197
|
+
/* @__PURE__ */ jsx2(ExpandableContent, { fadeClassName: "from-[var(--surface-danger-bg)]", children: /* @__PURE__ */ jsx2("pre", { className: "bg-[var(--surface-danger-bg)] p-3 text-xs font-mono whitespace-pre-wrap break-all text-[var(--surface-danger-text)]", children: error }) })
|
|
198
|
+
] }),
|
|
199
|
+
(status === "pending" || status === "running") && /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 rounded-[var(--radius-md)] border border-border bg-muted px-3 py-3 text-xs text-muted-foreground", children: [
|
|
200
|
+
/* @__PURE__ */ jsx2(Loader2, { className: cn("h-3 w-3 animate-spin text-primary") }),
|
|
201
|
+
"Running\u2026"
|
|
202
|
+
] })
|
|
203
|
+
] });
|
|
204
|
+
});
|
|
205
|
+
ExpandedToolDetail.displayName = "ExpandedToolDetail";
|
|
206
|
+
|
|
207
|
+
// src/run/run-item-primitives.tsx
|
|
208
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
209
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
210
|
+
function LiveDuration({ startTime }) {
|
|
211
|
+
const [elapsed, setElapsed] = useState2(Date.now() - startTime);
|
|
212
|
+
useEffect2(() => {
|
|
213
|
+
const id = setInterval(() => setElapsed(Date.now() - startTime), 100);
|
|
214
|
+
return () => clearInterval(id);
|
|
215
|
+
}, [startTime]);
|
|
216
|
+
return /* @__PURE__ */ jsx3("span", { className: "text-xs font-mono text-neutral-400 dark:text-neutral-500 tabular-nums", children: formatDuration(elapsed) });
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// src/run/inline-tool-item.tsx
|
|
220
|
+
import { memo as memo2 } from "react";
|
|
221
|
+
import {
|
|
222
|
+
Terminal,
|
|
223
|
+
FileEdit,
|
|
224
|
+
FileSearch,
|
|
225
|
+
Search,
|
|
226
|
+
PencilLine,
|
|
227
|
+
Bot,
|
|
228
|
+
Globe,
|
|
229
|
+
ClipboardList,
|
|
230
|
+
Settings
|
|
231
|
+
} from "lucide-react";
|
|
232
|
+
|
|
233
|
+
// src/run/run-row-shell.tsx
|
|
234
|
+
import { useState as useState3 } from "react";
|
|
235
|
+
import * as Collapsible from "@radix-ui/react-collapsible";
|
|
236
|
+
import { Loader2 as Loader22, ChevronRight } from "lucide-react";
|
|
237
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
238
|
+
function RunRowStatusDot({ status }) {
|
|
239
|
+
if (status === "running") {
|
|
240
|
+
return /* @__PURE__ */ jsx4(Loader22, { className: "h-3 w-3 shrink-0 animate-spin text-[var(--accent-text)]" });
|
|
241
|
+
}
|
|
242
|
+
if (status === "success") {
|
|
243
|
+
return /* @__PURE__ */ jsx4("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-[var(--surface-success-text)]" });
|
|
244
|
+
}
|
|
245
|
+
if (status === "error") {
|
|
246
|
+
return /* @__PURE__ */ jsx4("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-[var(--surface-danger-text)]" });
|
|
247
|
+
}
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
var SHAPE_CLASS = {
|
|
251
|
+
single: "rounded-[var(--radius-lg)]",
|
|
252
|
+
first: "rounded-t-[var(--radius-lg)] rounded-b-[var(--radius-sm)]",
|
|
253
|
+
middle: "rounded-[var(--radius-sm)]",
|
|
254
|
+
last: "rounded-t-[var(--radius-sm)] rounded-b-[var(--radius-lg)]"
|
|
255
|
+
};
|
|
256
|
+
function RunRowShell({
|
|
257
|
+
icon,
|
|
258
|
+
title,
|
|
259
|
+
description,
|
|
260
|
+
descriptionMono = false,
|
|
261
|
+
status = "idle",
|
|
262
|
+
startTime,
|
|
263
|
+
durationMs,
|
|
264
|
+
groupPosition = "single",
|
|
265
|
+
collapsedError,
|
|
266
|
+
actions,
|
|
267
|
+
open: openProp,
|
|
268
|
+
onOpenChange,
|
|
269
|
+
defaultOpen = false,
|
|
270
|
+
className,
|
|
271
|
+
contentClassName,
|
|
272
|
+
children
|
|
273
|
+
}) {
|
|
274
|
+
const [openState, setOpenState] = useState3(defaultOpen);
|
|
275
|
+
const isControlled = openProp !== void 0;
|
|
276
|
+
const open = isControlled ? openProp : openState;
|
|
277
|
+
const setOpen = (next) => {
|
|
278
|
+
if (!isControlled) setOpenState(next);
|
|
279
|
+
onOpenChange?.(next);
|
|
280
|
+
};
|
|
281
|
+
const isRunning = status === "running";
|
|
282
|
+
const expandable = children != null;
|
|
283
|
+
return /* @__PURE__ */ jsx4(Collapsible.Root, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs3("div", { className: "flex items-start gap-2", children: [
|
|
284
|
+
/* @__PURE__ */ jsxs3(
|
|
285
|
+
"div",
|
|
286
|
+
{
|
|
287
|
+
className: cn(
|
|
288
|
+
"min-w-0 flex-1 overflow-hidden border transition-colors",
|
|
289
|
+
"border-[var(--border-subtle)] bg-[var(--md3-surface-container)]",
|
|
290
|
+
expandable && "hover:border-border",
|
|
291
|
+
open && "border-border",
|
|
292
|
+
SHAPE_CLASS[groupPosition],
|
|
293
|
+
className
|
|
294
|
+
),
|
|
295
|
+
children: [
|
|
296
|
+
/* @__PURE__ */ jsx4(Collapsible.Trigger, { asChild: true, disabled: !expandable, children: /* @__PURE__ */ jsxs3(
|
|
297
|
+
"button",
|
|
298
|
+
{
|
|
299
|
+
type: "button",
|
|
300
|
+
className: cn(
|
|
301
|
+
"flex w-full items-center gap-2.5 px-3 py-2 text-left",
|
|
302
|
+
expandable ? "cursor-pointer" : "cursor-default"
|
|
303
|
+
),
|
|
304
|
+
children: [
|
|
305
|
+
/* @__PURE__ */ jsx4("span", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border border-border bg-muted text-muted-foreground", children: icon }),
|
|
306
|
+
/* @__PURE__ */ jsx4("span", { className: "shrink-0 whitespace-nowrap text-xs font-medium text-foreground", children: title }),
|
|
307
|
+
description ? /* @__PURE__ */ jsx4(
|
|
308
|
+
"span",
|
|
309
|
+
{
|
|
310
|
+
className: cn(
|
|
311
|
+
"hidden min-w-0 flex-1 truncate text-xs text-muted-foreground sm:inline",
|
|
312
|
+
descriptionMono && "font-mono"
|
|
313
|
+
),
|
|
314
|
+
children: description
|
|
315
|
+
}
|
|
316
|
+
) : null,
|
|
317
|
+
/* @__PURE__ */ jsxs3("div", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [
|
|
318
|
+
isRunning && startTime != null ? /* @__PURE__ */ jsx4(LiveDuration, { startTime }) : durationMs != null ? /* @__PURE__ */ jsx4("span", { className: "text-[10px] font-mono tabular-nums text-muted-foreground", children: formatDuration(durationMs) }) : null,
|
|
319
|
+
/* @__PURE__ */ jsx4(RunRowStatusDot, { status }),
|
|
320
|
+
expandable ? /* @__PURE__ */ jsx4(
|
|
321
|
+
ChevronRight,
|
|
322
|
+
{
|
|
323
|
+
className: cn(
|
|
324
|
+
"h-3 w-3 shrink-0 text-muted-foreground transition-transform",
|
|
325
|
+
open && "rotate-90"
|
|
326
|
+
)
|
|
327
|
+
}
|
|
328
|
+
) : null
|
|
329
|
+
] })
|
|
330
|
+
]
|
|
331
|
+
}
|
|
332
|
+
) }),
|
|
333
|
+
collapsedError && !open ? /* @__PURE__ */ jsx4("div", { className: "border-t border-border px-3 py-2 text-xs text-[var(--surface-danger-text)]", children: collapsedError }) : null,
|
|
334
|
+
expandable ? /* @__PURE__ */ jsx4(Collapsible.Content, { className: "overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp", children: /* @__PURE__ */ jsx4("div", { className: cn("border-t border-border", contentClassName), children }) }) : null
|
|
335
|
+
]
|
|
336
|
+
}
|
|
337
|
+
),
|
|
338
|
+
actions ? /* @__PURE__ */ jsx4(
|
|
339
|
+
"div",
|
|
340
|
+
{
|
|
341
|
+
className: "flex shrink-0 flex-wrap items-center justify-end gap-1.5 pt-1",
|
|
342
|
+
onClick: (event) => event.stopPropagation(),
|
|
343
|
+
children: actions
|
|
344
|
+
}
|
|
345
|
+
) : null
|
|
346
|
+
] }) });
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// src/run/inline-tool-item.tsx
|
|
350
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
351
|
+
var TOOL_CATEGORY_ICON_MAP = {
|
|
352
|
+
command: Terminal,
|
|
353
|
+
write: FileEdit,
|
|
354
|
+
read: FileSearch,
|
|
355
|
+
search: Search,
|
|
356
|
+
edit: PencilLine,
|
|
357
|
+
task: Bot,
|
|
358
|
+
web: Globe,
|
|
359
|
+
todo: ClipboardList,
|
|
360
|
+
other: Settings
|
|
361
|
+
};
|
|
362
|
+
function toRowStatus(status) {
|
|
363
|
+
if (status === "pending" || status === "running") return "running";
|
|
364
|
+
if (status === "error") return "error";
|
|
365
|
+
return "success";
|
|
366
|
+
}
|
|
367
|
+
var InlineToolItem = memo2(
|
|
368
|
+
({
|
|
369
|
+
part,
|
|
370
|
+
renderToolDetail,
|
|
371
|
+
groupPosition = "single",
|
|
372
|
+
className,
|
|
373
|
+
contentClassName,
|
|
374
|
+
actions,
|
|
375
|
+
title: titleOverride,
|
|
376
|
+
description: descriptionOverride
|
|
377
|
+
}) => {
|
|
378
|
+
const meta = getToolDisplayMetadata(part);
|
|
379
|
+
const title = titleOverride ?? meta.title;
|
|
380
|
+
const description = descriptionOverride ?? meta.description;
|
|
381
|
+
const errorText = getToolErrorText(part);
|
|
382
|
+
const startTime = part.state.time?.start;
|
|
383
|
+
const endTime = part.state.time?.end;
|
|
384
|
+
const durationMs = startTime != null && endTime != null ? endTime - startTime : void 0;
|
|
385
|
+
const category = getToolCategory(part.tool);
|
|
386
|
+
const DefaultIcon = TOOL_CATEGORY_ICON_MAP[category] ?? Settings;
|
|
387
|
+
return /* @__PURE__ */ jsx5(
|
|
388
|
+
RunRowShell,
|
|
389
|
+
{
|
|
390
|
+
icon: /* @__PURE__ */ jsx5(DefaultIcon, { className: "h-3.5 w-3.5" }),
|
|
391
|
+
title,
|
|
392
|
+
description,
|
|
393
|
+
descriptionMono: true,
|
|
394
|
+
status: toRowStatus(part.state.status),
|
|
395
|
+
startTime,
|
|
396
|
+
durationMs,
|
|
397
|
+
groupPosition,
|
|
398
|
+
collapsedError: errorText ?? void 0,
|
|
399
|
+
actions,
|
|
400
|
+
className,
|
|
401
|
+
contentClassName: cn("p-2", contentClassName),
|
|
402
|
+
children: renderToolDetail?.(part) ?? /* @__PURE__ */ jsx5(ExpandedToolDetail, { part })
|
|
403
|
+
}
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
);
|
|
407
|
+
InlineToolItem.displayName = "InlineToolItem";
|
|
408
|
+
|
|
409
|
+
// src/run/tool-call-step.tsx
|
|
410
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
411
|
+
var EXT_LANGUAGE = {
|
|
412
|
+
ts: "typescript",
|
|
413
|
+
tsx: "typescript",
|
|
414
|
+
js: "javascript",
|
|
415
|
+
jsx: "javascript",
|
|
416
|
+
mjs: "javascript",
|
|
417
|
+
cjs: "javascript",
|
|
418
|
+
css: "css",
|
|
419
|
+
scss: "scss",
|
|
420
|
+
json: "json",
|
|
421
|
+
jsonc: "json",
|
|
422
|
+
md: "markdown",
|
|
423
|
+
mdx: "markdown",
|
|
424
|
+
py: "python",
|
|
425
|
+
sh: "bash",
|
|
426
|
+
bash: "bash",
|
|
427
|
+
zsh: "bash",
|
|
428
|
+
html: "html",
|
|
429
|
+
htm: "html",
|
|
430
|
+
yaml: "yaml",
|
|
431
|
+
yml: "yaml",
|
|
432
|
+
toml: "toml",
|
|
433
|
+
rs: "rust",
|
|
434
|
+
go: "go",
|
|
435
|
+
sql: "sql",
|
|
436
|
+
xml: "xml"
|
|
437
|
+
};
|
|
438
|
+
function inferLanguage(detail, language) {
|
|
439
|
+
if (language) return language;
|
|
440
|
+
if (!detail) return void 0;
|
|
441
|
+
const ext = detail.split(".").pop()?.toLowerCase();
|
|
442
|
+
return ext ? EXT_LANGUAGE[ext] : void 0;
|
|
443
|
+
}
|
|
444
|
+
var STATUS_MAP = {
|
|
445
|
+
running: "running",
|
|
446
|
+
success: "completed",
|
|
447
|
+
error: "error"
|
|
448
|
+
};
|
|
449
|
+
function ToolCallStep({
|
|
450
|
+
type,
|
|
451
|
+
label,
|
|
452
|
+
status,
|
|
453
|
+
detail,
|
|
454
|
+
output,
|
|
455
|
+
language,
|
|
456
|
+
duration,
|
|
457
|
+
className,
|
|
458
|
+
actions,
|
|
459
|
+
part
|
|
460
|
+
}) {
|
|
461
|
+
const resolvedPart = part ?? {
|
|
462
|
+
type: "tool",
|
|
463
|
+
id: `${type}:${label}`,
|
|
464
|
+
tool: type,
|
|
465
|
+
state: {
|
|
466
|
+
status: STATUS_MAP[status],
|
|
467
|
+
input: detail ? { detail } : void 0,
|
|
468
|
+
output,
|
|
469
|
+
time: duration != null ? { start: 0, end: duration } : void 0
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
const lang = inferLanguage(detail, language);
|
|
473
|
+
return /* @__PURE__ */ jsx6(
|
|
474
|
+
InlineToolItem,
|
|
475
|
+
{
|
|
476
|
+
part: resolvedPart,
|
|
477
|
+
title: label,
|
|
478
|
+
description: detail,
|
|
479
|
+
className,
|
|
480
|
+
actions,
|
|
481
|
+
renderToolDetail: part ? void 0 : output ? () => /* @__PURE__ */ jsx6(
|
|
482
|
+
CodeBlock,
|
|
483
|
+
{
|
|
484
|
+
code: output,
|
|
485
|
+
language: lang,
|
|
486
|
+
className: "max-h-72 overflow-auto text-xs"
|
|
487
|
+
}
|
|
488
|
+
) : () => null
|
|
489
|
+
}
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
function ToolCallGroup({ title, children, className }) {
|
|
493
|
+
return /* @__PURE__ */ jsxs4("div", { className: ["my-2 space-y-2", className].filter(Boolean).join(" "), children: [
|
|
494
|
+
title && /* @__PURE__ */ jsx6("div", { className: "mb-1 px-1 text-xs font-medium uppercase tracking-wider text-muted-foreground", children: title }),
|
|
495
|
+
children
|
|
496
|
+
] });
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
export {
|
|
500
|
+
ExpandableContent,
|
|
501
|
+
ExpandedToolDetail,
|
|
502
|
+
LiveDuration,
|
|
503
|
+
RunRowShell,
|
|
504
|
+
InlineToolItem,
|
|
505
|
+
ToolCallStep,
|
|
506
|
+
ToolCallGroup
|
|
507
|
+
};
|