@tangle-network/ui 6.0.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,11 +6,11 @@ import {
6
6
  import {
7
7
  InlineThinkingItem,
8
8
  RunGroup
9
- } from "./chunk-LASW7CYH.js";
9
+ } from "./chunk-QIRVZMQY.js";
10
10
  import {
11
11
  ToolCallGroup,
12
12
  ToolCallStep
13
- } from "./chunk-EOGJX2TU.js";
13
+ } from "./chunk-RKQDBRTC.js";
14
14
  import {
15
15
  getToolDisplayMetadata
16
16
  } from "./chunk-ULDNFLIM.js";
@@ -27,9 +27,8 @@ import {
27
27
  // src/chat/chat-container.tsx
28
28
  import {
29
29
  memo as memo3,
30
- useCallback as useCallback2,
31
30
  useMemo,
32
- useRef as useRef2
31
+ useRef
33
32
  } from "react";
34
33
  import { ArrowDown } from "lucide-react";
35
34
 
@@ -303,306 +302,8 @@ function AgentTimeline({
303
302
  }) });
304
303
  }
305
304
 
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
305
  // src/chat/chat-container.tsx
605
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
306
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
606
307
  var OPENUI_NODE_TYPES = /* @__PURE__ */ new Set([
607
308
  "heading",
608
309
  "text",
@@ -752,7 +453,7 @@ function buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enab
752
453
  items.push({
753
454
  id: `${message.id}-openui-${part.id}`,
754
455
  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 }) })
456
+ 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
457
  });
757
458
  }
758
459
  }
@@ -784,7 +485,7 @@ function buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enab
784
485
  items.push({
785
486
  id: `${itemId}-openui`,
786
487
  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 }) })
488
+ 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
489
  });
789
490
  const afterJson = part.text.slice(part.text.lastIndexOf("```") + 3).trim();
790
491
  if (afterJson) {
@@ -814,7 +515,7 @@ function buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enab
814
515
  items.push({
815
516
  id: itemId,
816
517
  kind: "custom",
817
- content: /* @__PURE__ */ jsx6(InlineThinkingItem, { part, defaultOpen: isStreaming && lastAssistantMessage?.id === message.id })
518
+ content: /* @__PURE__ */ jsx5(InlineThinkingItem, { part, defaultOpen: isStreaming && lastAssistantMessage?.id === message.id })
818
519
  });
819
520
  return;
820
521
  }
