@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.
@@ -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-QIRVZMQY.js";
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 as useRef2
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 timelineItems = renderedItems.filter((item) => !(item.kind === "message" && item.role === "user"));
244
- return /* @__PURE__ */ jsx4("div", { className: cn("mx-auto w-full max-w-5xl px-4 py-4", className), children: renderedItems.map((item, index) => {
245
- if (item.kind === "message" && item.role === "user") {
246
- return /* @__PURE__ */ jsx4(UserMessage2, { item }, item.id);
247
- }
248
- const timelineIndex = timelineItems.indexOf(item);
249
- const isLast = timelineIndex === timelineItems.length - 1;
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
- if (item.kind === "tool") {
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
- ToolCallStep,
306
+ AssistantRunShell,
256
307
  {
257
- type: item.call.type,
258
- label: item.call.label,
259
- status: item.call.status,
260
- detail: item.call.detail,
261
- output: item.call.output,
262
- duration: item.call.duration
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
- ) }, item.id);
316
+ ) }, node.id);
265
317
  }
266
- if (item.kind === "tool_group") {
267
- return /* @__PURE__ */ jsx4(AgentTimelineRow, { isLast, accentClassName: "bg-[var(--border-hover)]", children: /* @__PURE__ */ jsx4(ToolCallGroup, { title: item.title, children: item.calls.map((call) => /* @__PURE__ */ jsx4(
268
- ToolCallStep,
269
- {
270
- type: call.type,
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 (item.kind === "status") {
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[item.tone ?? "default"].dot,
286
- children: /* @__PURE__ */ jsx4(StatusCard, { item })
332
+ accentClassName: TONE_STYLES[node.tone ?? "default"].dot,
333
+ children: /* @__PURE__ */ jsx4(StatusCard, { item: node })
287
334
  },
288
- item.id
335
+ node.id
289
336
  );
290
337
  }
291
- if (item.kind === "artifact") {
338
+ if (node.kind === "artifact") {
292
339
  return /* @__PURE__ */ jsx4(
293
340
  AgentTimelineRow,
294
341
  {
295
342
  isLast,
296
- accentClassName: TONE_STYLES[item.tone ?? "default"].dot,
297
- children: /* @__PURE__ */ jsx4(ArtifactCard, { item })
343
+ accentClassName: TONE_STYLES[node.tone ?? "default"].dot,
344
+ children: /* @__PURE__ */ jsx4(ArtifactCard, { item: node })
298
345
  },
299
- item.id
346
+ node.id
300
347
  );
301
348
  }
302
- return /* @__PURE__ */ jsx4(AgentTimelineRow, { isLast, accentClassName: "bg-[var(--border-hover)]", children: item.content }, item.id);
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 jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
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__ */ jsx6("div", { className: "my-2 rounded-[var(--radius-lg)] border border-border bg-card p-4 shadow-[var(--shadow-card)]", children: /* @__PURE__ */ jsx6(OpenUIArtifactRenderer, { schema, onAction: onOpenUIAction }) })
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__ */ jsx6("div", { className: "my-2 rounded-[var(--radius-lg)] border border-border bg-card p-4 shadow-[var(--shadow-card)]", children: /* @__PURE__ */ jsx6(OpenUIArtifactRenderer, { schema, onAction: onOpenUIAction }) })
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__ */ jsx6(InlineThinkingItem, { part, defaultOpen: isStreaming && lastAssistantMessage?.id === message.id })
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 = useRef2(null);
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
- const handleSend = useCallback2(
868
- (text) => {
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__ */ jsx6("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx6("div", { className: "max-w-md text-center", children: /* @__PURE__ */ jsx6("div", { className: "text-sm font-medium text-muted-foreground", children: "Start a conversation." }) }) }) : presentation === "timeline" ? /* @__PURE__ */ jsx6("div", { className: "mx-auto flex min-h-full w-full max-w-3xl flex-col justify-end", children: /* @__PURE__ */ jsx6(AgentTimeline, { items: timeline.items, isThinking: timeline.showThinking }) }) : /* @__PURE__ */ jsx6("div", { className: "mx-auto flex min-h-full w-full max-w-3xl flex-col justify-end", children: /* @__PURE__ */ jsx6(
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__ */ jsx6("div", { className: "relative z-10 -mt-10 flex justify-center", children: /* @__PURE__ */ jsxs5(
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__ */ jsx6(ArrowDown, { className: "w-3 h-3" }),
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 as Fragment2, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
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__ */ jsxs6(
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__ */ jsxs6("div", { className: cn("flex items-center gap-2 px-1", isUser && "flex-row-reverse"), children: [
956
- /* @__PURE__ */ jsx7("span", { className: "font-medium text-foreground text-xs", children: isUser ? userLabel : assistantLabel }),
957
- timestamp && /* @__PURE__ */ jsx7("span", { className: "text-muted-foreground text-xs", children: formatTime2(timestamp) })
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__ */ jsxs6(
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__ */ jsx7("div", { className: "whitespace-pre-wrap text-[var(--font-size-base)] leading-[var(--line-height-base)] text-foreground", children: content }) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
969
- content && /* @__PURE__ */ jsx7(Markdown, { className: "tangle-prose text-[var(--font-size-base)] leading-[var(--line-height-base)]", children: content }),
970
- isStreaming && /* @__PURE__ */ jsx7("span", { className: "ml-0.5 inline-block h-4 w-2 animate-pulse rounded-sm bg-[var(--brand-cool)] align-text-bottom" })
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
  };