@tangle-network/ui 1.0.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.
Files changed (220) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +33 -0
  4. package/dist/active-sessions-store-CeOmXgv5.d.ts +85 -0
  5. package/dist/artifact-pane-DvJyPWV4.d.ts +24 -0
  6. package/dist/auth.d.ts +74 -0
  7. package/dist/auth.js +15 -0
  8. package/dist/button-CMQuQEW_.d.ts +17 -0
  9. package/dist/chat.d.ts +232 -0
  10. package/dist/chat.js +30 -0
  11. package/dist/chunk-2NFQRQOD.js +1009 -0
  12. package/dist/chunk-2VH6PUXD.js +186 -0
  13. package/dist/chunk-34A66VBG.js +214 -0
  14. package/dist/chunk-3OI2QKFD.js +0 -0
  15. package/dist/chunk-4CLN43XT.js +45 -0
  16. package/dist/chunk-54SQQMMM.js +156 -0
  17. package/dist/chunk-5Z5ZYMOJ.js +0 -0
  18. package/dist/chunk-66BNMOVT.js +167 -0
  19. package/dist/chunk-6BGQA4BQ.js +0 -0
  20. package/dist/chunk-7UO2ZMRQ.js +133 -0
  21. package/dist/chunk-BX6AQMUS.js +183 -0
  22. package/dist/chunk-CD53GZOM.js +59 -0
  23. package/dist/chunk-CSAIKY36.js +54 -0
  24. package/dist/chunk-EEE55AVS.js +1201 -0
  25. package/dist/chunk-GYPQXTJU.js +230 -0
  26. package/dist/chunk-HFL6R6IF.js +37 -0
  27. package/dist/chunk-HJKCSXCH.js +737 -0
  28. package/dist/chunk-LISXUB4D.js +1222 -0
  29. package/dist/chunk-LQS34IGP.js +0 -0
  30. package/dist/chunk-MKTSMWVD.js +109 -0
  31. package/dist/chunk-NKDZ7GZE.js +192 -0
  32. package/dist/chunk-OEX7NZE3.js +321 -0
  33. package/dist/chunk-Q56BYXQF.js +61 -0
  34. package/dist/chunk-Q7EIIWTC.js +0 -0
  35. package/dist/chunk-REJESC5U.js +117 -0
  36. package/dist/chunk-RQGKSCEZ.js +0 -0
  37. package/dist/chunk-RQHJBTEU.js +10 -0
  38. package/dist/chunk-TMFOPHHN.js +299 -0
  39. package/dist/chunk-XGKULLYE.js +40 -0
  40. package/dist/chunk-XIHMJ7ZQ.js +614 -0
  41. package/dist/chunk-YJ2G3XO5.js +1048 -0
  42. package/dist/chunk-YNN4O57I.js +754 -0
  43. package/dist/code-block-DjXf8eOG.d.ts +19 -0
  44. package/dist/document-editor-pane-A5LT5H4N.js +12 -0
  45. package/dist/document-editor-pane-DyDEX_Zm.d.ts +124 -0
  46. package/dist/editor.d.ts +120 -0
  47. package/dist/editor.js +34 -0
  48. package/dist/files.d.ts +175 -0
  49. package/dist/files.js +20 -0
  50. package/dist/hooks.d.ts +56 -0
  51. package/dist/hooks.js +41 -0
  52. package/dist/index.d.ts +43 -0
  53. package/dist/index.js +446 -0
  54. package/dist/markdown.d.ts +15 -0
  55. package/dist/markdown.js +14 -0
  56. package/dist/message-BHWbxBtT.d.ts +15 -0
  57. package/dist/openui.d.ts +115 -0
  58. package/dist/openui.js +12 -0
  59. package/dist/parts-dj7AcUg0.d.ts +36 -0
  60. package/dist/primitives.d.ts +332 -0
  61. package/dist/primitives.js +191 -0
  62. package/dist/run-PfLmDAox.d.ts +41 -0
  63. package/dist/run.d.ts +69 -0
  64. package/dist/run.js +36 -0
  65. package/dist/sdk-hooks.d.ts +285 -0
  66. package/dist/sdk-hooks.js +31 -0
  67. package/dist/stores.d.ts +17 -0
  68. package/dist/stores.js +76 -0
  69. package/dist/tool-call-feed-Bs3MyQMT.d.ts +68 -0
  70. package/dist/tool-display-z4JcDmMQ.d.ts +32 -0
  71. package/dist/tool-previews.d.ts +48 -0
  72. package/dist/tool-previews.js +21 -0
  73. package/dist/types.d.ts +19 -0
  74. package/dist/types.js +1 -0
  75. package/dist/utils.d.ts +45 -0
  76. package/dist/utils.js +32 -0
  77. package/package.json +193 -0
  78. package/src/auth/auth.tsx +228 -0
  79. package/src/auth/index.ts +13 -0
  80. package/src/auth/login-layout.tsx +46 -0
  81. package/src/chat/agent-timeline.stories.tsx +429 -0
  82. package/src/chat/agent-timeline.tsx +360 -0
  83. package/src/chat/chat-container.tsx +486 -0
  84. package/src/chat/chat-input.stories.tsx +142 -0
  85. package/src/chat/chat-input.tsx +389 -0
  86. package/src/chat/chat-message.stories.tsx +237 -0
  87. package/src/chat/chat-message.tsx +129 -0
  88. package/src/chat/index.ts +18 -0
  89. package/src/chat/message-list.stories.tsx +336 -0
  90. package/src/chat/message-list.tsx +79 -0
  91. package/src/chat/thinking-indicator.stories.tsx +56 -0
  92. package/src/chat/thinking-indicator.tsx +30 -0
  93. package/src/chat/user-message.stories.tsx +92 -0
  94. package/src/chat/user-message.tsx +43 -0
  95. package/src/editor/document-editor-pane.tsx +351 -0
  96. package/src/editor/editor-provider.tsx +428 -0
  97. package/src/editor/editor-toolbar.tsx +130 -0
  98. package/src/editor/index.ts +31 -0
  99. package/src/editor/markdown-conversion.ts +21 -0
  100. package/src/editor/markdown-document-editor.tsx +137 -0
  101. package/src/editor/tiptap-editor.tsx +331 -0
  102. package/src/editor/use-editor.ts +221 -0
  103. package/src/files/file-artifact-pane.tsx +183 -0
  104. package/src/files/file-preview.tsx +342 -0
  105. package/src/files/file-tabs.tsx +71 -0
  106. package/src/files/file-tree.tsx +258 -0
  107. package/src/files/index.ts +17 -0
  108. package/src/files/rich-file-tree.stories.tsx +104 -0
  109. package/src/files/rich-file-tree.test.tsx +42 -0
  110. package/src/files/rich-file-tree.tsx +232 -0
  111. package/src/hooks/index.ts +10 -0
  112. package/src/hooks/use-auth.ts +153 -0
  113. package/src/hooks/use-auto-scroll.ts +59 -0
  114. package/src/hooks/use-dropdown-menu.ts +40 -0
  115. package/src/hooks/use-live-time.test.tsx +40 -0
  116. package/src/hooks/use-live-time.ts +27 -0
  117. package/src/hooks/use-realtime-session.ts +319 -0
  118. package/src/hooks/use-run-collapse-state.ts +25 -0
  119. package/src/hooks/use-run-groups.ts +111 -0
  120. package/src/hooks/use-sdk-session.ts +575 -0
  121. package/src/hooks/use-sse-stream.ts +475 -0
  122. package/src/hooks/use-tool-call-stream.ts +96 -0
  123. package/src/index.ts +14 -0
  124. package/src/lib/utils.ts +6 -0
  125. package/src/markdown/code-block.tsx +198 -0
  126. package/src/markdown/index.ts +2 -0
  127. package/src/markdown/markdown.stories.tsx +190 -0
  128. package/src/markdown/markdown.tsx +62 -0
  129. package/src/openui/index.ts +20 -0
  130. package/src/openui/openui-artifact-renderer.tsx +542 -0
  131. package/src/primitives/artifact-pane.tsx +91 -0
  132. package/src/primitives/avatar.stories.tsx +95 -0
  133. package/src/primitives/avatar.tsx +47 -0
  134. package/src/primitives/badge.stories.tsx +57 -0
  135. package/src/primitives/badge.tsx +97 -0
  136. package/src/primitives/button.stories.tsx +48 -0
  137. package/src/primitives/button.tsx +115 -0
  138. package/src/primitives/card.stories.tsx +53 -0
  139. package/src/primitives/card.tsx +98 -0
  140. package/src/primitives/code-block.stories.tsx +115 -0
  141. package/src/primitives/code-block.tsx +22 -0
  142. package/src/primitives/design-tokens.stories.tsx +162 -0
  143. package/src/primitives/dialog.stories.tsx +176 -0
  144. package/src/primitives/dialog.tsx +137 -0
  145. package/src/primitives/drop-zone.stories.tsx +123 -0
  146. package/src/primitives/drop-zone.tsx +131 -0
  147. package/src/primitives/dropdown-menu.stories.tsx +122 -0
  148. package/src/primitives/dropdown-menu.tsx +214 -0
  149. package/src/primitives/empty-state.stories.tsx +81 -0
  150. package/src/primitives/empty-state.tsx +40 -0
  151. package/src/primitives/index.ts +118 -0
  152. package/src/primitives/input.stories.tsx +113 -0
  153. package/src/primitives/input.tsx +136 -0
  154. package/src/primitives/label.stories.tsx +84 -0
  155. package/src/primitives/label.tsx +24 -0
  156. package/src/primitives/progress.stories.tsx +93 -0
  157. package/src/primitives/progress.tsx +50 -0
  158. package/src/primitives/segmented-control.test.tsx +328 -0
  159. package/src/primitives/segmented-control.tsx +154 -0
  160. package/src/primitives/select.stories.tsx +164 -0
  161. package/src/primitives/select.tsx +158 -0
  162. package/src/primitives/sidebar-drop-zone.stories.tsx +100 -0
  163. package/src/primitives/sidebar-drop-zone.tsx +149 -0
  164. package/src/primitives/skeleton.stories.tsx +79 -0
  165. package/src/primitives/skeleton.tsx +55 -0
  166. package/src/primitives/stat-card.stories.tsx +137 -0
  167. package/src/primitives/stat-card.tsx +97 -0
  168. package/src/primitives/switch.stories.tsx +85 -0
  169. package/src/primitives/switch.tsx +28 -0
  170. package/src/primitives/table.stories.tsx +170 -0
  171. package/src/primitives/table.tsx +116 -0
  172. package/src/primitives/tabs.stories.tsx +180 -0
  173. package/src/primitives/tabs.tsx +71 -0
  174. package/src/primitives/terminal-display.stories.tsx +191 -0
  175. package/src/primitives/terminal-display.tsx +189 -0
  176. package/src/primitives/theme-toggle.stories.tsx +32 -0
  177. package/src/primitives/theme-toggle.tsx +96 -0
  178. package/src/primitives/toast.stories.tsx +155 -0
  179. package/src/primitives/toast.tsx +190 -0
  180. package/src/primitives/upload-progress.stories.tsx +120 -0
  181. package/src/primitives/upload-progress.tsx +110 -0
  182. package/src/run/expanded-tool-detail.stories.tsx +182 -0
  183. package/src/run/expanded-tool-detail.tsx +186 -0
  184. package/src/run/index.ts +13 -0
  185. package/src/run/inline-thinking-item.stories.tsx +136 -0
  186. package/src/run/inline-thinking-item.tsx +120 -0
  187. package/src/run/inline-tool-item.stories.tsx +222 -0
  188. package/src/run/inline-tool-item.tsx +190 -0
  189. package/src/run/run-group.stories.tsx +322 -0
  190. package/src/run/run-group.tsx +569 -0
  191. package/src/run/run-item-primitives.tsx +17 -0
  192. package/src/run/tool-call-feed.stories.tsx +294 -0
  193. package/src/run/tool-call-feed.tsx +192 -0
  194. package/src/run/tool-call-step.stories.tsx +198 -0
  195. package/src/run/tool-call-step.tsx +240 -0
  196. package/src/sdk-hooks.ts +38 -0
  197. package/src/stores/active-sessions-store.ts +455 -0
  198. package/src/stores/chat-store.ts +43 -0
  199. package/src/stores/index.ts +2 -0
  200. package/src/tool-previews/command-preview.tsx +116 -0
  201. package/src/tool-previews/diff-preview.tsx +85 -0
  202. package/src/tool-previews/glob-results-preview.tsx +98 -0
  203. package/src/tool-previews/grep-results-preview.tsx +157 -0
  204. package/src/tool-previews/index.ts +22 -0
  205. package/src/tool-previews/preview-primitives.tsx +84 -0
  206. package/src/tool-previews/question-preview.tsx +101 -0
  207. package/src/tool-previews/web-search-preview.tsx +117 -0
  208. package/src/tool-previews/write-file-preview.tsx +80 -0
  209. package/src/types/branding.ts +11 -0
  210. package/src/types/index.ts +5 -0
  211. package/src/types/message.ts +13 -0
  212. package/src/types/parts.ts +51 -0
  213. package/src/types/run.ts +56 -0
  214. package/src/types/tool-display.ts +41 -0
  215. package/src/utils/copy-text.ts +30 -0
  216. package/src/utils/format.test.ts +43 -0
  217. package/src/utils/format.ts +56 -0
  218. package/src/utils/index.ts +10 -0
  219. package/src/utils/time-ago.ts +9 -0
  220. package/src/utils/tool-display.ts +238 -0
