@tangle-network/ui 11.9.0 → 11.11.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 (155) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +14 -0
  3. package/dist/active-sessions-store-Gt1R0rFG.js +262 -0
  4. package/dist/{active-sessions-store-CeOmXgv5.d.ts → active-sessions-store-nl70ZnMC.d.ts} +40 -41
  5. package/dist/artifact-pane-BL_DFWNl.d.ts +32 -0
  6. package/dist/artifact-pane-DMXT9a8U.js +70 -0
  7. package/dist/auth-DixfCMCk.js +154 -0
  8. package/dist/auth.d.ts +2 -74
  9. package/dist/auth.js +2 -15
  10. package/dist/branding-26d5ARIr.d.ts +14 -0
  11. package/dist/button-uhNnwdsD.js +78 -0
  12. package/dist/button-yoIv77e2.d.ts +16 -0
  13. package/dist/chat-CPLL0Fd9.js +667 -0
  14. package/dist/chat.d.ts +2 -201
  15. package/dist/chat.js +2 -30
  16. package/dist/code-block-B9miUPht.d.ts +23 -0
  17. package/dist/code-block-CngSn37j.js +165 -0
  18. package/dist/diff-preview-cySuqowW.js +533 -0
  19. package/dist/document-editor-pane-BcoABlhn.d.ts +131 -0
  20. package/dist/document-editor-pane-Cz6oEF1o.js +1287 -0
  21. package/dist/dropdown-menu-BpcLa5vF.js +101 -0
  22. package/dist/editor.d.ts +76 -78
  23. package/dist/editor.js +2 -33
  24. package/dist/file-format-BgXbr-Ib.js +160 -0
  25. package/dist/files-CYlOo0mE.js +743 -0
  26. package/dist/files.d.ts +2 -243
  27. package/dist/files.js +3 -40
  28. package/dist/focus-Cw02pNSr.js +56 -0
  29. package/dist/format-DfcLWqMa.js +54 -0
  30. package/dist/hooks.d.ts +30 -37
  31. package/dist/hooks.js +111 -45
  32. package/dist/index-2UntyjBb.d.ts +52 -0
  33. package/dist/index-COgqsFAQ.d.ts +42 -0
  34. package/dist/index-CPDET_s1.d.ts +549 -0
  35. package/dist/index-CUhfHT_V.d.ts +204 -0
  36. package/dist/index-Cg6gYAqh.d.ts +73 -0
  37. package/dist/index-Cq-EJzqW.d.ts +16 -0
  38. package/dist/index-DhYmSaLF.d.ts +245 -0
  39. package/dist/index-DjKxO357.d.ts +128 -0
  40. package/dist/index-b56ew9aF.d.ts +107 -0
  41. package/dist/index.d.ts +26 -43
  42. package/dist/index.js +35 -460
  43. package/dist/markdown-BprL96Gl.js +45 -0
  44. package/dist/markdown.d.ts +3 -18
  45. package/dist/markdown.js +3 -14
  46. package/dist/message-vhUI0c5G.d.ts +16 -0
  47. package/dist/nav.d.ts +6 -8
  48. package/dist/nav.js +29 -11
  49. package/dist/openui-artifact-renderer-D3E5bIAI.d.ts +114 -0
  50. package/dist/openui-artifact-renderer-DT4xbvWt.js +266 -0
  51. package/dist/openui.d.ts +2 -115
  52. package/dist/openui.js +2 -12
  53. package/dist/parts-5mhy9yJ3.d.ts +37 -0
  54. package/dist/primitives-DE-blUz-.js +1239 -0
  55. package/dist/primitives.d.ts +5 -523
  56. package/dist/primitives.js +9 -211
  57. package/dist/redaction-CGGB2ENG.js +74 -0
  58. package/dist/redaction.d.ts +2 -42
  59. package/dist/redaction.js +2 -7
  60. package/dist/run-OyWmIDqu.d.ts +41 -0
  61. package/dist/run-ZsIKPA6J.js +17 -0
  62. package/dist/run-group-D1InSdQu.js +410 -0
  63. package/dist/run.d.ts +3 -126
  64. package/dist/run.js +5 -39
  65. package/dist/sdk-hooks.d.ts +2 -285
  66. package/dist/sdk-hooks.js +3 -35
  67. package/dist/stores.d.ts +13 -14
  68. package/dist/stores.js +34 -76
  69. package/dist/table-DHyqDPbU.js +146 -0
  70. package/dist/tabs-ujuqAdtb.js +40 -0
  71. package/dist/text-shimmer-BUUo6I-g.js +64 -0
  72. package/dist/tool-call-feed-BeB1_4pX.d.ts +47 -0
  73. package/dist/tool-call-feed-C1W1N54c.js +109 -0
  74. package/dist/tool-call-step-Bi3_YJRV.js +434 -0
  75. package/dist/tool-display-BAuAVa43.js +158 -0
  76. package/dist/{tool-display-z4JcDmMQ.d.ts → tool-display-DgmL5rIU.d.ts} +16 -16
  77. package/dist/tool-previews.d.ts +2 -48
  78. package/dist/tool-previews.js +2 -22
  79. package/dist/types.d.ts +6 -19
  80. package/dist/types.js +0 -1
  81. package/dist/use-auto-scroll-C5Pjeqon.js +153 -0
  82. package/dist/use-sse-stream-BjVBDbxK.js +884 -0
  83. package/dist/use-sse-stream-Dm6R5YWz.d.ts +282 -0
  84. package/dist/utils-Bl_CZ0Qp.js +37 -0
  85. package/dist/{chunk-RQHJBTEU.js → utils-C_uf36nf.js} +4 -6
  86. package/dist/utils.d.ts +2 -51
  87. package/dist/utils.js +6 -32
  88. package/package.json +39 -41
  89. package/src/auth/auth.tsx +5 -1
  90. package/src/chat/agent-timeline.tsx +6 -1
  91. package/src/chat/chat-container.tsx +2 -1
  92. package/src/editor/document-editor-pane.test.tsx +3 -1
  93. package/src/editor/document-editor-pane.tsx +5 -1
  94. package/src/editor/markdown-document-editor.test.tsx +9 -4
  95. package/src/files/file-artifact-pane.tsx +3 -2
  96. package/src/files/file-preview.tsx +3 -1
  97. package/src/files/file-tabs.tsx +9 -2
  98. package/src/lib/focus.ts +63 -0
  99. package/src/markdown/code-block.tsx +5 -1
  100. package/src/primitives/badge.tsx +2 -1
  101. package/src/primitives/button.tsx +2 -1
  102. package/src/primitives/card.tsx +1 -2
  103. package/src/primitives/dialog.tsx +7 -1
  104. package/src/primitives/input.tsx +15 -14
  105. package/src/primitives/segmented-control.tsx +5 -3
  106. package/src/primitives/select.tsx +3 -1
  107. package/src/primitives/switch.tsx +3 -1
  108. package/src/primitives/tabs.tsx +6 -4
  109. package/src/primitives/terminal-display.tsx +6 -8
  110. package/src/primitives/toast.tsx +5 -1
  111. package/src/tool-previews/command-preview.tsx +5 -1
  112. package/src/tool-previews/web-search-preview.tsx +2 -1
  113. package/src/utils/index.ts +7 -0
  114. package/dist/artifact-pane-DpuWcAiF.d.ts +0 -33
  115. package/dist/button-CMQuQEW_.d.ts +0 -17
  116. package/dist/chunk-34A66VBG.js +0 -214
  117. package/dist/chunk-3OI2QKFD.js +0 -0
  118. package/dist/chunk-3TI5DEHV.js +0 -299
  119. package/dist/chunk-4CLN43XT.js +0 -45
  120. package/dist/chunk-565EATZZ.js +0 -156
  121. package/dist/chunk-5Z5ZYMOJ.js +0 -0
  122. package/dist/chunk-6BGQA4BQ.js +0 -0
  123. package/dist/chunk-7YOCS6IF.js +0 -728
  124. package/dist/chunk-EOAX2ENE.js +0 -60
  125. package/dist/chunk-GYPQXTJU.js +0 -230
  126. package/dist/chunk-HFL6R6IF.js +0 -37
  127. package/dist/chunk-HGML45QH.js +0 -104
  128. package/dist/chunk-KNYSKNZX.js +0 -550
  129. package/dist/chunk-L57WRIND.js +0 -59
  130. package/dist/chunk-LDLOJKPC.js +0 -1585
  131. package/dist/chunk-LTEKI7YJ.js +0 -59
  132. package/dist/chunk-MKTSMWVD.js +0 -109
  133. package/dist/chunk-ND3ZFXQK.js +0 -179
  134. package/dist/chunk-NKDZ7GZE.js +0 -192
  135. package/dist/chunk-NWECTSOH.js +0 -589
  136. package/dist/chunk-OEX7NZE3.js +0 -321
  137. package/dist/chunk-Q56BYXQF.js +0 -61
  138. package/dist/chunk-REJESC5U.js +0 -117
  139. package/dist/chunk-RQGKSCEZ.js +0 -0
  140. package/dist/chunk-TN4FUEWY.js +0 -437
  141. package/dist/chunk-VPWY4I5O.js +0 -1048
  142. package/dist/chunk-WUQDUBJG.js +0 -168
  143. package/dist/chunk-XGKULLYE.js +0 -40
  144. package/dist/chunk-XU3HB5QL.js +0 -127
  145. package/dist/chunk-XYAIX4SU.js +0 -133
  146. package/dist/chunk-YJ6RE5WV.js +0 -875
  147. package/dist/chunk-YTO5V6QS.js +0 -19
  148. package/dist/chunk-ZKCEAIIZ.js +0 -1395
  149. package/dist/code-block-0kSpWMnf.d.ts +0 -25
  150. package/dist/document-editor-pane-EX25CEYW.js +0 -12
  151. package/dist/document-editor-pane-IAEQn_Dl.d.ts +0 -128
  152. package/dist/message-BHWbxBtT.d.ts +0 -15
  153. package/dist/parts-dj7AcUg0.d.ts +0 -36
  154. package/dist/run-PfLmDAox.d.ts +0 -41
  155. package/dist/tool-call-feed-D9iofJgW.d.ts +0 -46