@@ -831,27 +532,17 @@ var ChatContainer = memo3(
831
532
  messages,
832
533
  partMap,
833
534
  isStreaming,
834
- onSend,
835
- onCancel,
836
535
  branding,
837
- placeholder = "Type a message...",
838
536
  className,
839
- hideInput = false,
840
537
  renderToolDetail,
841
538
  presentation = "runs",
842
- modelLabel,
843
- onModelClick,
844
- pendingFiles,
845
- onRemoveFile,
846
- onAttach,
847
- disabled = false,
848
539
  onOpenUIAction,
849
540
  enableOpenUI = true,
850
541
  renderRunActions,
851
542
  renderUserMessageActions,
852
543
  renderToolActions
853
544
  }) => {
854
- const scrollRef = useRef2(null);
545
+ const scrollRef = useRef(null);
855
546
  const groups = useRunGroups({ messages, partMap, isStreaming });
856
547
  const runs = groups.filter((g) => g.type === "run").map((g) => g.run);
857
548
  const { isCollapsed, toggleCollapse } = useRunCollapseState(runs);
@@ -864,19 +555,13 @@ var ChatContainer = memo3(
864
555
  () => buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enableOpenUI),
865
556
  [messages, partMap, isStreaming, onOpenUIAction, enableOpenUI]
866
557
  );
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(
558
+ return /* @__PURE__ */ jsxs4("div", { className: cn("flex h-full flex-col", className), children: [
559
+ /* @__PURE__ */ jsx5(
875
560
  "div",
876
561
  {
877
562
  ref: scrollRef,
878
563
  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(
564
+ 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
565
  MessageList,
881
566
  {
882
567
  groups,
@@ -892,7 +577,7 @@ var ChatContainer = memo3(
892
577
  ) })
893
578
  }
894
579
  ),
895
- !isAtBottom && /* @__PURE__ */ jsx6("div", { className: "relative z-10 -mt-10 flex justify-center", children: /* @__PURE__ */ jsxs5(
580
+ !isAtBottom && /* @__PURE__ */ jsx5("div", { className: "relative z-10 -mt-10 flex justify-center", children: /* @__PURE__ */ jsxs4(
896
581
  "button",
897
582
  {
898
583
  onClick: scrollToBottom,
@@ -903,35 +588,18 @@ var ChatContainer = memo3(
903
588
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60"
904
589
  ),
905
590
  children: [
906
- /* @__PURE__ */ jsx6(ArrowDown, { className: "w-3 h-3" }),
591
+ /* @__PURE__ */ jsx5(ArrowDown, { className: "w-3 h-3" }),
907
592
  "Scroll to bottom"
908
593
  ]
909
594
  }
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
- )
595
+ ) })
927
596
  ] });
928
597
  }
929
598
  );
930
599
  ChatContainer.displayName = "ChatContainer";
931
600
 
932
601
  // src/chat/chat-message.tsx
933
- import { User, Bot } from "lucide-react";
934
- import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
602
+ import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
935
603
  function ChatMessage({
936
604
  role,
937
605
  content,
@@ -941,32 +609,23 @@ function ChatMessage({
941
609
  className,
942
610
  userLabel = "You",
943
611
  assistantLabel = "Agent",
944
- hideRoleLabel,
945
- hideAvatar,
946
- avatar
612
+ hideRoleLabel
947
613
  }) {
948
614
  const isUser = role === "user";
949
- return /* @__PURE__ */ jsxs6(
615
+ return /* @__PURE__ */ jsxs5(
950
616
  "div",
951
617
  {
952
618
  className: cn(
953
- "flex gap-3",
954
- isUser ? "flex-row-reverse" : "flex-row",
619
+ "flex flex-col gap-1",
620
+ isUser ? "items-end" : "items-start",
955
621
  className
956
622
  ),
957
623
  children: [
958
- !hideAvatar && (avatar ? /* @__PURE__ */ jsx7("div", { className: "mt-0.5 shrink-0", children: avatar }) : /* @__PURE__ */ jsx7(
959
- "div",
960
- {
961
- className: cn(
962
- "mt-0.5 flex shrink-0 items-center justify-center rounded-[calc(var(--radius-md)+2px)] border",
963
- "h-[var(--avatar-size)] w-[var(--avatar-size)]",
964
- isUser ? "border-border bg-[var(--accent-surface-soft)] text-[var(--accent-text)]" : "border-border bg-muted text-[var(--brand-cool)]"
965
- ),
966
- children: isUser ? /* @__PURE__ */ jsx7(User, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx7(Bot, { className: "h-3.5 w-3.5" })
967
- }
968
- )),
969
- /* @__PURE__ */ jsxs6(
624
+ !hideRoleLabel && /* @__PURE__ */ jsxs5("div", { className: cn("flex items-center gap-2 px-1", isUser && "flex-row-reverse"), children: [
625
+ /* @__PURE__ */ jsx6("span", { className: "font-medium text-foreground text-xs", children: isUser ? userLabel : assistantLabel }),
626
+ timestamp && /* @__PURE__ */ jsx6("span", { className: "text-muted-foreground text-xs", children: formatTime2(timestamp) })
627
+ ] }),
628
+ /* @__PURE__ */ jsxs5(
970
629
  "div",
971
630
  {
972
631
  className: cn(
@@ -975,13 +634,9 @@ function ChatMessage({
975
634
  isUser ? "border-border bg-muted/50" : "border-border bg-card"
976
635
  ),
977
636
  children: [
978
- !hideRoleLabel && /* @__PURE__ */ jsxs6("div", { className: cn("flex items-center gap-2", isUser && "flex-row-reverse"), children: [
979
- /* @__PURE__ */ jsx7("span", { className: "text-[var(--font-size-xs)] font-[var(--chat-label-weight,600)] uppercase tracking-[var(--chat-label-tracking,0.14em)] text-foreground", children: isUser ? userLabel : assistantLabel }),
980
- timestamp && /* @__PURE__ */ jsx7("span", { className: "text-[var(--font-size-xs)] text-muted-foreground", children: formatTime2(timestamp) })
981
- ] }),
982
- 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: [
983
- content && /* @__PURE__ */ jsx7(Markdown, { className: "tangle-prose text-[var(--font-size-base)] leading-[var(--line-height-base)]", children: content }),
984
- 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" })
637
+ 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: [
638
+ content && /* @__PURE__ */ jsx6(Markdown, { className: "tangle-prose text-[var(--font-size-base)] leading-[var(--line-height-base)]", children: content }),
639
+ 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" })
985
640
  ] }),
986
641
  toolCalls
987
642
  ]
@@ -1003,7 +658,6 @@ export {
1003
658
  MessageList,
1004
659
  ThinkingIndicator,
1005
660
  AgentTimeline,
1006
- ChatInput,
1007
661
  ChatContainer,
1008
662
  ChatMessage
1009
663
  };
package/dist/hooks.d.ts CHANGED
@@ -5,7 +5,7 @@ import './message-BHWbxBtT.js';
5
5
  import './parts-dj7AcUg0.js';
6
6
  import './active-sessions-store-CeOmXgv5.js';
7
7
  import 'nanostores';
8
- import './tool-call-feed-Bs3MyQMT.js';
8
+ import './tool-call-feed-D9iofJgW.js';
9
9
  import 'react/jsx-runtime';
10
10
 
11
11
  /**
package/dist/hooks.js CHANGED
@@ -11,15 +11,15 @@ import {
11
11
  useSSEStream,
12
12
  useSdkSession,
13
13
  useToolCallStream
14
- } from "./chunk-PN3S2MTV.js";
14
+ } from "./chunk-DLSGUNRD.js";
15
15
  import "./chunk-OEX7NZE3.js";
16
16
  import {
17
17
  useAutoScroll,
18
18
  useRunCollapseState,
19
19
  useRunGroups
20
20
  } from "./chunk-AZWDI2JG.js";
21
- import "./chunk-O6NUUCT2.js";
22
- import "./chunk-EOGJX2TU.js";
21
+ import "./chunk-IWQZXL6A.js";
22
+ import "./chunk-RKQDBRTC.js";
23
23
  import "./chunk-ULDNFLIM.js";
24
24
  import "./chunk-AAUNOHVL.js";
25
25
  import "./chunk-ZRVH3WCA.js";
package/dist/index.d.ts CHANGED
@@ -2,9 +2,9 @@ export { B as Button, a as ButtonProps, b as buttonVariants } from './button-CMQ
2
2
  export { Avatar, AvatarFallback, AvatarImage, Badge, BadgeProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EmptyStateProps, InlineCode, InlineCodeProps, Input, InputProps, Label, Progress, SegmentedControl, SegmentedControlOption, SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, StatCardProps, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, Textarea, TextareaProps, ThemeToggle, Toast, ToastContainer, ToastProvider, UploadFile, UploadProgress, UploadProgressProps, badgeVariants, useTheme, useToast } from './primitives.js';
3
3
  export { Logo, LogoProps, TangleKnot } from '@tangle-network/brand';
4
4
  export { A as ArtifactPane, a as ArtifactPaneProps } from './artifact-pane-DvJyPWV4.js';
5
- export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem, ChatContainer, ChatContainerProps, ChatInput, ChatInputProps, ChatMessage, ChatMessageProps, MessageList, MessageListProps, MessageRole, PendingFile, ThinkingIndicator, ThinkingIndicatorProps, UserMessage, UserMessageProps } from './chat.js';
5
+ export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem, ChatContainer, ChatContainerProps, ChatMessage, ChatMessageProps, MessageList, MessageListProps, MessageRole, ThinkingIndicator, ThinkingIndicatorProps, UserMessage, UserMessageProps } from './chat.js';
6
6
  export { ExpandedToolDetail, ExpandedToolDetailProps, InlineThinkingItem, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps } from './run.js';
7
- export { F as FeedSegment, T as ToolCallData, a as ToolCallFeed, b as ToolCallFeedProps, c as ToolCallGroup, d as ToolCallGroupProps, e as ToolCallStatus, f as ToolCallStep, g as ToolCallStepProps, h as ToolCallType, p as parseToolEvent } from './tool-call-feed-Bs3MyQMT.js';
7
+ export { F as FeedSegment, T as ToolCallData, a as ToolCallFeed, b as ToolCallFeedProps, c as ToolCallStatus, d as ToolCallType, p as parseToolEvent } from './tool-call-feed-D9iofJgW.js';
8
8
  export { OpenUIAction, OpenUIActionsNode, OpenUIArtifactRenderer, OpenUIArtifactRendererProps, OpenUIBadgeNode, OpenUICardNode, OpenUICodeNode, OpenUIComponentNode, OpenUIGridNode, OpenUIHeadingNode, OpenUIKeyValueNode, OpenUIMarkdownNode, OpenUIPrimitive, OpenUISeparatorNode, OpenUIStackNode, OpenUIStatNode, OpenUITableNode, OpenUITextNode } from './openui.js';
9
9
  export { FileArtifactPane, FileArtifactPaneProps, FileFormat, FileNode, FilePreview, FilePreviewProps, FileTabData, FileTabs, FileTabsProps, FileTree, FileTreeProps, FileTreeVisibilityOptions, RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars, detectFileFormat, fileExtension, filterFileTree, getCodeLanguage, getFormatLabel, getSyntaxLanguage } from './files.js';
10
10
  export { Markdown, MarkdownProps } from './markdown.js';
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  useSSEStream,
18
18
  useSdkSession,
19
19
  useToolCallStream
20
- } from "./chunk-PN3S2MTV.js";
20
+ } from "./chunk-DLSGUNRD.js";
21
21
  import {
22
22
  addMessage,
23
23
  addParts,
@@ -133,33 +133,30 @@ import {
133
133
  import {
134
134
  AgentTimeline,
135
135
  ChatContainer,
136
- ChatInput,
137
136
  ChatMessage,
138
137
  MessageList,
139
138
  ThinkingIndicator,
140
139
  UserMessage
141
- } from "./chunk-SJ6IL4HI.js";
140
+ } from "./chunk-UOLL2YHG.js";
142
141
  import {
143
142
  useAutoScroll,
144
143
  useRunCollapseState,
145
144
  useRunGroups
146
145
  } from "./chunk-AZWDI2JG.js";
147
- import "./chunk-LQS34IGP.js";
146
+ import "./chunk-47XH56SV.js";
148
147
  import {
149
148
  ToolCallFeed,
150
149
  parseToolEvent
151
- } from "./chunk-O6NUUCT2.js";
150
+ } from "./chunk-IWQZXL6A.js";
152
151
  import {
153
152
  InlineThinkingItem,
154
153
  RunGroup
155
- } from "./chunk-LASW7CYH.js";
154
+ } from "./chunk-QIRVZMQY.js";
156
155
  import {
157
156
  ExpandedToolDetail,
158
157
  InlineToolItem,
159
- LiveDuration,
160
- ToolCallGroup,
161
- ToolCallStep
162
- } from "./chunk-EOGJX2TU.js";
158
+ LiveDuration
159
+ } from "./chunk-RKQDBRTC.js";
163
160
  import {
164
161
  TOOL_CATEGORY_ICONS,
165
162
  formatBytes,
@@ -354,7 +351,6 @@ export {
354
351
  CardHeader,
355
352
  CardTitle,
356
353
  ChatContainer,
357
- ChatInput,
358
354
  ChatMessage,
359
355
  CodeBlock,
360
356
  CommandPreview,
@@ -453,8 +449,6 @@ export {
453
449
  ToastContainer,
454
450
  ToastProvider,
455
451
  ToolCallFeed,
456
- ToolCallGroup,
457
- ToolCallStep,
458
452
  UploadProgress,
459
453
  UserMenu,
460
454
  UserMessage,
package/dist/run.d.ts CHANGED
@@ -5,7 +5,7 @@ import { R as Run } from './run-PfLmDAox.js';
5
5
  import { S as SessionPart, a as ToolPart, R as ReasoningPart } from './parts-dj7AcUg0.js';
6
6
  import { AgentBranding } from './types.js';
7
7
  import { C as CustomToolRenderer } from './tool-display-z4JcDmMQ.js';
8
- export { F as FeedSegment, T as ToolCallData, a as ToolCallFeed, b as ToolCallFeedProps, c as ToolCallGroup, d as ToolCallGroupProps, e as ToolCallStatus, f as ToolCallStep, g as ToolCallStepProps, h as ToolCallType, p as parseToolEvent } from './tool-call-feed-Bs3MyQMT.js';
8
+ export { F as FeedSegment, T as ToolCallData, a as ToolCallFeed, b as ToolCallFeedProps, c as ToolCallStatus, d as ToolCallType, p as parseToolEvent } from './tool-call-feed-D9iofJgW.js';
9
9
  import './message-BHWbxBtT.js';
10
10
 
11
11
  interface RunGroupProps {