@@ -0,0 +1,167 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-RQHJBTEU.js";
4
+
5
+ // src/markdown/code-block.tsx
6
+ import {
7
+ memo,
8
+ useCallback,
9
+ useEffect,
10
+ useRef,
11
+ useState
12
+ } from "react";
13
+ import SyntaxHighlighter from "react-syntax-highlighter";
14
+ import { Check, Copy } from "lucide-react";
15
+ import { jsx, jsxs } from "react/jsx-runtime";
16
+ function getSyntaxTheme() {
17
+ const el = typeof document !== "undefined" ? document.documentElement : null;
18
+ const v = (name, fallback) => el ? getComputedStyle(el).getPropertyValue(name).trim() || fallback : fallback;
19
+ const comment = v("--syntax-comment", "#6B7094");
20
+ const keyword = v("--syntax-keyword", "#A78FFF");
21
+ const string = v("--syntax-string", "#10b981");
22
+ const fn = v("--syntax-function", "#6D9FFF");
23
+ const number = v("--syntax-number", "#FFB347");
24
+ const meta = v("--syntax-meta", "#8263FF");
25
+ const error = v("--syntax-error", "#FF4D6D");
26
+ const variable = v("--syntax-variable", "#C4C0D8");
27
+ const fg = v("--syntax-foreground", "#E8E6F6");
28
+ return {
29
+ "hljs-comment": { color: comment, fontStyle: "italic" },
30
+ "hljs-quote": { color: comment, fontStyle: "italic" },
31
+ "hljs-doctag": { color: comment },
32
+ "hljs-keyword": { color: keyword },
33
+ "hljs-selector-tag": { color: keyword },
34
+ "hljs-literal": { color: keyword },
35
+ "hljs-type": { color: keyword },
36
+ "hljs-class": { color: keyword },
37
+ "hljs-string": { color: string },
38
+ "hljs-template-tag": { color: string },
39
+ "hljs-template-variable": { color: string },
40
+ "hljs-addition": { color: string },
41
+ "hljs-regexp": { color: string },
42
+ "hljs-title": { color: fn },
43
+ "hljs-section": { color: fn },
44
+ "hljs-built_in": { color: fn },
45
+ "hljs-name": { color: fn },
46
+ "hljs-function": { color: fn },
47
+ "hljs-selector-id": { color: fn },
48
+ "hljs-selector-class": { color: fn },
49
+ "hljs-attribute": { color: fn },
50
+ "hljs-number": { color: number },
51
+ "hljs-symbol": { color: number },
52
+ "hljs-bullet": { color: number },
53
+ "hljs-link": { color: number, textDecoration: "underline" },
54
+ "hljs-meta": { color: meta },
55
+ "hljs-selector-pseudo": { color: meta },
56
+ "hljs-deletion": { color: error },
57
+ "hljs-params": { color: variable },
58
+ "hljs-variable": { color: variable },
59
+ "hljs-tag": { color: variable },
60
+ "hljs-attr": { color: variable },
61
+ "hljs-subst": { color: variable },
62
+ "hljs-strong": { fontWeight: "bold" },
63
+ "hljs-emphasis": { fontStyle: "italic" },
64
+ "hljs": { color: fg, background: "transparent" }
65
+ };
66
+ }
67
+ var LIGHT_THEMES = /* @__PURE__ */ new Set(["vault", "dawn"]);
68
+ function detectLightTheme() {
69
+ return typeof document !== "undefined" && LIGHT_THEMES.has(document.documentElement.getAttribute("data-sandbox-theme") ?? "");
70
+ }
71
+ function useIsLightTheme() {
72
+ const [isLight, setIsLight] = useState(detectLightTheme);
73
+ useEffect(() => {
74
+ if (typeof document === "undefined") return;
75
+ setIsLight(detectLightTheme());
76
+ const observer = new MutationObserver(() => setIsLight(detectLightTheme()));
77
+ observer.observe(document.documentElement, {
78
+ attributes: true,
79
+ attributeFilter: ["data-sandbox-theme"]
80
+ });
81
+ return () => observer.disconnect();
82
+ }, []);
83
+ return isLight;
84
+ }
85
+ var CodeBlock = memo(
86
+ ({ code, language, showLineNumbers = false, light: lightProp, className, children, ...props }) => {
87
+ const isLight = useIsLightTheme();
88
+ const light = lightProp ?? isLight;
89
+ const theme = getSyntaxTheme();
90
+ const bg = "bg-card border-border";
91
+ const headerBg = light ? "bg-muted/50 border-border" : "bg-background border-border";
92
+ const langColor = "text-muted-foreground";
93
+ return /* @__PURE__ */ jsxs(
94
+ "div",
95
+ {
96
+ className: cn("group relative overflow-hidden rounded-lg border font-mono", bg, className),
97
+ ...props,
98
+ children: [
99
+ language && /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between border-b px-3 py-1", headerBg), children: [
100
+ /* @__PURE__ */ jsx("span", { className: cn("text-[calc(var(--font-size-xs)-1px)] font-mono font-medium uppercase tracking-widest", langColor), children: language }),
101
+ children
102
+ ] }),
103
+ !language && children && /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2 z-10 flex items-center gap-2 opacity-0 transition-opacity group-hover:opacity-100", children }),
104
+ /* @__PURE__ */ jsx(
105
+ SyntaxHighlighter,
106
+ {
107
+ language: language ?? "text",
108
+ style: theme,
109
+ showLineNumbers,
110
+ lineNumberStyle: {
111
+ color: light ? "#8B92B8" : "#4A4D6A",
112
+ minWidth: "2.5em",
113
+ paddingRight: "1em"
114
+ },
115
+ customStyle: {
116
+ margin: 0,
117
+ padding: "var(--code-padding-y, 0.625rem) var(--code-padding-x, 0.75rem)",
118
+ background: "transparent",
119
+ fontSize: "var(--code-font-size, 0.8125rem)",
120
+ lineHeight: "var(--code-line-height, 1.5)",
121
+ overflowX: "auto"
122
+ },
123
+ codeTagProps: { style: { fontFamily: "var(--font-mono, 'JetBrains Mono', ui-monospace, monospace)" } },
124
+ wrapLines: false,
125
+ children: code
126
+ }
127
+ )
128
+ ]
129
+ }
130
+ );
131
+ }
132
+ );
133
+ CodeBlock.displayName = "CodeBlock";
134
+ var CopyButton = memo(({ text }) => {
135
+ const [copied, setCopied] = useState(false);
136
+ const timerRef = useRef(null);
137
+ useEffect(() => {
138
+ return () => {
139
+ if (timerRef.current) clearTimeout(timerRef.current);
140
+ };
141
+ }, []);
142
+ const handleCopy = useCallback(async () => {
143
+ try {
144
+ await navigator.clipboard.writeText(text);
145
+ setCopied(true);
146
+ if (timerRef.current) clearTimeout(timerRef.current);
147
+ timerRef.current = setTimeout(() => setCopied(false), 2e3);
148
+ } catch (err) {
149
+ console.warn("Clipboard write failed:", err);
150
+ }
151
+ }, [text]);
152
+ return /* @__PURE__ */ jsx(
153
+ "button",
154
+ {
155
+ onClick: handleCopy,
156
+ className: "flex items-center justify-center w-6 h-6 rounded-md bg-muted border border-border hover:border-primary/20 transition-colors",
157
+ title: "Copy to clipboard",
158
+ children: copied ? /* @__PURE__ */ jsx(Check, { className: "w-3.5 h-3.5 text-emerald-500" }) : /* @__PURE__ */ jsx(Copy, { className: "w-3.5 h-3.5 text-muted-foreground" })
159
+ }
160
+ );
161
+ });
162
+ CopyButton.displayName = "CopyButton";
163
+
164
+ export {
165
+ CodeBlock,
166
+ CopyButton
167
+ };
File without changes
@@ -0,0 +1,133 @@
1
+ import {
2
+ ToolCallGroup,
3
+ ToolCallStep
4
+ } from "./chunk-2VH6PUXD.js";
5
+ import {
6
+ Markdown
7
+ } from "./chunk-CD53GZOM.js";
8
+ import {
9
+ cn
10
+ } from "./chunk-RQHJBTEU.js";
11
+
12
+ // src/run/tool-call-feed.tsx
13
+ import { jsx } from "react/jsx-runtime";
14
+ function ToolCallFeed({ segments, className }) {
15
+ if (segments.length === 0) return null;
16
+ return /* @__PURE__ */ jsx("div", { className: cn("space-y-1", className), children: segments.map((segment, i) => {
17
+ if (segment.kind === "text") {
18
+ return segment.content.trim() ? /* @__PURE__ */ jsx(Markdown, { children: segment.content }, i) : null;
19
+ }
20
+ if (segment.kind === "tool_call") {
21
+ return /* @__PURE__ */ jsx(
22
+ ToolCallStep,
23
+ {
24
+ type: segment.call.type,
25
+ label: segment.call.label,
26
+ status: segment.call.status,
27
+ detail: segment.call.detail,
28
+ output: segment.call.output,
29
+ duration: segment.call.duration
30
+ },
31
+ segment.call.id || i
32
+ );
33
+ }
34
+ if (segment.kind === "tool_group") {
35
+ return /* @__PURE__ */ jsx(ToolCallGroup, { title: segment.title, children: segment.calls.map((call) => /* @__PURE__ */ jsx(
36
+ ToolCallStep,
37
+ {
38
+ type: call.type,
39
+ label: call.label,
40
+ status: call.status,
41
+ detail: call.detail,
42
+ output: call.output,
43
+ duration: call.duration
44
+ },
45
+ call.id
46
+ )) }, i);
47
+ }
48
+ return null;
49
+ }) });
50
+ }
51
+ function parseToolEvent(event) {
52
+ const { type, data } = event;
53
+ if (type === "tool.invocation" || type === "tool_use") {
54
+ const toolName = data.name || data.tool || "unknown";
55
+ const input = data.input;
56
+ return {
57
+ id: data.id || data.toolUseId || createId(),
58
+ type: mapToolName(toolName),
59
+ label: formatToolLabel(toolName, input),
60
+ status: "running",
61
+ detail: input ? formatToolInput(toolName, input) : void 0
62
+ };
63
+ }
64
+ if (type === "tool.result" || type === "tool_result") {
65
+ return {
66
+ id: data.id || data.toolUseId || "",
67
+ type: mapToolName(data.name || data.tool || "unknown"),
68
+ label: formatToolLabel(data.name || data.tool || "unknown"),
69
+ status: data.error ? "error" : "success",
70
+ output: truncate(data.output || data.result || "", 500),
71
+ duration: data.duration
72
+ };
73
+ }
74
+ return null;
75
+ }
76
+ function createId() {
77
+ if (typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.randomUUID === "function") {
78
+ try {
79
+ return globalThis.crypto.randomUUID();
80
+ } catch {
81
+ }
82
+ }
83
+ return `tool_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
84
+ }
85
+ function mapToolName(name) {
86
+ const lower = name.toLowerCase();
87
+ if (lower.includes("bash") || lower.includes("terminal") || lower.includes("exec")) return "bash";
88
+ if (lower.includes("read") || lower.includes("cat")) return "read";
89
+ if (lower.includes("write") || lower.includes("create")) return "write";
90
+ if (lower.includes("edit") || lower.includes("replace")) return "edit";
91
+ if (lower.includes("glob") || lower.includes("find")) return "glob";
92
+ if (lower.includes("grep") || lower.includes("search")) return "grep";
93
+ if (lower.includes("list") || lower.includes("ls")) return "list";
94
+ if (lower.includes("inspect")) return "inspect";
95
+ if (lower.includes("audit")) return "audit";
96
+ return "unknown";
97
+ }
98
+ function formatToolLabel(toolName, input) {
99
+ const lower = toolName.toLowerCase();
100
+ if (lower.includes("bash") && input?.command) {
101
+ const cmd = String(input.command);
102
+ return cmd.length > 80 ? `${cmd.slice(0, 77)}...` : cmd;
103
+ }
104
+ if ((lower.includes("read") || lower.includes("cat")) && input?.path) {
105
+ return `Read ${input.path}`;
106
+ }
107
+ if (lower.includes("write") && input?.path) {
108
+ return `Write ${input.path}`;
109
+ }
110
+ if (lower.includes("edit") && input?.path) {
111
+ return `Edit ${input.path}`;
112
+ }
113
+ if (lower.includes("glob") && input?.pattern) {
114
+ return `Find ${input.pattern}`;
115
+ }
116
+ if (lower.includes("grep") && input?.pattern) {
117
+ return `Search for ${input.pattern}`;
118
+ }
119
+ return toolName;
120
+ }
121
+ function formatToolInput(toolName, input) {
122
+ if (input.command) return String(input.command);
123
+ if (input.path) return String(input.path);
124
+ return JSON.stringify(input, null, 2).slice(0, 300);
125
+ }
126
+ function truncate(text, max) {
127
+ return text.length > max ? text.slice(0, max - 3) + "..." : text;
128
+ }
129
+
130
+ export {
131
+ ToolCallFeed,
132
+ parseToolEvent
133
+ };
@@ -0,0 +1,183 @@
1
+ // src/utils/tool-display.ts
2
+ var TOOL_NAME_PREFIX = "tool:";
3
+ function normalizeToolName(tool) {
4
+ const n = tool?.toLowerCase() ?? "";
5
+ return n.startsWith(TOOL_NAME_PREFIX) ? n.slice(TOOL_NAME_PREFIX.length) : n;
6
+ }
7
+ function extractString(obj, key) {
8
+ if (typeof obj === "object" && obj !== null && key in obj) {
9
+ const val = obj[key];
10
+ if (typeof val === "string") return val;
11
+ }
12
+ return void 0;
13
+ }
14
+ function extractCommand(input) {
15
+ if (typeof input === "string") return input;
16
+ return extractString(input, "command") ?? extractString(input, "cmd");
17
+ }
18
+ function extractFilePath(input) {
19
+ return extractString(input, "file_path") ?? extractString(input, "path") ?? extractString(input, "filePath") ?? extractString(input, "file");
20
+ }
21
+ function cleanPath(path) {
22
+ const parts = path.split("/");
23
+ return parts.length > 3 ? ".../" + parts.slice(-2).join("/") : path;
24
+ }
25
+ var TOOL_CATEGORY_ICONS = {
26
+ command: "terminal",
27
+ write: "file-plus",
28
+ read: "file-text",
29
+ search: "search",
30
+ edit: "file-edit",
31
+ task: "cpu",
32
+ web: "globe",
33
+ todo: "check-square",
34
+ other: "box"
35
+ };
36
+ function getToolCategory(toolName) {
37
+ const name = normalizeToolName(toolName);
38
+ switch (name) {
39
+ case "bash":
40
+ case "shell":
41
+ case "command":
42
+ case "execute":
43
+ return "command";
44
+ case "write":
45
+ case "write_file":
46
+ case "create_file":
47
+ return "write";
48
+ case "read":
49
+ case "read_file":
50
+ case "cat":
51
+ return "read";
52
+ case "grep":
53
+ case "search":
54
+ case "rg":
55
+ return "search";
56
+ case "edit":
57
+ case "patch":
58
+ case "sed":
59
+ return "edit";
60
+ case "glob":
61
+ case "find":
62
+ case "ls":
63
+ return "search";
64
+ case "web_search":
65
+ case "web_fetch":
66
+ case "fetch":
67
+ return "web";
68
+ case "task":
69
+ case "agent":
70
+ case "spawn":
71
+ return "task";
72
+ case "todo":
73
+ case "todo_write":
74
+ return "todo";
75
+ default:
76
+ return "other";
77
+ }
78
+ }
79
+ function getToolDisplayMetadata(part) {
80
+ const name = normalizeToolName(part.tool);
81
+ const input = part.state.status !== "pending" ? part.state.input : void 0;
82
+ const filePath = extractFilePath(input);
83
+ const command = extractCommand(input);
84
+ switch (name) {
85
+ case "bash":
86
+ case "shell":
87
+ case "command":
88
+ case "execute":
89
+ return {
90
+ title: "Run command",
91
+ description: command ? truncateCommand(command) : void 0,
92
+ displayVariant: "command",
93
+ commandSnippet: command
94
+ };
95
+ case "write":
96
+ case "write_file":
97
+ case "create_file":
98
+ return {
99
+ title: filePath ? `Write ${cleanPath(filePath)}` : "Write file",
100
+ description: filePath,
101
+ displayVariant: "write-file",
102
+ targetPath: filePath
103
+ };
104
+ case "edit":
105
+ case "patch":
106
+ return {
107
+ title: filePath ? `Edit ${cleanPath(filePath)}` : "Edit file",
108
+ description: filePath,
109
+ hasDiffOutput: true,
110
+ diffFilePath: filePath,
111
+ displayVariant: "diff",
112
+ targetPath: filePath
113
+ };
114
+ case "read":
115
+ case "read_file":
116
+ case "cat":
117
+ return {
118
+ title: filePath ? `Read ${cleanPath(filePath)}` : "Read file",
119
+ description: filePath,
120
+ displayVariant: "read-file",
121
+ targetPath: filePath
122
+ };
123
+ case "grep":
124
+ case "search":
125
+ case "rg": {
126
+ const pattern = extractString(input, "pattern");
127
+ return {
128
+ title: pattern ? `Search: ${pattern}` : "Search",
129
+ description: pattern,
130
+ displayVariant: "grep"
131
+ };
132
+ }
133
+ case "glob":
134
+ case "find":
135
+ case "ls": {
136
+ const pattern = extractString(input, "pattern");
137
+ return {
138
+ title: pattern ? `Find: ${pattern}` : "Find files",
139
+ description: pattern,
140
+ displayVariant: "glob"
141
+ };
142
+ }
143
+ case "web_search":
144
+ case "web_fetch":
145
+ case "fetch": {
146
+ const query = extractString(input, "query") ?? extractString(input, "url");
147
+ return {
148
+ title: query ? `Web: ${truncateCommand(query)}` : "Web search",
149
+ description: query,
150
+ displayVariant: "web-search"
151
+ };
152
+ }
153
+ case "task":
154
+ case "agent":
155
+ case "spawn": {
156
+ const desc = extractString(input, "description") ?? extractString(input, "prompt");
157
+ return {
158
+ title: desc ? `Task: ${truncateCommand(desc)}` : "Agent task",
159
+ description: desc
160
+ };
161
+ }
162
+ default:
163
+ return {
164
+ title: part.tool || "Tool",
165
+ description: command ?? filePath ?? extractString(input, "pattern") ?? extractString(input, "query")
166
+ };
167
+ }
168
+ }
169
+ function truncateCommand(cmd) {
170
+ const first = cmd.split("\n")[0];
171
+ return first.length > 60 ? first.slice(0, 57) + "..." : first;
172
+ }
173
+ function getToolErrorText(part, fallback) {
174
+ if (part.state.status !== "error") return void 0;
175
+ return part.state.error || fallback;
176
+ }
177
+
178
+ export {
179
+ TOOL_CATEGORY_ICONS,
180
+ getToolCategory,
181
+ getToolDisplayMetadata,
182
+ getToolErrorText
183
+ };
@@ -0,0 +1,59 @@
1
+ import {
2
+ CodeBlock,
3
+ CopyButton
4
+ } from "./chunk-66BNMOVT.js";
5
+ import {
6
+ cn
7
+ } from "./chunk-RQHJBTEU.js";
8
+
9
+ // src/markdown/markdown.tsx
10
+ import { memo } from "react";
11
+ import ReactMarkdown from "react-markdown";
12
+ import remarkGfm from "remark-gfm";
13
+ import rehypeSanitize from "rehype-sanitize";
14
+ import { Fragment, jsx } from "react/jsx-runtime";
15
+ var Markdown = memo(({ children, className }) => {
16
+ return /* @__PURE__ */ jsx(
17
+ "div",
18
+ {
19
+ className: cn("prose prose-sm dark:prose-invert max-w-none", className),
20
+ children: /* @__PURE__ */ jsx(
21
+ ReactMarkdown,
22
+ {
23
+ remarkPlugins: [remarkGfm],
24
+ rehypePlugins: [rehypeSanitize],
25
+ components: {
26
+ pre({ children: preChildren }) {
27
+ return /* @__PURE__ */ jsx(Fragment, { children: preChildren });
28
+ },
29
+ code({ className: codeClass, children: codeChildren, ...rest }) {
30
+ const match = /language-(\w+)/.exec(codeClass || "");
31
+ const language = match?.[1];
32
+ const code = String(codeChildren).replace(/\n$/, "");
33
+ if (!language && !code.includes("\n")) {
34
+ return /* @__PURE__ */ jsx(
35
+ "code",
36
+ {
37
+ className: cn(
38
+ "px-1.5 py-0.5 rounded border border-border bg-card text-[var(--code-keyword)] text-[0.85em] font-mono",
39
+ codeClass
40
+ ),
41
+ ...rest,
42
+ children: codeChildren
43
+ }
44
+ );
45
+ }
46
+ return /* @__PURE__ */ jsx(CodeBlock, { code, language, children: /* @__PURE__ */ jsx(CopyButton, { text: code }) });
47
+ }
48
+ },
49
+ children
50
+ }
51
+ )
52
+ }
53
+ );
54
+ });
55
+ Markdown.displayName = "Markdown";
56
+
57
+ export {
58
+ Markdown
59
+ };
@@ -0,0 +1,54 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-RQHJBTEU.js";
4
+
5
+ // src/primitives/artifact-pane.tsx
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ function ArtifactPane({
8
+ eyebrow,
9
+ title,
10
+ subtitle,
11
+ meta,
12
+ headerActions,
13
+ tabs,
14
+ toolbar,
15
+ footer,
16
+ emptyState,
17
+ children,
18
+ className,
19
+ contentClassName
20
+ }) {
21
+ const hasContent = children !== void 0 && children !== null;
22
+ return /* @__PURE__ */ jsxs(
23
+ "section",
24
+ {
25
+ className: cn(
26
+ "flex h-full min-h-0 flex-col overflow-hidden bg-background text-foreground",
27
+ className
28
+ ),
29
+ children: [
30
+ /* @__PURE__ */ jsxs("header", { className: "border-b border-border bg-muted/10", children: [
31
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 px-3 py-2", children: [
32
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
33
+ eyebrow && /* @__PURE__ */ jsx("div", { className: "mb-1 inline-flex max-w-full items-center px-1 py-0.5 text-[10px] font-bold uppercase tracking-wider text-muted-foreground", children: eyebrow }),
34
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 text-[13px] font-medium text-foreground", children: title }),
35
+ (subtitle || meta) && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-xs leading-relaxed text-muted-foreground", children: [
36
+ subtitle && /* @__PURE__ */ jsx("span", { className: "truncate", children: subtitle }),
37
+ meta && /* @__PURE__ */ jsx("span", { className: "flex items-center gap-2", children: meta })
38
+ ] })
39
+ ] }),
40
+ headerActions && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-1.5", children: headerActions })
41
+ ] }),
42
+ tabs,
43
+ toolbar && /* @__PURE__ */ jsx("div", { className: "border-t border-border px-3 py-2", children: toolbar })
44
+ ] }),
45
+ /* @__PURE__ */ jsx("div", { className: cn("min-h-0 flex-1 overflow-auto", contentClassName), children: hasContent ? children : emptyState ? /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center p-6", children: emptyState }) : null }),
46
+ footer && /* @__PURE__ */ jsx("footer", { className: "shrink-0 border-t border-border bg-card px-3 py-2", children: footer })
47
+ ]
48
+ }
49
+ );
50
+ }
51
+
52
+ export {
53
+ ArtifactPane
54
+ };