@@ -1,728 +0,0 @@
1
- import {
2
- useAutoScroll,
3
- useRunCollapseState,
4
- useRunGroups
5
- } from "./chunk-565EATZZ.js";
6
- import {
7
- InlineThinkingItem,
8
- RunGroup
9
- } from "./chunk-TN4FUEWY.js";
10
- import {
11
- ToolCallGroup,
12
- ToolCallStep
13
- } from "./chunk-KNYSKNZX.js";
14
- import {
15
- getToolDisplayMetadata
16
- } from "./chunk-ND3ZFXQK.js";
17
- import {
18
- OpenUIArtifactRenderer
19
- } from "./chunk-3TI5DEHV.js";
20
- import {
21
- Markdown
22
- } from "./chunk-EOAX2ENE.js";
23
- import {
24
- cn
25
- } from "./chunk-RQHJBTEU.js";
26
-
27
- // src/chat/chat-container.tsx
28
- import {
29
- memo as memo3,
30
- useMemo,
31
- useRef
32
- } from "react";
33
- import { ArrowDown } from "lucide-react";
34
-
35
- // src/chat/message-list.tsx
36
- import { memo as memo2 } from "react";
37
-
38
- // src/chat/user-message.tsx
39
- import { memo } from "react";
40
- import { jsx, jsxs } from "react/jsx-runtime";
41
- function formatTime(date) {
42
- return date.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
43
- }
44
- var UserMessage = memo(
45
- ({ message: _message, parts, content, timestamp, actions }) => {
46
- const text = content ?? (parts ?? []).filter((p) => p.type === "text").map((p) => p.text).join("\n");
47
- if (!text.trim()) return null;
48
- return /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs("div", { className: "group flex max-w-[78%] flex-col items-end gap-2", children: [
49
- /* @__PURE__ */ jsxs("div", { className: "relative w-full rounded-2xl bg-muted/50 px-4 py-3", children: [
50
- timestamp ? /* @__PURE__ */ jsx(
51
- "span",
52
- {
53
- "data-user-message-time": "",
54
- className: "pointer-events-none absolute right-full top-1/2 mr-3 -translate-y-1/2 whitespace-nowrap text-[var(--font-size-xs)] text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100",
55
- children: formatTime(timestamp)
56
- }
57
- ) : null,
58
- /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap text-[var(--font-size-base)] leading-[1.5] text-foreground", children: text })
59
- ] }),
60
- actions ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center justify-end gap-1.5 text-xs text-muted-foreground", children: actions }) : null
61
- ] }) });
62
- }
63
- );
64
- UserMessage.displayName = "UserMessage";
65
-
66
- // src/chat/message-list.tsx
67
- import { jsx as jsx2 } from "react/jsx-runtime";
68
- var MessageList = memo2(
69
- ({
70
- groups,
71
- partMap,
72
- isCollapsed,
73
- onToggleCollapse,
74
- branding,
75
- renderToolDetail,
76
- renderRunActions,
77
- renderUserMessageActions,
78
- renderToolActions
79
- }) => {
80
- return /* @__PURE__ */ jsx2("div", { className: "space-y-4", children: groups.map((group) => {
81
- if (group.type === "user") {
82
- const messageParts = partMap[group.message.id] ?? [];
83
- return /* @__PURE__ */ jsx2(
84
- UserMessage,
85
- {
86
- message: group.message,
87
- parts: messageParts,
88
- actions: renderUserMessageActions?.(group.message, messageParts)
89
- },
90
- group.message.id
91
- );
92
- }
93
- return /* @__PURE__ */ jsx2(
94
- RunGroup,
95
- {
96
- run: group.run,
97
- partMap,
98
- collapsed: isCollapsed(group.run.id),
99
- onToggle: () => onToggleCollapse(group.run.id),
100
- branding,
101
- renderToolDetail,
102
- headerActions: renderRunActions?.(group.run),
103
- renderToolActions
104
- },
105
- group.run.id
106
- );
107
- }) });
108
- }
109
- );
110
- MessageList.displayName = "MessageList";
111
-
112
- // src/chat/agent-timeline.tsx
113
- import { useState as useState2 } from "react";
114
- import {
115
- AlertTriangle,
116
- CheckCircle2,
117
- CircleDot,
118
- FileText,
119
- Info
120
- } from "lucide-react";
121
-
122
- // src/chat/thinking-indicator.tsx
123
- import { useEffect, useState } from "react";
124
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
125
- function ThinkingIndicator({ className }) {
126
- const [elapsed, setElapsed] = useState(0);
127
- useEffect(() => {
128
- const interval = window.setInterval(() => setElapsed((current) => current + 1), 1e3);
129
- return () => window.clearInterval(interval);
130
- }, []);
131
- return /* @__PURE__ */ jsxs2(
132
- "div",
133
- {
134
- role: "status",
135
- "aria-label": "Agent is thinking",
136
- className: cn("flex items-center gap-2 px-3 py-1.5", className),
137
- children: [
138
- /* @__PURE__ */ jsxs2("div", { className: "flex gap-[3px]", children: [
139
- /* @__PURE__ */ jsx3("span", { className: "h-[var(--indicator-dot-size)] w-[var(--indicator-dot-size)] animate-bounce rounded-full bg-[var(--brand-glow)]", style: { animationDelay: "0ms" } }),
140
- /* @__PURE__ */ jsx3("span", { className: "h-[var(--indicator-dot-size)] w-[var(--indicator-dot-size)] animate-bounce rounded-full bg-[var(--brand-glow)]", style: { animationDelay: "150ms" } }),
141
- /* @__PURE__ */ jsx3("span", { className: "h-[var(--indicator-dot-size)] w-[var(--indicator-dot-size)] animate-bounce rounded-full bg-[var(--brand-glow)]", style: { animationDelay: "300ms" } })
142
- ] }),
143
- elapsed > 3 && /* @__PURE__ */ jsxs2("span", { className: "text-[var(--font-size-xs)] tabular-nums text-muted-foreground", children: [
144
- elapsed,
145
- "s"
146
- ] })
147
- ]
148
- }
149
- );
150
- }
151
-
152
- // src/chat/agent-timeline.tsx
153
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
154
- var TONE_STYLES = {
155
- default: {
156
- card: "border-border bg-card",
157
- text: "text-foreground",
158
- icon: CircleDot
159
- },
160
- info: {
161
- card: "border-[var(--surface-info-border)] bg-[var(--surface-info-bg)]",
162
- text: "text-[var(--surface-info-text)]",
163
- icon: Info
164
- },
165
- success: {
166
- card: "border-[var(--surface-success-border)] bg-[var(--surface-success-bg)]",
167
- text: "text-[var(--surface-success-text)]",
168
- icon: CheckCircle2
169
- },
170
- warning: {
171
- card: "border-[var(--surface-warning-border)] bg-[var(--surface-warning-bg)]",
172
- text: "text-[var(--surface-warning-text)]",
173
- icon: AlertTriangle
174
- },
175
- error: {
176
- card: "border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)]",
177
- text: "text-[var(--surface-danger-text)]",
178
- icon: AlertTriangle
179
- }
180
- };
181
- function stepKind(item) {
182
- if (item.kind === "message") return item.role === "user" ? "user" : "prose";
183
- if (item.kind === "status" || item.kind === "artifact") return "card";
184
- return "tool";
185
- }
186
- function spacingBefore(prev, next) {
187
- if (prev === void 0) return "";
188
- if (prev === "user" || next === "user") return "mt-4";
189
- if (prev === "card" || next === "card") return "mt-2";
190
- if (prev === "tool" || next === "tool") return "mt-1";
191
- return "mt-3";
192
- }
193
- var ROW_BLEED = "-mx-3";
194
- function AssistantMessage({ item }) {
195
- return /* @__PURE__ */ jsxs3("div", { children: [
196
- item.content && /* @__PURE__ */ jsx4(Markdown, { className: "tangle-prose text-[var(--font-size-base)] leading-[1.5]", children: item.content }),
197
- item.isStreaming && /* @__PURE__ */ jsx4(
198
- "span",
199
- {
200
- "aria-hidden": true,
201
- "data-streaming-caret": "",
202
- className: "ml-0.5 inline-block h-[1em] w-0.5 animate-pulse rounded-full bg-muted-foreground align-text-bottom"
203
- }
204
- ),
205
- item.toolCalls && /* @__PURE__ */ jsx4("div", { className: "mt-1", children: item.toolCalls }),
206
- item.after && /* @__PURE__ */ jsx4("div", { className: "mt-3 border-t border-border pt-3", children: item.after })
207
- ] });
208
- }
209
- function StatusCard({ item }) {
210
- const tone = TONE_STYLES[item.tone ?? "default"];
211
- const Icon = tone.icon;
212
- return /* @__PURE__ */ jsx4("div", { className: cn("rounded-[var(--radius-lg)] border px-4 py-3", tone.card), children: /* @__PURE__ */ jsxs3("div", { className: "flex items-start gap-3", children: [
213
- /* @__PURE__ */ jsx4(Icon, { className: cn("mt-0.5 h-4 w-4 shrink-0", tone.text) }),
214
- /* @__PURE__ */ jsxs3("div", { className: "min-w-0", children: [
215
- /* @__PURE__ */ jsx4("div", { className: cn("text-sm font-medium", tone.text), children: item.label }),
216
- item.detail && /* @__PURE__ */ jsx4("div", { className: "mt-0.5 text-sm text-muted-foreground", children: item.detail })
217
- ] })
218
- ] }) });
219
- }
220
- function ArtifactCard({ item }) {
221
- const tone = TONE_STYLES[item.tone ?? "default"];
222
- const content = /* @__PURE__ */ jsx4("div", { className: cn("rounded-[var(--radius-lg)] border px-4 py-3", tone.card), children: /* @__PURE__ */ jsxs3("div", { className: "flex items-start gap-3", children: [
223
- /* @__PURE__ */ jsx4("div", { className: "mt-0.5 flex h-[var(--avatar-size)] w-[var(--avatar-size)] shrink-0 items-center justify-center rounded-[var(--radius-md)] bg-muted/50 text-foreground", children: item.icon ?? /* @__PURE__ */ jsx4(FileText, { className: "h-4 w-4" }) }),
224
- /* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
225
- /* @__PURE__ */ jsx4("div", { className: "text-sm font-medium text-foreground", children: item.title }),
226
- item.description && /* @__PURE__ */ jsx4("div", { className: "mt-1 text-sm text-muted-foreground", children: item.description }),
227
- item.meta && /* @__PURE__ */ jsx4("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-xs text-muted-foreground", children: item.meta })
228
- ] }),
229
- item.action && /* @__PURE__ */ jsx4("div", { className: "shrink-0", children: item.action })
230
- ] }) });
231
- if (!item.onClick) return content;
232
- return /* @__PURE__ */ jsx4(
233
- "div",
234
- {
235
- role: "button",
236
- tabIndex: 0,
237
- onClick: item.onClick,
238
- onKeyDown: (event) => {
239
- if (event.key === "Enter" || event.key === " ") {
240
- event.preventDefault();
241
- item.onClick?.();
242
- }
243
- },
244
- className: "block w-full text-left transition-transform hover:-translate-y-0.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60",
245
- children: content
246
- }
247
- );
248
- }
249
- function AgentTimeline({
250
- items,
251
- isThinking,
252
- emptyState,
253
- className,
254
- renderToolActions,
255
- collapseAfter
256
- }) {
257
- const [expanded, setExpanded] = useState2(false);
258
- if (items.length === 0 && !isThinking) {
259
- return emptyState ? /* @__PURE__ */ jsx4("div", { className: cn("flex h-full items-center justify-center p-4", className), children: emptyState }) : null;
260
- }
261
- const renderedItems = isThinking ? [...items, { id: "__thinking__", kind: "custom", content: /* @__PURE__ */ jsx4(ThinkingIndicator, {}) }] : items;
262
- const isUserMessage = (item) => item.kind === "message" && item.role === "user";
263
- const stepItems = renderedItems.filter((item) => !isUserMessage(item));
264
- const limit = collapseAfter ?? Infinity;
265
- const collapsible = stepItems.length > limit;
266
- const collapsed = collapsible && !expanded;
267
- let renderList = renderedItems;
268
- let hiddenCount = 0;
269
- if (collapsed) {
270
- const visible = [];
271
- let stepCount = 0;
272
- for (const item of renderedItems) {
273
- if (stepCount >= limit) break;
274
- visible.push(item);
275
- if (!isUserMessage(item)) stepCount += 1;
276
- }
277
- renderList = visible;
278
- hiddenCount = stepItems.length - limit;
279
- }
280
- const renderItem = (item) => {
281
- if (item.kind === "message") {
282
- return item.role === "user" ? /* @__PURE__ */ jsx4(UserMessage, { content: item.content, timestamp: item.timestamp }) : /* @__PURE__ */ jsx4(AssistantMessage, { item });
283
- }
284
- if (item.kind === "tool") {
285
- return /* @__PURE__ */ jsx4(
286
- ToolCallStep,
287
- {
288
- type: item.call.type,
289
- label: item.call.label,
290
- status: item.call.status,
291
- detail: item.call.detail,
292
- output: item.call.output,
293
- duration: item.call.duration,
294
- part: item.part,
295
- actions: item.part ? renderToolActions?.(item.part) : void 0
296
- }
297
- );
298
- }
299
- if (item.kind === "tool_group") {
300
- return /* @__PURE__ */ jsx4(ToolCallGroup, { title: item.title, children: item.calls.map((call, callIndex) => {
301
- const part = item.parts?.[callIndex];
302
- return /* @__PURE__ */ jsx4(
303
- ToolCallStep,
304
- {
305
- type: call.type,
306
- label: call.label,
307
- status: call.status,
308
- detail: call.detail,
309
- output: call.output,
310
- duration: call.duration,
311
- part,
312
- actions: part ? renderToolActions?.(part) : void 0
313
- },
314
- call.id
315
- );
316
- }) });
317
- }
318
- if (item.kind === "status") return /* @__PURE__ */ jsx4(StatusCard, { item });
319
- if (item.kind === "artifact") return /* @__PURE__ */ jsx4(ArtifactCard, { item });
320
- return item.content;
321
- };
322
- return /* @__PURE__ */ jsxs3("div", { className: cn("mx-auto flex w-full max-w-5xl flex-col px-4 py-4", className), children: [
323
- renderList.map((item, index) => {
324
- const kind = stepKind(item);
325
- const prev = index > 0 ? stepKind(renderList[index - 1]) : void 0;
326
- return /* @__PURE__ */ jsx4(
327
- "div",
328
- {
329
- "data-timeline-step": kind,
330
- className: cn(spacingBefore(prev, kind), kind === "tool" && ROW_BLEED),
331
- children: renderItem(item)
332
- },
333
- item.id
334
- );
335
- }),
336
- collapsible ? /* @__PURE__ */ jsx4(
337
- "button",
338
- {
339
- type: "button",
340
- onClick: () => setExpanded((value) => !value),
341
- className: "mt-2 self-start text-xs font-medium text-muted-foreground transition-colors hover:text-foreground",
342
- children: collapsed ? `Show ${hiddenCount} more step${hiddenCount === 1 ? "" : "s"}` : "Show less"
343
- }
344
- ) : null
345
- ] });
346
- }
347
-
348
- // src/chat/chat-container.tsx
349
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
350
- var OPENUI_NODE_TYPES = /* @__PURE__ */ new Set([
351
- "heading",
352
- "text",
353
- "badge",
354
- "stat",
355
- "key_value",
356
- "code",
357
- "markdown",
358
- "table",
359
- "actions",
360
- "separator",
361
- "stack",
362
- "grid",
363
- "card"
364
- ]);
365
- function isOpenUINode(value) {
366
- return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string" && OPENUI_NODE_TYPES.has(value.type);
367
- }
368
- function extractOpenUISchema(output) {
369
- if (output == null) return null;
370
- if (isOpenUINode(output)) return [output];
371
- if (Array.isArray(output) && output.length > 0 && output.every(isOpenUINode)) {
372
- return output;
373
- }
374
- if (typeof output === "object" && !Array.isArray(output)) {
375
- const obj = output;
376
- for (const key of ["openui", "schema", "ui"]) {
377
- if (obj[key]) {
378
- const inner = obj[key];
379
- if (isOpenUINode(inner)) return [inner];
380
- if (Array.isArray(inner) && inner.length > 0 && inner.every(isOpenUINode)) {
381
- return inner;
382
- }
383
- }
384
- }
385
- }
386
- if (typeof output === "string") {
387
- try {
388
- const parsed = JSON.parse(output);
389
- return extractOpenUISchema(parsed);
390
- } catch {
391
- return null;
392
- }
393
- }
394
- return null;
395
- }
396
- function formatUnknown(value) {
397
- if (value == null) return void 0;
398
- if (typeof value === "string") return value;
399
- try {
400
- return JSON.stringify(value, null, 2);
401
- } catch {
402
- return String(value);
403
- }
404
- }
405
- function createdAtFromMessage(message) {
406
- return message.time?.created ? new Date(message.time.created) : void 0;
407
- }
408
- function mapToolPartToTimelineType(part) {
409
- const name = part.tool.toLowerCase().replace(/^tool:/, "");
410
- switch (name) {
411
- case "bash":
412
- case "shell":
413
- case "command":
414
- case "execute":
415
- return "bash";
416
- case "write":
417
- case "write_file":
418
- case "create_file":
419
- return "write";
420
- case "read":
421
- case "read_file":
422
- case "cat":
423
- return "read";
424
- case "edit":
425
- case "patch":
426
- case "sed":
427
- return "edit";
428
- case "glob":
429
- case "find":
430
- return "glob";
431
- case "ls":
432
- return "list";
433
- case "grep":
434
- case "search":
435
- case "rg":
436
- return "grep";
437
- case "inspect":
438
- return "inspect";
439
- default:
440
- return "unknown";
441
- }
442
- }
443
- function buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enableOpenUI = true) {
444
- const items = [];
445
- let latestUserIndex = -1;
446
- for (let index = messages.length - 1; index >= 0; index -= 1) {
447
- if (messages[index].role === "user") {
448
- latestUserIndex = index;
449
- break;
450
- }
451
- }
452
- const responseMessages = latestUserIndex >= 0 ? messages.slice(latestUserIndex + 1) : messages;
453
- const lastAssistantMessage = [...responseMessages].reverse().find((message) => message.role === "assistant");
454
- const toToolCall = (part) => {
455
- const meta = getToolDisplayMetadata(part);
456
- const start = part.state.time?.start;
457
- const end = part.state.time?.end;
458
- return {
459
- id: part.id,
460
- type: mapToolPartToTimelineType(part),
461
- label: meta.title,
462
- status: part.state.status === "completed" ? "success" : part.state.status === "error" ? "error" : "running",
463
- // A human-readable summary (file path / command), not the raw input JSON —
464
- // the full input still renders in the expanded ExpandedToolDetail.
465
- detail: meta.commandSnippet ?? meta.targetPath ?? meta.description,
466
- output: formatUnknown(part.state.output),
467
- duration: start && end ? end - start : void 0
468
- };
469
- };
470
- for (const message of messages) {
471
- const parts = partMap[message.id] ?? [];
472
- if (message.role === "user") {
473
- const content = parts.filter((part) => part.type === "text").map((part) => part.text).join("\n").trim();
474
- if (!content) continue;
475
- items.push({
476
- id: message.id,
477
- kind: "message",
478
- role: "user",
479
- content,
480
- timestamp: createdAtFromMessage(message)
481
- });
482
- continue;
483
- }
484
- const toolBuffer = [];
485
- const flushToolBuffer = (index) => {
486
- if (toolBuffer.length === 0) return;
487
- if (toolBuffer.length === 1) {
488
- items.push({
489
- id: `${message.id}-tool-${toolBuffer[0].id}`,
490
- kind: "tool",
491
- call: toToolCall(toolBuffer[0]),
492
- part: toolBuffer[0]
493
- });
494
- } else {
495
- items.push({
496
- id: `${message.id}-tool-group-${index}`,
497
- kind: "tool_group",
498
- title: "Tool activity",
499
- parts: [...toolBuffer],
500
- calls: toolBuffer.map((part) => toToolCall(part))
501
- });
502
- }
503
- if (enableOpenUI) {
504
- for (const part of toolBuffer) {
505
- if (part.state.status !== "completed" || !part.state.output) continue;
506
- const schema = extractOpenUISchema(part.state.output);
507
- if (!schema) continue;
508
- items.push({
509
- id: `${message.id}-openui-${part.id}`,
510
- kind: "custom",
511
- content: /* @__PURE__ */ jsx5("div", { className: "my-2 rounded-[var(--radius-lg)] border border-border bg-card p-4 shadow-[var(--shadow-card)]", children: /* @__PURE__ */ jsx5(OpenUIArtifactRenderer, { schema, onAction: onOpenUIAction }) })
512
- });
513
- }
514
- }
515
- toolBuffer.length = 0;
516
- };
517
- parts.forEach((part, index) => {
518
- const itemId = `${message.id}-${index}`;
519
- if (part.type === "tool") {
520
- toolBuffer.push(part);
521
- return;
522
- }
523
- flushToolBuffer(index);
524
- if (part.type === "text" && !part.synthetic && part.text.trim()) {
525
- if (enableOpenUI) {
526
- const jsonMatch = part.text.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);
527
- if (jsonMatch) {
528
- const schema = extractOpenUISchema(jsonMatch[1]);
529
- if (schema) {
530
- const beforeJson = part.text.slice(0, part.text.indexOf("```")).trim();
531
- if (beforeJson) {
532
- items.push({
533
- id: `${itemId}-text`,
534
- kind: "message",
535
- role: "assistant",
536
- content: beforeJson,
537
- timestamp: createdAtFromMessage(message)
538
- });
539
- }
540
- items.push({
541
- id: `${itemId}-openui`,
542
- kind: "custom",
543
- content: /* @__PURE__ */ jsx5("div", { className: "my-2 rounded-[var(--radius-lg)] border border-border bg-card p-4 shadow-[var(--shadow-card)]", children: /* @__PURE__ */ jsx5(OpenUIArtifactRenderer, { schema, onAction: onOpenUIAction }) })
544
- });
545
- const afterJson = part.text.slice(part.text.lastIndexOf("```") + 3).trim();
546
- if (afterJson) {
547
- items.push({
548
- id: `${itemId}-after`,
549
- kind: "message",
550
- role: "assistant",
551
- content: afterJson,
552
- timestamp: createdAtFromMessage(message)
553
- });
554
- }
555
- return;
556
- }
557
- }
558
- }
559
- items.push({
560
- id: itemId,
561
- kind: "message",
562
- role: "assistant",
563
- content: part.text,
564
- timestamp: createdAtFromMessage(message),
565
- isStreaming: isStreaming && lastAssistantMessage?.id === message.id && index === parts.length - 1
566
- });
567
- return;
568
- }
569
- if (part.type === "reasoning") {
570
- items.push({
571
- id: itemId,
572
- kind: "custom",
573
- content: /* @__PURE__ */ jsx5(InlineThinkingItem, { part, defaultOpen: isStreaming && lastAssistantMessage?.id === message.id })
574
- });
575
- return;
576
- }
577
- });
578
- flushToolBuffer(parts.length);
579
- }
580
- const showThinking = isStreaming && latestUserIndex >= 0 && (lastAssistantMessage == null || !items.some(
581
- (item) => item.kind === "message" && item.role === "assistant" && item.id.startsWith(lastAssistantMessage.id)
582
- ));
583
- return { items, showThinking };
584
- }
585
- var ChatContainer = memo3(
586
- ({
587
- messages,
588
- partMap,
589
- isStreaming,
590
- branding,
591
- className,
592
- renderToolDetail,
593
- presentation = "runs",
594
- onOpenUIAction,
595
- enableOpenUI = true,
596
- renderRunActions,
597
- renderUserMessageActions,
598
- renderToolActions,
599
- renderTimelineToolActions,
600
- collapseTimelineAfter
601
- }) => {
602
- const scrollRef = useRef(null);
603
- const groups = useRunGroups({ messages, partMap, isStreaming });
604
- const runs = groups.filter((g) => g.type === "run").map((g) => g.run);
605
- const { isCollapsed, toggleCollapse } = useRunCollapseState(runs);
606
- const { isAtBottom, scrollToBottom } = useAutoScroll(scrollRef, [
607
- messages,
608
- partMap,
609
- isStreaming
610
- ]);
611
- const timeline = useMemo(
612
- () => buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enableOpenUI),
613
- [messages, partMap, isStreaming, onOpenUIAction, enableOpenUI]
614
- );
615
- return /* @__PURE__ */ jsxs4("div", { className: cn("flex h-full flex-col", className), children: [
616
- /* @__PURE__ */ jsx5(
617
- "div",
618
- {
619
- ref: scrollRef,
620
- className: "flex-1 overflow-y-auto [scrollbar-gutter:stable]",
621
- children: messages.length === 0 ? /* @__PURE__ */ jsx5("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx5("div", { className: "max-w-md text-center", children: /* @__PURE__ */ jsx5("div", { className: "text-sm font-medium text-muted-foreground", children: "Start a conversation." }) }) }) : presentation === "timeline" ? /* @__PURE__ */ jsx5("div", { className: "mx-auto flex min-h-full w-full max-w-3xl flex-col justify-end", children: /* @__PURE__ */ jsx5(
622
- AgentTimeline,
623
- {
624
- items: timeline.items,
625
- isThinking: timeline.showThinking,
626
- renderToolActions: renderTimelineToolActions,
627
- collapseAfter: collapseTimelineAfter
628
- }
629
- ) }) : /* @__PURE__ */ jsx5("div", { className: "mx-auto flex min-h-full w-full max-w-3xl flex-col justify-end", children: /* @__PURE__ */ jsx5(
630
- MessageList,
631
- {
632
- groups,
633
- partMap,
634
- isCollapsed,
635
- onToggleCollapse: toggleCollapse,
636
- branding,
637
- renderToolDetail,
638
- renderRunActions,
639
- renderUserMessageActions,
640
- renderToolActions
641
- }
642
- ) })
643
- }
644
- ),
645
- !isAtBottom && /* @__PURE__ */ jsx5("div", { className: "relative z-10 -mt-10 flex justify-center", children: /* @__PURE__ */ jsxs4(
646
- "button",
647
- {
648
- onClick: scrollToBottom,
649
- className: cn(
650
- "flex items-center gap-1.5 px-3 py-1.5 rounded-full",
651
- "border border-border bg-card shadow-[0_6px_16px_rgba(15,23,42,0.08)]",
652
- "text-xs text-foreground transition-colors hover:bg-accent",
653
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60"
654
- ),
655
- children: [
656
- /* @__PURE__ */ jsx5(ArrowDown, { className: "w-3 h-3" }),
657
- "Scroll to bottom"
658
- ]
659
- }
660
- ) })
661
- ] });
662
- }
663
- );
664
- ChatContainer.displayName = "ChatContainer";
665
-
666
- // src/chat/chat-message.tsx
667
- import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
668
- function ChatMessage({
669
- role,
670
- content,
671
- toolCalls,
672
- isStreaming,
673
- timestamp,
674
- className,
675
- userLabel = "You",
676
- assistantLabel = "Agent",
677
- hideRoleLabel
678
- }) {
679
- const isUser = role === "user";
680
- return /* @__PURE__ */ jsxs5(
681
- "div",
682
- {
683
- className: cn(
684
- "flex flex-col gap-1",
685
- isUser ? "items-end" : "items-start",
686
- className
687
- ),
688
- children: [
689
- !hideRoleLabel && /* @__PURE__ */ jsxs5("div", { className: cn("flex items-center gap-2 px-1", isUser && "flex-row-reverse"), children: [
690
- /* @__PURE__ */ jsx6("span", { className: "font-medium text-foreground text-xs", children: isUser ? userLabel : assistantLabel }),
691
- timestamp && /* @__PURE__ */ jsx6("span", { className: "text-muted-foreground text-xs", children: formatTime2(timestamp) })
692
- ] }),
693
- /* @__PURE__ */ jsxs5(
694
- "div",
695
- {
696
- className: cn(
697
- "min-w-0 max-w-[85%] space-y-1 rounded-[var(--radius-lg)] border",
698
- "px-[var(--chat-message-px)] py-[var(--chat-message-py)]",
699
- isUser ? "border-border bg-muted/50" : "border-border bg-card"
700
- ),
701
- children: [
702
- isUser ? /* @__PURE__ */ jsx6("div", { className: "whitespace-pre-wrap text-[var(--font-size-base)] leading-[var(--line-height-base)] text-foreground", children: content }) : /* @__PURE__ */ jsxs5(Fragment, { children: [
703
- content && /* @__PURE__ */ jsx6(Markdown, { className: "tangle-prose text-[var(--font-size-base)] leading-[var(--line-height-base)]", children: content }),
704
- isStreaming && /* @__PURE__ */ jsx6("span", { className: "ml-0.5 inline-block h-4 w-2 animate-pulse rounded-sm bg-[var(--brand-cool)] align-text-bottom" })
705
- ] }),
706
- toolCalls
707
- ]
708
- }
709
- )
710
- ]
711
- }
712
- );
713
- }
714
- function formatTime2(date) {
715
- return date.toLocaleTimeString(void 0, {
716
- hour: "numeric",
717
- minute: "2-digit"
718
- });
719
- }
720
-
721
- export {
722
- UserMessage,
723
- MessageList,
724
- ThinkingIndicator,
725
- AgentTimeline,
726
- ChatContainer,
727
- ChatMessage
728
- };