@tangle-network/ui 11.10.0 → 11.11.1

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