@copilotz/chat-ui 0.1.20 → 0.1.21

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/dist/index.d.cts CHANGED
@@ -38,6 +38,8 @@ interface ChatMessage {
38
38
  id: string;
39
39
  role: 'user' | 'assistant' | 'system';
40
40
  content: string;
41
+ /** Optional model reasoning stream (when the backend emits reasoning tokens separately). */
42
+ reasoning?: string;
41
43
  timestamp: number;
42
44
  attachments?: MediaAttachment[];
43
45
  isStreaming?: boolean;
package/dist/index.d.ts CHANGED
@@ -38,6 +38,8 @@ interface ChatMessage {
38
38
  id: string;
39
39
  role: 'user' | 'assistant' | 'system';
40
40
  content: string;
41
+ /** Optional model reasoning stream (when the backend emits reasoning tokens separately). */
42
+ reasoning?: string;
41
43
  timestamp: number;
42
44
  attachments?: MediaAttachment[];
43
45
  isStreaming?: boolean;
package/dist/index.js CHANGED
@@ -553,7 +553,8 @@ import {
553
553
  Wrench,
554
554
  Clock,
555
555
  ChevronRight,
556
- ChevronDown
556
+ ChevronDown,
557
+ BrainCircuit
557
558
  } from "lucide-react";
558
559
  import { Fragment, jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
559
560
  var ThinkingIndicator = memo(function ThinkingIndicator2({ label = "Thinking..." }) {
@@ -584,6 +585,78 @@ var ThinkingIndicator = memo(function ThinkingIndicator2({ label = "Thinking..."
584
585
  /* @__PURE__ */ jsx7("span", { className: "text-sm text-muted-foreground animate-pulse", children: label })
585
586
  ] });
586
587
  });
588
+ var ThinkingBlock = memo(function ThinkingBlock2({ content, isStreaming = false, label = "Thinking", chunkSize = 12e3 }) {
589
+ const [open, setOpen] = useState(isStreaming);
590
+ useEffect(() => {
591
+ if (isStreaming) setOpen(true);
592
+ }, [isStreaming]);
593
+ useEffect(() => {
594
+ if (!isStreaming && open) {
595
+ const timer = setTimeout(() => setOpen(false), 600);
596
+ return () => clearTimeout(timer);
597
+ }
598
+ }, [isStreaming, open]);
599
+ return /* @__PURE__ */ jsxs2("div", { className: "mb-3 relative rounded-lg overflow-hidden", children: [
600
+ isStreaming && /* @__PURE__ */ jsx7(
601
+ "div",
602
+ {
603
+ className: "absolute inset-0 rounded-lg pointer-events-none",
604
+ style: {
605
+ padding: "1px",
606
+ background: "linear-gradient(135deg, hsl(var(--primary) / 0.4), hsl(var(--muted-foreground) / 0.2), hsl(var(--primary) / 0.4))",
607
+ backgroundSize: "200% 200%",
608
+ animation: "thinking-shimmer 2s ease-in-out infinite"
609
+ }
610
+ }
611
+ ),
612
+ /* @__PURE__ */ jsxs2(
613
+ "div",
614
+ {
615
+ className: `relative rounded-lg border bg-muted/30 ${isStreaming ? "border-transparent" : "border-muted-foreground/20"}`,
616
+ style: isStreaming ? { margin: "1px" } : void 0,
617
+ children: [
618
+ /* @__PURE__ */ jsxs2(
619
+ "button",
620
+ {
621
+ type: "button",
622
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left text-xs font-medium text-muted-foreground hover:text-foreground/70 transition-colors",
623
+ onClick: () => setOpen((v) => !v),
624
+ children: [
625
+ /* @__PURE__ */ jsx7(BrainCircuit, { className: `h-3.5 w-3.5 flex-shrink-0 ${isStreaming ? "animate-pulse text-primary" : ""}` }),
626
+ /* @__PURE__ */ jsxs2("span", { className: "flex-1", children: [
627
+ isStreaming ? label : `${label}`,
628
+ isStreaming && /* @__PURE__ */ jsxs2("span", { className: "ml-1 inline-flex gap-0.5", children: [
629
+ /* @__PURE__ */ jsx7("span", { className: "inline-block w-1 h-1 bg-current rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
630
+ /* @__PURE__ */ jsx7("span", { className: "inline-block w-1 h-1 bg-current rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
631
+ /* @__PURE__ */ jsx7("span", { className: "inline-block w-1 h-1 bg-current rounded-full animate-bounce", style: { animationDelay: "300ms" } })
632
+ ] })
633
+ ] }),
634
+ open ? /* @__PURE__ */ jsx7(ChevronDown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx7(ChevronRight, { className: "h-3 w-3" })
635
+ ]
636
+ }
637
+ ),
638
+ open && /* @__PURE__ */ jsx7("div", { className: "px-3 pb-3", children: /* @__PURE__ */ jsxs2("div", { className: "border-l-2 border-muted-foreground/20 pl-3", children: [
639
+ /* @__PURE__ */ jsx7(
640
+ PlainTextContent,
641
+ {
642
+ content,
643
+ className: "text-xs text-muted-foreground/80 leading-5",
644
+ chunkSize
645
+ }
646
+ ),
647
+ isStreaming && /* @__PURE__ */ jsx7("span", { className: "inline-block w-1.5 h-3 bg-muted-foreground/40 animate-pulse ml-0.5" })
648
+ ] }) })
649
+ ]
650
+ }
651
+ ),
652
+ /* @__PURE__ */ jsx7("style", { children: `
653
+ @keyframes thinking-shimmer {
654
+ 0%, 100% { background-position: 0% 50%; }
655
+ 50% { background-position: 100% 50%; }
656
+ }
657
+ ` })
658
+ ] });
659
+ });
587
660
  var markdownComponents = {
588
661
  code: ({ node, className, children, ...props }) => {
589
662
  const inline = props.inline;
@@ -974,6 +1047,15 @@ var Message = memo(({
974
1047
  ] })
975
1048
  ] })
976
1049
  ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
1050
+ !messageIsUser && message.reasoning && message.reasoning.trim().length > 0 && /* @__PURE__ */ jsx7(
1051
+ ThinkingBlock,
1052
+ {
1053
+ content: message.reasoning,
1054
+ isStreaming: message.isStreaming,
1055
+ label: thinkingLabel,
1056
+ chunkSize: normalizedChunkChars
1057
+ }
1058
+ ),
977
1059
  enableToolCallsDisplay && message.toolCalls && message.toolCalls.length > 0 && /* @__PURE__ */ jsx7("div", { className: "mb-3", children: /* @__PURE__ */ jsx7(ToolCallsDisplay, { toolCalls: message.toolCalls, label: toolUsedLabel }) }),
978
1060
  /* @__PURE__ */ jsx7(
979
1061
  StreamingText,