@tangle-network/ui 7.0.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/chat.d.ts +17 -72
- package/dist/chat.js +2 -4
- package/dist/{chunk-QIRVZMQY.js → chunk-C3BIVG72.js} +143 -107
- package/dist/{chunk-5CS3I7Y3.js → chunk-QUAU6ZNC.js} +111 -395
- package/dist/hooks.d.ts +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -9
- package/dist/run.d.ts +30 -2
- package/dist/run.js +4 -6
- package/dist/sdk-hooks.d.ts +1 -1
- package/dist/{tool-call-feed-Bs3MyQMT.d.ts → tool-call-feed-D9iofJgW.d.ts} +1 -23
- package/package.json +2 -2
- package/src/chat/agent-timeline.tsx +139 -45
- package/src/chat/chat-container.tsx +6 -48
- package/src/chat/chat-message.tsx +0 -4
- package/src/chat/index.ts +0 -1
- package/src/markdown/markdown.stories.tsx +1 -1
- package/src/run/assistant-run-shell.tsx +115 -0
- package/src/run/index.ts +5 -1
- package/src/run/run-group.tsx +12 -76
- package/src/run/tool-call-step.tsx +5 -7
- package/src/chat/chat-input.stories.tsx +0 -142
- package/src/chat/chat-input.tsx +0 -389
|
@@ -4,9 +4,10 @@ import {
|
|
|
4
4
|
useRunGroups
|
|
5
5
|
} from "./chunk-AZWDI2JG.js";
|
|
6
6
|
import {
|
|
7
|
+
AssistantRunShell,
|
|
7
8
|
InlineThinkingItem,
|
|
8
9
|
RunGroup
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-C3BIVG72.js";
|
|
10
11
|
import {
|
|
11
12
|
ToolCallGroup,
|
|
12
13
|
ToolCallStep
|
|
@@ -27,9 +28,8 @@ import {
|
|
|
27
28
|
// src/chat/chat-container.tsx
|
|
28
29
|
import {
|
|
29
30
|
memo as memo3,
|
|
30
|
-
useCallback as useCallback2,
|
|
31
31
|
useMemo,
|
|
32
|
-
useRef
|
|
32
|
+
useRef
|
|
33
33
|
} from "react";
|
|
34
34
|
import { ArrowDown } from "lucide-react";
|
|
35
35
|
|
|
@@ -99,6 +99,7 @@ var MessageList = memo2(
|
|
|
99
99
|
MessageList.displayName = "MessageList";
|
|
100
100
|
|
|
101
101
|
// src/chat/agent-timeline.tsx
|
|
102
|
+
import { useState as useState2 } from "react";
|
|
102
103
|
import {
|
|
103
104
|
AlertTriangle,
|
|
104
105
|
CheckCircle2,
|
|
@@ -131,6 +132,48 @@ function ThinkingIndicator({ className }) {
|
|
|
131
132
|
|
|
132
133
|
// src/chat/agent-timeline.tsx
|
|
133
134
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
135
|
+
function foldToolRuns(items) {
|
|
136
|
+
const nodes = [];
|
|
137
|
+
let run = [];
|
|
138
|
+
const flush = () => {
|
|
139
|
+
if (run.length === 0) return;
|
|
140
|
+
if (run.length === 1) {
|
|
141
|
+
nodes.push(run[0]);
|
|
142
|
+
} else {
|
|
143
|
+
nodes.push({ id: `tool-run-${run[0].id}`, kind: "tool_run", items: run });
|
|
144
|
+
}
|
|
145
|
+
run = [];
|
|
146
|
+
};
|
|
147
|
+
for (const item of items) {
|
|
148
|
+
if (item.kind === "tool" || item.kind === "tool_group") {
|
|
149
|
+
run.push(item);
|
|
150
|
+
} else {
|
|
151
|
+
flush();
|
|
152
|
+
nodes.push(item);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
flush();
|
|
156
|
+
return nodes;
|
|
157
|
+
}
|
|
158
|
+
function countTools(group) {
|
|
159
|
+
return group.items.reduce(
|
|
160
|
+
(n, item) => n + (item.kind === "tool_group" ? item.calls.length : 1),
|
|
161
|
+
0
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
function ToolCallRow({ call }) {
|
|
165
|
+
return /* @__PURE__ */ jsx4(
|
|
166
|
+
ToolCallStep,
|
|
167
|
+
{
|
|
168
|
+
type: call.type,
|
|
169
|
+
label: call.label,
|
|
170
|
+
status: call.status,
|
|
171
|
+
detail: call.detail,
|
|
172
|
+
output: call.output,
|
|
173
|
+
duration: call.duration
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
}
|
|
134
177
|
var TONE_STYLES = {
|
|
135
178
|
default: {
|
|
136
179
|
dot: "bg-[var(--border-hover)]",
|
|
@@ -234,375 +277,81 @@ function AgentTimeline({
|
|
|
234
277
|
items,
|
|
235
278
|
isThinking,
|
|
236
279
|
emptyState,
|
|
237
|
-
className
|
|
280
|
+
className,
|
|
281
|
+
collapsibleToolRuns = true,
|
|
282
|
+
defaultToolRunsOpen = true
|
|
238
283
|
}) {
|
|
284
|
+
const [collapsedRuns, setCollapsedRuns] = useState2({});
|
|
285
|
+
const toggleRun = (id) => setCollapsedRuns((prev) => ({
|
|
286
|
+
...prev,
|
|
287
|
+
[id]: prev[id] === void 0 ? defaultToolRunsOpen : !prev[id]
|
|
288
|
+
}));
|
|
239
289
|
if (items.length === 0 && !isThinking) {
|
|
240
290
|
return emptyState ? /* @__PURE__ */ jsx4("div", { className: cn("flex h-full items-center justify-center p-4", className), children: emptyState }) : null;
|
|
241
291
|
}
|
|
242
292
|
const renderedItems = isThinking ? [...items, { id: "__thinking__", kind: "custom", content: /* @__PURE__ */ jsx4(ThinkingIndicator, {}) }] : items;
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if (item.kind === "message") {
|
|
251
|
-
return /* @__PURE__ */ jsx4(AgentTimelineRow, { isLast, accentClassName: "bg-[var(--brand-glow)]", children: /* @__PURE__ */ jsx4(AssistantMessage, { item }) }, item.id);
|
|
293
|
+
const nodes = collapsibleToolRuns ? foldToolRuns(renderedItems) : renderedItems;
|
|
294
|
+
const timelineNodes = nodes.filter(
|
|
295
|
+
(node) => !(node.kind === "message" && node.role === "user")
|
|
296
|
+
);
|
|
297
|
+
return /* @__PURE__ */ jsx4("div", { className: cn("mx-auto w-full max-w-5xl px-4 py-4", className), children: nodes.map((node) => {
|
|
298
|
+
if (node.kind === "message" && node.role === "user") {
|
|
299
|
+
return /* @__PURE__ */ jsx4(UserMessage2, { item: node }, node.id);
|
|
252
300
|
}
|
|
253
|
-
|
|
301
|
+
const isLast = timelineNodes.indexOf(node) === timelineNodes.length - 1;
|
|
302
|
+
if (node.kind === "tool_run") {
|
|
303
|
+
const collapsed = collapsedRuns[node.id] ?? !defaultToolRunsOpen;
|
|
304
|
+
const total = countTools(node);
|
|
254
305
|
return /* @__PURE__ */ jsx4(AgentTimelineRow, { isLast, accentClassName: "bg-[var(--border-hover)]", children: /* @__PURE__ */ jsx4(
|
|
255
|
-
|
|
306
|
+
AssistantRunShell,
|
|
256
307
|
{
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
308
|
+
label: "Tools",
|
|
309
|
+
summary: `${total} ${total === 1 ? "tool" : "tools"}`,
|
|
310
|
+
collapsed,
|
|
311
|
+
onToggle: () => toggleRun(node.id),
|
|
312
|
+
children: /* @__PURE__ */ jsx4("div", { className: "space-y-px", children: node.items.map(
|
|
313
|
+
(item) => item.kind === "tool_group" ? /* @__PURE__ */ jsx4(ToolCallGroup, { title: item.title, children: item.calls.map((call) => /* @__PURE__ */ jsx4(ToolCallRow, { call }, call.id)) }, item.id) : /* @__PURE__ */ jsx4(ToolCallRow, { call: item.call }, item.id)
|
|
314
|
+
) })
|
|
263
315
|
}
|
|
264
|
-
) },
|
|
316
|
+
) }, node.id);
|
|
265
317
|
}
|
|
266
|
-
if (
|
|
267
|
-
return /* @__PURE__ */ jsx4(AgentTimelineRow, { isLast, accentClassName: "bg-[var(--
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
label: call.label,
|
|
272
|
-
status: call.status,
|
|
273
|
-
detail: call.detail,
|
|
274
|
-
output: call.output,
|
|
275
|
-
duration: call.duration
|
|
276
|
-
},
|
|
277
|
-
call.id
|
|
278
|
-
)) }) }, item.id);
|
|
318
|
+
if (node.kind === "message") {
|
|
319
|
+
return /* @__PURE__ */ jsx4(AgentTimelineRow, { isLast, accentClassName: "bg-[var(--brand-glow)]", children: /* @__PURE__ */ jsx4(AssistantMessage, { item: node }) }, node.id);
|
|
320
|
+
}
|
|
321
|
+
if (node.kind === "tool") {
|
|
322
|
+
return /* @__PURE__ */ jsx4(AgentTimelineRow, { isLast, accentClassName: "bg-[var(--border-hover)]", children: /* @__PURE__ */ jsx4(ToolCallRow, { call: node.call }) }, node.id);
|
|
279
323
|
}
|
|
280
|
-
if (
|
|
324
|
+
if (node.kind === "tool_group") {
|
|
325
|
+
return /* @__PURE__ */ jsx4(AgentTimelineRow, { isLast, accentClassName: "bg-[var(--border-hover)]", children: /* @__PURE__ */ jsx4(ToolCallGroup, { title: node.title, children: node.calls.map((call) => /* @__PURE__ */ jsx4(ToolCallRow, { call }, call.id)) }) }, node.id);
|
|
326
|
+
}
|
|
327
|
+
if (node.kind === "status") {
|
|
281
328
|
return /* @__PURE__ */ jsx4(
|
|
282
329
|
AgentTimelineRow,
|
|
283
330
|
{
|
|
284
331
|
isLast,
|
|
285
|
-
accentClassName: TONE_STYLES[
|
|
286
|
-
children: /* @__PURE__ */ jsx4(StatusCard, { item })
|
|
332
|
+
accentClassName: TONE_STYLES[node.tone ?? "default"].dot,
|
|
333
|
+
children: /* @__PURE__ */ jsx4(StatusCard, { item: node })
|
|
287
334
|
},
|
|
288
|
-
|
|
335
|
+
node.id
|
|
289
336
|
);
|
|
290
337
|
}
|
|
291
|
-
if (
|
|
338
|
+
if (node.kind === "artifact") {
|
|
292
339
|
return /* @__PURE__ */ jsx4(
|
|
293
340
|
AgentTimelineRow,
|
|
294
341
|
{
|
|
295
342
|
isLast,
|
|
296
|
-
accentClassName: TONE_STYLES[
|
|
297
|
-
children: /* @__PURE__ */ jsx4(ArtifactCard, { item })
|
|
343
|
+
accentClassName: TONE_STYLES[node.tone ?? "default"].dot,
|
|
344
|
+
children: /* @__PURE__ */ jsx4(ArtifactCard, { item: node })
|
|
298
345
|
},
|
|
299
|
-
|
|
346
|
+
node.id
|
|
300
347
|
);
|
|
301
348
|
}
|
|
302
|
-
return /* @__PURE__ */ jsx4(AgentTimelineRow, { isLast, accentClassName: "bg-[var(--border-hover)]", children:
|
|
349
|
+
return /* @__PURE__ */ jsx4(AgentTimelineRow, { isLast, accentClassName: "bg-[var(--border-hover)]", children: node.content }, node.id);
|
|
303
350
|
}) });
|
|
304
351
|
}
|
|
305
352
|
|
|
306
|
-
// src/chat/chat-input.tsx
|
|
307
|
-
import { useState as useState2, useRef, useCallback } from "react";
|
|
308
|
-
import { Send, Square, Paperclip, FolderUp, X, Upload } from "lucide-react";
|
|
309
|
-
import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
310
|
-
function ChatInput({
|
|
311
|
-
onSend,
|
|
312
|
-
onCancel,
|
|
313
|
-
isStreaming,
|
|
314
|
-
disabled,
|
|
315
|
-
placeholder = "Ask the agent to inspect files, run commands, or explain results\u2026",
|
|
316
|
-
modelLabel,
|
|
317
|
-
onModelClick,
|
|
318
|
-
pendingFiles = [],
|
|
319
|
-
onRemoveFile,
|
|
320
|
-
onAttach,
|
|
321
|
-
onAttachFolder,
|
|
322
|
-
accept,
|
|
323
|
-
dropTitle = "Drop files to add context",
|
|
324
|
-
dropDescription = "Files will be attached to your next message.",
|
|
325
|
-
className,
|
|
326
|
-
inputLabel = "Agent Command Deck",
|
|
327
|
-
idleStatus = "Ready for next instruction",
|
|
328
|
-
streamingStatus = "Streaming response",
|
|
329
|
-
hideShortcutHint
|
|
330
|
-
}) {
|
|
331
|
-
const [value, setValue] = useState2("");
|
|
332
|
-
const [dragOver, setDragOver] = useState2(false);
|
|
333
|
-
const dragCounter = useRef(0);
|
|
334
|
-
const textareaRef = useRef(null);
|
|
335
|
-
const fileInputRef = useRef(null);
|
|
336
|
-
const folderInputRef = useRef(null);
|
|
337
|
-
const handleSend = useCallback(() => {
|
|
338
|
-
const trimmed = value.trim();
|
|
339
|
-
if (!trimmed || isStreaming || disabled) return;
|
|
340
|
-
onSend(trimmed);
|
|
341
|
-
setValue("");
|
|
342
|
-
if (textareaRef.current) {
|
|
343
|
-
textareaRef.current.style.height = "auto";
|
|
344
|
-
}
|
|
345
|
-
}, [value, isStreaming, disabled, onSend]);
|
|
346
|
-
const handleKeyDown = (e) => {
|
|
347
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
348
|
-
e.preventDefault();
|
|
349
|
-
handleSend();
|
|
350
|
-
}
|
|
351
|
-
};
|
|
352
|
-
const handleChange = (e) => {
|
|
353
|
-
setValue(e.target.value);
|
|
354
|
-
const el = e.target;
|
|
355
|
-
el.style.height = "auto";
|
|
356
|
-
el.style.height = `${Math.min(el.scrollHeight, 160)}px`;
|
|
357
|
-
};
|
|
358
|
-
const handleAttachClick = () => {
|
|
359
|
-
fileInputRef.current?.click();
|
|
360
|
-
};
|
|
361
|
-
const handleFolderClick = () => {
|
|
362
|
-
folderInputRef.current?.click();
|
|
363
|
-
};
|
|
364
|
-
const handleFileChange = (e) => {
|
|
365
|
-
if (e.target.files?.length) {
|
|
366
|
-
onAttach?.(e.target.files);
|
|
367
|
-
e.target.value = "";
|
|
368
|
-
}
|
|
369
|
-
};
|
|
370
|
-
const handleFolderChange = (e) => {
|
|
371
|
-
if (e.target.files?.length) {
|
|
372
|
-
(onAttachFolder ?? onAttach)?.(e.target.files);
|
|
373
|
-
e.target.value = "";
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
const handleDragEnter = useCallback((e) => {
|
|
377
|
-
e.preventDefault();
|
|
378
|
-
e.stopPropagation();
|
|
379
|
-
dragCounter.current++;
|
|
380
|
-
if (e.dataTransfer?.types.includes("Files")) {
|
|
381
|
-
setDragOver(true);
|
|
382
|
-
}
|
|
383
|
-
}, []);
|
|
384
|
-
const handleDragLeave = useCallback((e) => {
|
|
385
|
-
e.preventDefault();
|
|
386
|
-
e.stopPropagation();
|
|
387
|
-
dragCounter.current--;
|
|
388
|
-
if (dragCounter.current === 0) {
|
|
389
|
-
setDragOver(false);
|
|
390
|
-
}
|
|
391
|
-
}, []);
|
|
392
|
-
const handleDragOver = useCallback((e) => {
|
|
393
|
-
e.preventDefault();
|
|
394
|
-
e.stopPropagation();
|
|
395
|
-
e.dataTransfer.dropEffect = "copy";
|
|
396
|
-
}, []);
|
|
397
|
-
const handleDrop = useCallback((e) => {
|
|
398
|
-
e.preventDefault();
|
|
399
|
-
e.stopPropagation();
|
|
400
|
-
dragCounter.current = 0;
|
|
401
|
-
setDragOver(false);
|
|
402
|
-
const files = e.dataTransfer?.files;
|
|
403
|
-
if (files?.length && onAttach) {
|
|
404
|
-
onAttach(files);
|
|
405
|
-
}
|
|
406
|
-
}, [onAttach]);
|
|
407
|
-
const fileChips = pendingFiles.filter((f) => f.type === "file" || !f.type);
|
|
408
|
-
const folderChips = pendingFiles.filter((f) => f.type === "folder");
|
|
409
|
-
return /* @__PURE__ */ jsxs4(
|
|
410
|
-
"div",
|
|
411
|
-
{
|
|
412
|
-
className: cn("relative", className),
|
|
413
|
-
onDragEnter: onAttach ? handleDragEnter : void 0,
|
|
414
|
-
onDragLeave: onAttach ? handleDragLeave : void 0,
|
|
415
|
-
onDragOver: onAttach ? handleDragOver : void 0,
|
|
416
|
-
onDrop: onAttach ? handleDrop : void 0,
|
|
417
|
-
children: [
|
|
418
|
-
dragOver && /* @__PURE__ */ jsx5("div", { className: "absolute inset-0 z-10 flex items-center justify-center rounded-[var(--radius-xl)] border-2 border-dashed border-border bg-card pointer-events-none", children: /* @__PURE__ */ jsxs4("div", { className: "text-center", children: [
|
|
419
|
-
/* @__PURE__ */ jsx5("div", { className: "mx-auto mb-3 flex h-12 w-12 items-center justify-center rounded-xl bg-[var(--accent-surface-soft)]", children: /* @__PURE__ */ jsx5(Upload, { className: "h-6 w-6 text-primary" }) }),
|
|
420
|
-
/* @__PURE__ */ jsx5("p", { className: "text-sm font-semibold text-foreground", children: dropTitle }),
|
|
421
|
-
/* @__PURE__ */ jsx5("p", { className: "mt-1 text-xs text-muted-foreground", children: dropDescription })
|
|
422
|
-
] }) }),
|
|
423
|
-
pendingFiles.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "mb-3 flex flex-wrap gap-2", children: [
|
|
424
|
-
folderChips.map((f) => /* @__PURE__ */ jsxs4(
|
|
425
|
-
"span",
|
|
426
|
-
{
|
|
427
|
-
className: cn(
|
|
428
|
-
"inline-flex items-center gap-1.5 rounded-[var(--radius-full)] border px-3 py-1.5 text-xs",
|
|
429
|
-
"border-border bg-muted/50",
|
|
430
|
-
f.status === "error" && "border-[var(--code-error)]/30 text-[var(--code-error)]",
|
|
431
|
-
f.status !== "error" && "text-foreground"
|
|
432
|
-
),
|
|
433
|
-
children: [
|
|
434
|
-
/* @__PURE__ */ jsx5(FolderUp, { className: "h-3 w-3 shrink-0" }),
|
|
435
|
-
/* @__PURE__ */ jsx5("span", { className: "truncate max-w-[150px]", children: f.name }),
|
|
436
|
-
f.fileCount !== void 0 && /* @__PURE__ */ jsxs4("span", { className: "text-muted-foreground", children: [
|
|
437
|
-
"(",
|
|
438
|
-
f.fileCount,
|
|
439
|
-
")"
|
|
440
|
-
] }),
|
|
441
|
-
f.status === "uploading" && /* @__PURE__ */ jsx5("span", { className: "w-3 h-3 border-2 border-primary border-t-transparent rounded-full animate-spin" }),
|
|
442
|
-
onRemoveFile && /* @__PURE__ */ jsx5(
|
|
443
|
-
"button",
|
|
444
|
-
{
|
|
445
|
-
type: "button",
|
|
446
|
-
"aria-label": `Remove ${f.name}`,
|
|
447
|
-
onClick: () => onRemoveFile(f.id),
|
|
448
|
-
className: "rounded p-0.5 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60",
|
|
449
|
-
children: /* @__PURE__ */ jsx5(X, { className: "h-3 w-3" })
|
|
450
|
-
}
|
|
451
|
-
)
|
|
452
|
-
]
|
|
453
|
-
},
|
|
454
|
-
f.id
|
|
455
|
-
)),
|
|
456
|
-
fileChips.map((f) => /* @__PURE__ */ jsxs4(
|
|
457
|
-
"span",
|
|
458
|
-
{
|
|
459
|
-
className: cn(
|
|
460
|
-
"inline-flex items-center gap-1.5 rounded-[var(--radius-full)] border px-3 py-1.5 text-xs",
|
|
461
|
-
"border-border bg-muted/50",
|
|
462
|
-
f.status === "error" && "border-[var(--code-error)]/30 text-[var(--code-error)]",
|
|
463
|
-
f.status !== "error" && "text-foreground"
|
|
464
|
-
),
|
|
465
|
-
children: [
|
|
466
|
-
/* @__PURE__ */ jsx5(Paperclip, { className: "h-3 w-3 shrink-0" }),
|
|
467
|
-
/* @__PURE__ */ jsx5("span", { className: "truncate max-w-[150px]", children: f.name }),
|
|
468
|
-
f.status === "uploading" && /* @__PURE__ */ jsx5("span", { className: "w-3 h-3 border-2 border-primary border-t-transparent rounded-full animate-spin" }),
|
|
469
|
-
onRemoveFile && /* @__PURE__ */ jsx5(
|
|
470
|
-
"button",
|
|
471
|
-
{
|
|
472
|
-
type: "button",
|
|
473
|
-
"aria-label": `Remove ${f.name}`,
|
|
474
|
-
onClick: () => onRemoveFile(f.id),
|
|
475
|
-
className: "rounded p-0.5 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60",
|
|
476
|
-
children: /* @__PURE__ */ jsx5(X, { className: "h-3 w-3" })
|
|
477
|
-
}
|
|
478
|
-
)
|
|
479
|
-
]
|
|
480
|
-
},
|
|
481
|
-
f.id
|
|
482
|
-
))
|
|
483
|
-
] }),
|
|
484
|
-
/* @__PURE__ */ jsx5("div", { className: "rounded-[24px] border border-[var(--chat-input-border,var(--border-default))] [background:var(--chat-input-bg,var(--bg-card))] shadow-[var(--chat-input-shadow,0_1px_2px_rgba(15,23,42,0.05))] transition-all focus-within:border-[var(--chat-input-focus-border,var(--border-accent))] focus-within:shadow-[var(--chat-input-focus-shadow,0_10px_30px_rgba(15,23,42,0.08))]", children: /* @__PURE__ */ jsxs4("div", { className: "rounded-[24px] px-4 py-[var(--chat-input-py)]", children: [
|
|
485
|
-
(inputLabel !== null || idleStatus !== null || streamingStatus !== null) && /* @__PURE__ */ jsxs4("div", { className: "mb-1.5 flex items-center justify-between gap-3 px-1", children: [
|
|
486
|
-
inputLabel !== null && /* @__PURE__ */ jsx5("div", { className: "text-[var(--chat-label-size,11px)] font-[var(--chat-label-weight,600)] uppercase tracking-[var(--chat-label-tracking,0.16em)] text-[var(--text-muted)]", children: inputLabel }),
|
|
487
|
-
(idleStatus !== null || streamingStatus !== null) && /* @__PURE__ */ jsx5("div", { className: "text-[var(--chat-label-size,11px)] text-[var(--text-muted)]", children: isStreaming ? streamingStatus ?? "" : idleStatus ?? "" })
|
|
488
|
-
] }),
|
|
489
|
-
/* @__PURE__ */ jsxs4("div", { className: "flex items-end gap-2.5", children: [
|
|
490
|
-
onAttach && /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
491
|
-
/* @__PURE__ */ jsx5(
|
|
492
|
-
"button",
|
|
493
|
-
{
|
|
494
|
-
type: "button",
|
|
495
|
-
onClick: handleAttachClick,
|
|
496
|
-
disabled: isStreaming,
|
|
497
|
-
"aria-label": "Attach files",
|
|
498
|
-
title: "Attach files",
|
|
499
|
-
className: "mb-0.5 shrink-0 rounded-[var(--radius-md)] border border-transparent p-2 text-muted-foreground transition-colors hover:border-border hover:bg-accent hover:text-foreground disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60",
|
|
500
|
-
children: /* @__PURE__ */ jsx5(Paperclip, { className: "h-4 w-4" })
|
|
501
|
-
}
|
|
502
|
-
),
|
|
503
|
-
/* @__PURE__ */ jsx5(
|
|
504
|
-
"input",
|
|
505
|
-
{
|
|
506
|
-
ref: fileInputRef,
|
|
507
|
-
type: "file",
|
|
508
|
-
multiple: true,
|
|
509
|
-
className: "hidden",
|
|
510
|
-
onChange: handleFileChange,
|
|
511
|
-
accept: accept ?? ".pdf,.csv,.xlsx,.xls,.jpg,.jpeg,.png,.gif,.txt,.json,.yaml,.yml"
|
|
512
|
-
}
|
|
513
|
-
)
|
|
514
|
-
] }),
|
|
515
|
-
(onAttachFolder ?? onAttach) && /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
516
|
-
/* @__PURE__ */ jsx5(
|
|
517
|
-
"button",
|
|
518
|
-
{
|
|
519
|
-
type: "button",
|
|
520
|
-
onClick: handleFolderClick,
|
|
521
|
-
disabled: isStreaming,
|
|
522
|
-
"aria-label": "Attach folder",
|
|
523
|
-
title: "Attach folder",
|
|
524
|
-
className: "mb-0.5 shrink-0 rounded-[var(--radius-md)] border border-transparent p-2 text-muted-foreground transition-colors hover:border-border hover:bg-accent hover:text-foreground disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60",
|
|
525
|
-
children: /* @__PURE__ */ jsx5(FolderUp, { className: "h-4 w-4" })
|
|
526
|
-
}
|
|
527
|
-
),
|
|
528
|
-
/* @__PURE__ */ jsx5(
|
|
529
|
-
"input",
|
|
530
|
-
{
|
|
531
|
-
ref: folderInputRef,
|
|
532
|
-
type: "file",
|
|
533
|
-
multiple: true,
|
|
534
|
-
className: "hidden",
|
|
535
|
-
onChange: handleFolderChange,
|
|
536
|
-
webkitdirectory: ""
|
|
537
|
-
}
|
|
538
|
-
)
|
|
539
|
-
] }),
|
|
540
|
-
/* @__PURE__ */ jsx5(
|
|
541
|
-
"textarea",
|
|
542
|
-
{
|
|
543
|
-
ref: textareaRef,
|
|
544
|
-
value,
|
|
545
|
-
onChange: handleChange,
|
|
546
|
-
onKeyDown: handleKeyDown,
|
|
547
|
-
placeholder,
|
|
548
|
-
disabled: isStreaming || disabled,
|
|
549
|
-
rows: 1,
|
|
550
|
-
"aria-label": "Message input",
|
|
551
|
-
className: "min-h-[42px] max-h-[160px] flex-1 resize-none bg-transparent py-2 text-[15px] leading-6 text-foreground placeholder:text-muted-foreground disabled:opacity-50 focus-visible:outline-none"
|
|
552
|
-
}
|
|
553
|
-
),
|
|
554
|
-
isStreaming ? /* @__PURE__ */ jsx5(
|
|
555
|
-
"button",
|
|
556
|
-
{
|
|
557
|
-
type: "button",
|
|
558
|
-
onClick: onCancel,
|
|
559
|
-
"aria-label": "Stop response",
|
|
560
|
-
className: "mb-0.5 shrink-0 rounded-[var(--radius-lg)] border border-[var(--code-error)]/20 bg-[var(--code-error)]/14 p-2.5 text-[var(--code-error)] transition-colors hover:bg-[var(--code-error)]/24 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--code-error)]/50",
|
|
561
|
-
children: /* @__PURE__ */ jsx5(Square, { className: "h-4 w-4" })
|
|
562
|
-
}
|
|
563
|
-
) : /* @__PURE__ */ jsxs4(
|
|
564
|
-
"button",
|
|
565
|
-
{
|
|
566
|
-
type: "button",
|
|
567
|
-
onClick: handleSend,
|
|
568
|
-
disabled: !value.trim() || disabled,
|
|
569
|
-
"aria-label": "Send message",
|
|
570
|
-
className: "mb-0.5 inline-flex shrink-0 items-center gap-1.5 rounded-full border border-[var(--chat-send-border,var(--border-accent))] [background:var(--chat-send-bg,var(--brand-primary))] px-3.5 py-2.5 text-sm font-medium text-[var(--chat-send-color,white)] shadow-[var(--chat-send-shadow,0_6px_16px_rgba(15,23,42,0.12))] transition-all hover:translate-y-[-1px] hover:[background:var(--chat-send-hover-bg,var(--brand-strong))] disabled:opacity-30 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--chat-send-ring,var(--border-accent))]",
|
|
571
|
-
children: [
|
|
572
|
-
/* @__PURE__ */ jsx5(Send, { className: "h-4 w-4" }),
|
|
573
|
-
/* @__PURE__ */ jsx5("span", { children: "Send" })
|
|
574
|
-
]
|
|
575
|
-
}
|
|
576
|
-
)
|
|
577
|
-
] })
|
|
578
|
-
] }) }),
|
|
579
|
-
(modelLabel || !hideShortcutHint) && /* @__PURE__ */ jsxs4("div", { className: "mt-2 flex items-center justify-between px-1", children: [
|
|
580
|
-
/* @__PURE__ */ jsx5("div", { className: "flex items-center gap-2", children: modelLabel && /* @__PURE__ */ jsxs4(
|
|
581
|
-
"button",
|
|
582
|
-
{
|
|
583
|
-
type: "button",
|
|
584
|
-
onClick: onModelClick,
|
|
585
|
-
"aria-label": `Select model, current model ${modelLabel}`,
|
|
586
|
-
className: "inline-flex items-center gap-1.5 rounded-[var(--radius-full)] border border-border bg-[linear-gradient(180deg,rgba(255,255,255,0.04),transparent)] px-2.5 py-1 text-xs text-muted-foreground transition-colors hover:border-primary/20 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60",
|
|
587
|
-
children: [
|
|
588
|
-
/* @__PURE__ */ jsx5("span", { className: "w-1.5 h-1.5 rounded-full bg-[var(--code-success)]" }),
|
|
589
|
-
modelLabel
|
|
590
|
-
]
|
|
591
|
-
}
|
|
592
|
-
) }),
|
|
593
|
-
!hideShortcutHint && /* @__PURE__ */ jsxs4("span", { className: "text-xs text-muted-foreground", children: [
|
|
594
|
-
/* @__PURE__ */ jsx5("kbd", { className: "px-1 py-0.5 bg-background rounded border border-border text-[10px]", children: "Cmd" }),
|
|
595
|
-
/* @__PURE__ */ jsx5("kbd", { className: "px-1 py-0.5 bg-background rounded border border-border text-[10px] ml-0.5", children: "L" }),
|
|
596
|
-
/* @__PURE__ */ jsx5("span", { className: "ml-1", children: "to focus" })
|
|
597
|
-
] })
|
|
598
|
-
] })
|
|
599
|
-
]
|
|
600
|
-
}
|
|
601
|
-
);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
353
|
// src/chat/chat-container.tsx
|
|
605
|
-
import { jsx as
|
|
354
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
606
355
|
var OPENUI_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
607
356
|
"heading",
|
|
608
357
|
"text",
|
|
@@ -752,7 +501,7 @@ function buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enab
|
|
|
752
501
|
items.push({
|
|
753
502
|
id: `${message.id}-openui-${part.id}`,
|
|
754
503
|
kind: "custom",
|
|
755
|
-
content: /* @__PURE__ */
|
|
504
|
+
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 }) })
|
|
756
505
|
});
|
|
757
506
|
}
|
|
758
507
|
}
|
|
@@ -784,7 +533,7 @@ function buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enab
|
|
|
784
533
|
items.push({
|
|
785
534
|
id: `${itemId}-openui`,
|
|
786
535
|
kind: "custom",
|
|
787
|
-
content: /* @__PURE__ */
|
|
536
|
+
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 }) })
|
|
788
537
|
});
|
|
789
538
|
const afterJson = part.text.slice(part.text.lastIndexOf("```") + 3).trim();
|
|
790
539
|
if (afterJson) {
|
|
@@ -814,7 +563,7 @@ function buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enab
|
|
|
814
563
|
items.push({
|
|
815
564
|
id: itemId,
|
|
816
565
|
kind: "custom",
|
|
817
|
-
content: /* @__PURE__ */
|
|
566
|
+
content: /* @__PURE__ */ jsx5(InlineThinkingItem, { part, defaultOpen: isStreaming && lastAssistantMessage?.id === message.id })
|
|
818
567
|
});
|
|
819
568
|
return;
|
|
820
569
|
}
|
|
@@ -831,27 +580,17 @@ var ChatContainer = memo3(
|
|
|
831
580
|
messages,
|
|
832
581
|
partMap,
|
|
833
582
|
isStreaming,
|
|
834
|
-
onSend,
|
|
835
|
-
onCancel,
|
|
836
583
|
branding,
|
|
837
|
-
placeholder = "Type a message...",
|
|
838
584
|
className,
|
|
839
|
-
hideInput = false,
|
|
840
585
|
renderToolDetail,
|
|
841
586
|
presentation = "runs",
|
|
842
|
-
modelLabel,
|
|
843
|
-
onModelClick,
|
|
844
|
-
pendingFiles,
|
|
845
|
-
onRemoveFile,
|
|
846
|
-
onAttach,
|
|
847
|
-
disabled = false,
|
|
848
587
|
onOpenUIAction,
|
|
849
588
|
enableOpenUI = true,
|
|
850
589
|
renderRunActions,
|
|
851
590
|
renderUserMessageActions,
|
|
852
591
|
renderToolActions
|
|
853
592
|
}) => {
|
|
854
|
-
const scrollRef =
|
|
593
|
+
const scrollRef = useRef(null);
|
|
855
594
|
const groups = useRunGroups({ messages, partMap, isStreaming });
|
|
856
595
|
const runs = groups.filter((g) => g.type === "run").map((g) => g.run);
|
|
857
596
|
const { isCollapsed, toggleCollapse } = useRunCollapseState(runs);
|
|
@@ -864,19 +603,13 @@ var ChatContainer = memo3(
|
|
|
864
603
|
() => buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enableOpenUI),
|
|
865
604
|
[messages, partMap, isStreaming, onOpenUIAction, enableOpenUI]
|
|
866
605
|
);
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
onSend?.(text);
|
|
870
|
-
},
|
|
871
|
-
[onSend]
|
|
872
|
-
);
|
|
873
|
-
return /* @__PURE__ */ jsxs5("div", { className: cn("flex h-full flex-col", className), children: [
|
|
874
|
-
/* @__PURE__ */ jsx6(
|
|
606
|
+
return /* @__PURE__ */ jsxs4("div", { className: cn("flex h-full flex-col", className), children: [
|
|
607
|
+
/* @__PURE__ */ jsx5(
|
|
875
608
|
"div",
|
|
876
609
|
{
|
|
877
610
|
ref: scrollRef,
|
|
878
611
|
className: "flex-1 overflow-y-auto [scrollbar-gutter:stable]",
|
|
879
|
-
children: messages.length === 0 ? /* @__PURE__ */
|
|
612
|
+
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(AgentTimeline, { items: timeline.items, isThinking: timeline.showThinking }) }) : /* @__PURE__ */ jsx5("div", { className: "mx-auto flex min-h-full w-full max-w-3xl flex-col justify-end", children: /* @__PURE__ */ jsx5(
|
|
880
613
|
MessageList,
|
|
881
614
|
{
|
|
882
615
|
groups,
|
|
@@ -892,7 +625,7 @@ var ChatContainer = memo3(
|
|
|
892
625
|
) })
|
|
893
626
|
}
|
|
894
627
|
),
|
|
895
|
-
!isAtBottom && /* @__PURE__ */
|
|
628
|
+
!isAtBottom && /* @__PURE__ */ jsx5("div", { className: "relative z-10 -mt-10 flex justify-center", children: /* @__PURE__ */ jsxs4(
|
|
896
629
|
"button",
|
|
897
630
|
{
|
|
898
631
|
onClick: scrollToBottom,
|
|
@@ -903,34 +636,18 @@ var ChatContainer = memo3(
|
|
|
903
636
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60"
|
|
904
637
|
),
|
|
905
638
|
children: [
|
|
906
|
-
/* @__PURE__ */
|
|
639
|
+
/* @__PURE__ */ jsx5(ArrowDown, { className: "w-3 h-3" }),
|
|
907
640
|
"Scroll to bottom"
|
|
908
641
|
]
|
|
909
642
|
}
|
|
910
|
-
) })
|
|
911
|
-
!hideInput && onSend && /* @__PURE__ */ jsx6(
|
|
912
|
-
ChatInput,
|
|
913
|
-
{
|
|
914
|
-
onSend: handleSend,
|
|
915
|
-
onCancel,
|
|
916
|
-
isStreaming,
|
|
917
|
-
placeholder,
|
|
918
|
-
modelLabel,
|
|
919
|
-
onModelClick,
|
|
920
|
-
pendingFiles,
|
|
921
|
-
onRemoveFile,
|
|
922
|
-
onAttach,
|
|
923
|
-
disabled,
|
|
924
|
-
className: "shrink-0 border-t border-border bg-background"
|
|
925
|
-
}
|
|
926
|
-
)
|
|
643
|
+
) })
|
|
927
644
|
] });
|
|
928
645
|
}
|
|
929
646
|
);
|
|
930
647
|
ChatContainer.displayName = "ChatContainer";
|
|
931
648
|
|
|
932
649
|
// src/chat/chat-message.tsx
|
|
933
|
-
import { Fragment
|
|
650
|
+
import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
934
651
|
function ChatMessage({
|
|
935
652
|
role,
|
|
936
653
|
content,
|
|
@@ -943,7 +660,7 @@ function ChatMessage({
|
|
|
943
660
|
hideRoleLabel
|
|
944
661
|
}) {
|
|
945
662
|
const isUser = role === "user";
|
|
946
|
-
return /* @__PURE__ */
|
|
663
|
+
return /* @__PURE__ */ jsxs5(
|
|
947
664
|
"div",
|
|
948
665
|
{
|
|
949
666
|
className: cn(
|
|
@@ -952,11 +669,11 @@ function ChatMessage({
|
|
|
952
669
|
className
|
|
953
670
|
),
|
|
954
671
|
children: [
|
|
955
|
-
!hideRoleLabel && /* @__PURE__ */
|
|
956
|
-
/* @__PURE__ */
|
|
957
|
-
timestamp && /* @__PURE__ */
|
|
672
|
+
!hideRoleLabel && /* @__PURE__ */ jsxs5("div", { className: cn("flex items-center gap-2 px-1", isUser && "flex-row-reverse"), children: [
|
|
673
|
+
/* @__PURE__ */ jsx6("span", { className: "font-medium text-foreground text-xs", children: isUser ? userLabel : assistantLabel }),
|
|
674
|
+
timestamp && /* @__PURE__ */ jsx6("span", { className: "text-muted-foreground text-xs", children: formatTime2(timestamp) })
|
|
958
675
|
] }),
|
|
959
|
-
/* @__PURE__ */
|
|
676
|
+
/* @__PURE__ */ jsxs5(
|
|
960
677
|
"div",
|
|
961
678
|
{
|
|
962
679
|
className: cn(
|
|
@@ -965,9 +682,9 @@ function ChatMessage({
|
|
|
965
682
|
isUser ? "border-border bg-muted/50" : "border-border bg-card"
|
|
966
683
|
),
|
|
967
684
|
children: [
|
|
968
|
-
isUser ? /* @__PURE__ */
|
|
969
|
-
content && /* @__PURE__ */
|
|
970
|
-
isStreaming && /* @__PURE__ */
|
|
685
|
+
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: [
|
|
686
|
+
content && /* @__PURE__ */ jsx6(Markdown, { className: "tangle-prose text-[var(--font-size-base)] leading-[var(--line-height-base)]", children: content }),
|
|
687
|
+
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" })
|
|
971
688
|
] }),
|
|
972
689
|
toolCalls
|
|
973
690
|
]
|
|
@@ -989,7 +706,6 @@ export {
|
|
|
989
706
|
MessageList,
|
|
990
707
|
ThinkingIndicator,
|
|
991
708
|
AgentTimeline,
|
|
992
|
-
ChatInput,
|
|
993
709
|
ChatContainer,
|
|
994
710
|
ChatMessage
|
|
995
711
|
};
|