veryfront 0.0.72 → 0.0.74

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.
@@ -735,14 +735,497 @@ function Markdown({
735
735
  }
736
736
 
737
737
  // src/ai/react/components/chat.tsx
738
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
738
+ import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
739
+ function CircleIcon({ className }) {
740
+ return /* @__PURE__ */ jsx7(
741
+ "svg",
742
+ {
743
+ className: cn("size-4", className),
744
+ viewBox: "0 0 24 24",
745
+ fill: "none",
746
+ stroke: "currentColor",
747
+ strokeWidth: "2",
748
+ strokeLinecap: "round",
749
+ strokeLinejoin: "round",
750
+ children: /* @__PURE__ */ jsx7("circle", { cx: "12", cy: "12", r: "10" })
751
+ }
752
+ );
753
+ }
754
+ function ClockIcon({ className }) {
755
+ return /* @__PURE__ */ jsxs4(
756
+ "svg",
757
+ {
758
+ className: cn("size-4", className),
759
+ viewBox: "0 0 24 24",
760
+ fill: "none",
761
+ stroke: "currentColor",
762
+ strokeWidth: "2",
763
+ strokeLinecap: "round",
764
+ strokeLinejoin: "round",
765
+ children: [
766
+ /* @__PURE__ */ jsx7("circle", { cx: "12", cy: "12", r: "10" }),
767
+ /* @__PURE__ */ jsx7("polyline", { points: "12 6 12 12 16 14" })
768
+ ]
769
+ }
770
+ );
771
+ }
772
+ function CheckCircleIcon({ className }) {
773
+ return /* @__PURE__ */ jsxs4(
774
+ "svg",
775
+ {
776
+ className: cn("size-4", className),
777
+ viewBox: "0 0 24 24",
778
+ fill: "none",
779
+ stroke: "currentColor",
780
+ strokeWidth: "2",
781
+ strokeLinecap: "round",
782
+ strokeLinejoin: "round",
783
+ children: [
784
+ /* @__PURE__ */ jsx7("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }),
785
+ /* @__PURE__ */ jsx7("polyline", { points: "22 4 12 14.01 9 11.01" })
786
+ ]
787
+ }
788
+ );
789
+ }
790
+ function XCircleIcon({ className }) {
791
+ return /* @__PURE__ */ jsxs4(
792
+ "svg",
793
+ {
794
+ className: cn("size-4", className),
795
+ viewBox: "0 0 24 24",
796
+ fill: "none",
797
+ stroke: "currentColor",
798
+ strokeWidth: "2",
799
+ strokeLinecap: "round",
800
+ strokeLinejoin: "round",
801
+ children: [
802
+ /* @__PURE__ */ jsx7("circle", { cx: "12", cy: "12", r: "10" }),
803
+ /* @__PURE__ */ jsx7("line", { x1: "15", y1: "9", x2: "9", y2: "15" }),
804
+ /* @__PURE__ */ jsx7("line", { x1: "9", y1: "9", x2: "15", y2: "15" })
805
+ ]
806
+ }
807
+ );
808
+ }
809
+ function WrenchIcon({ className }) {
810
+ return /* @__PURE__ */ jsx7(
811
+ "svg",
812
+ {
813
+ className: cn("size-4", className),
814
+ viewBox: "0 0 24 24",
815
+ fill: "none",
816
+ stroke: "currentColor",
817
+ strokeWidth: "2",
818
+ strokeLinecap: "round",
819
+ strokeLinejoin: "round",
820
+ children: /* @__PURE__ */ jsx7("path", { d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" })
821
+ }
822
+ );
823
+ }
824
+ function ChevronDownIcon({ className }) {
825
+ return /* @__PURE__ */ jsx7(
826
+ "svg",
827
+ {
828
+ className: cn("size-4", className),
829
+ viewBox: "0 0 24 24",
830
+ fill: "none",
831
+ stroke: "currentColor",
832
+ strokeWidth: "2",
833
+ strokeLinecap: "round",
834
+ strokeLinejoin: "round",
835
+ children: /* @__PURE__ */ jsx7("polyline", { points: "6 9 12 15 18 9" })
836
+ }
837
+ );
838
+ }
839
+ function BrainIcon({ className }) {
840
+ return /* @__PURE__ */ jsxs4(
841
+ "svg",
842
+ {
843
+ className: cn("size-4", className),
844
+ viewBox: "0 0 24 24",
845
+ fill: "none",
846
+ stroke: "currentColor",
847
+ strokeWidth: "2",
848
+ strokeLinecap: "round",
849
+ strokeLinejoin: "round",
850
+ children: [
851
+ /* @__PURE__ */ jsx7("path", { d: "M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z" }),
852
+ /* @__PURE__ */ jsx7("path", { d: "M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z" }),
853
+ /* @__PURE__ */ jsx7("path", { d: "M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4" }),
854
+ /* @__PURE__ */ jsx7("path", { d: "M17.599 6.5a3 3 0 0 0 .399-1.375" }),
855
+ /* @__PURE__ */ jsx7("path", { d: "M6.003 5.125A3 3 0 0 0 6.401 6.5" }),
856
+ /* @__PURE__ */ jsx7("path", { d: "M3.477 10.896a4 4 0 0 1 .585-.396" }),
857
+ /* @__PURE__ */ jsx7("path", { d: "M19.938 10.5a4 4 0 0 1 .585.396" }),
858
+ /* @__PURE__ */ jsx7("path", { d: "M6 18a4 4 0 0 1-1.967-.516" }),
859
+ /* @__PURE__ */ jsx7("path", { d: "M19.967 17.484A4 4 0 0 1 18 18" })
860
+ ]
861
+ }
862
+ );
863
+ }
864
+ function MessageSquareIcon({ className }) {
865
+ return /* @__PURE__ */ jsx7(
866
+ "svg",
867
+ {
868
+ className: cn("size-4", className),
869
+ viewBox: "0 0 24 24",
870
+ fill: "none",
871
+ stroke: "currentColor",
872
+ strokeWidth: "2",
873
+ strokeLinecap: "round",
874
+ strokeLinejoin: "round",
875
+ children: /* @__PURE__ */ jsx7("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
876
+ }
877
+ );
878
+ }
879
+ function ArrowDownIcon({ className }) {
880
+ return /* @__PURE__ */ jsxs4(
881
+ "svg",
882
+ {
883
+ className: cn("size-4", className),
884
+ viewBox: "0 0 24 24",
885
+ fill: "none",
886
+ stroke: "currentColor",
887
+ strokeWidth: "2",
888
+ strokeLinecap: "round",
889
+ strokeLinejoin: "round",
890
+ children: [
891
+ /* @__PURE__ */ jsx7("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
892
+ /* @__PURE__ */ jsx7("polyline", { points: "19 12 12 19 5 12" })
893
+ ]
894
+ }
895
+ );
896
+ }
897
+ function RefreshCwIcon({ className }) {
898
+ return /* @__PURE__ */ jsxs4(
899
+ "svg",
900
+ {
901
+ className: cn("size-4", className),
902
+ viewBox: "0 0 24 24",
903
+ fill: "none",
904
+ stroke: "currentColor",
905
+ strokeWidth: "2",
906
+ strokeLinecap: "round",
907
+ strokeLinejoin: "round",
908
+ children: [
909
+ /* @__PURE__ */ jsx7("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }),
910
+ /* @__PURE__ */ jsx7("path", { d: "M21 3v5h-5" }),
911
+ /* @__PURE__ */ jsx7("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }),
912
+ /* @__PURE__ */ jsx7("path", { d: "M8 16H3v5" })
913
+ ]
914
+ }
915
+ );
916
+ }
917
+ function CopyIcon({ className }) {
918
+ return /* @__PURE__ */ jsxs4(
919
+ "svg",
920
+ {
921
+ className: cn("size-4", className),
922
+ viewBox: "0 0 24 24",
923
+ fill: "none",
924
+ stroke: "currentColor",
925
+ strokeWidth: "2",
926
+ strokeLinecap: "round",
927
+ strokeLinejoin: "round",
928
+ children: [
929
+ /* @__PURE__ */ jsx7("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
930
+ /* @__PURE__ */ jsx7("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
931
+ ]
932
+ }
933
+ );
934
+ }
935
+ function CheckIcon({ className }) {
936
+ return /* @__PURE__ */ jsx7(
937
+ "svg",
938
+ {
939
+ className: cn("size-4", className),
940
+ viewBox: "0 0 24 24",
941
+ fill: "none",
942
+ stroke: "currentColor",
943
+ strokeWidth: "2",
944
+ strokeLinecap: "round",
945
+ strokeLinejoin: "round",
946
+ children: /* @__PURE__ */ jsx7("polyline", { points: "20 6 9 17 4 12" })
947
+ }
948
+ );
949
+ }
950
+ function Shimmer({ children }) {
951
+ return /* @__PURE__ */ jsx7("span", { className: "relative inline-block overflow-hidden", children: /* @__PURE__ */ jsx7("span", { className: "animate-pulse", children }) });
952
+ }
953
+ function ReasoningCard({ text, isStreaming = false }) {
954
+ const [isOpen, setIsOpen] = React8.useState(true);
955
+ React8.useEffect(() => {
956
+ if (!isStreaming && isOpen) {
957
+ const timer = setTimeout(() => {
958
+ setIsOpen(false);
959
+ }, 1e3);
960
+ return () => clearTimeout(timer);
961
+ }
962
+ }, [isStreaming, isOpen]);
963
+ return /* @__PURE__ */ jsxs4("div", { className: "not-prose mb-4", children: [
964
+ /* @__PURE__ */ jsxs4(
965
+ "button",
966
+ {
967
+ type: "button",
968
+ onClick: () => setIsOpen(!isOpen),
969
+ className: "flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",
970
+ children: [
971
+ /* @__PURE__ */ jsx7(BrainIcon, { className: "size-4" }),
972
+ isStreaming ? /* @__PURE__ */ jsx7(Shimmer, { children: "Thinking..." }) : /* @__PURE__ */ jsx7("span", { children: "Thought process" }),
973
+ /* @__PURE__ */ jsx7(
974
+ ChevronDownIcon,
975
+ {
976
+ className: cn(
977
+ "size-4 transition-transform",
978
+ isOpen && "rotate-180"
979
+ )
980
+ }
981
+ )
982
+ ]
983
+ }
984
+ ),
985
+ isOpen && /* @__PURE__ */ jsx7("div", { className: "mt-4 text-sm text-muted-foreground border-l-2 border-muted pl-4 ml-2", children: /* @__PURE__ */ jsx7(Markdown, { className: "text-sm", children: text }) })
986
+ ] });
987
+ }
988
+ function Suggestion({ suggestion, onClick, className, icon }) {
989
+ return /* @__PURE__ */ jsxs4(
990
+ "button",
991
+ {
992
+ type: "button",
993
+ onClick: () => onClick?.(suggestion),
994
+ className: cn(
995
+ "group flex items-start gap-3 rounded-xl border border-border bg-background p-4 text-left text-sm text-foreground transition-all hover:bg-muted hover:border-muted-foreground/20",
996
+ className
997
+ ),
998
+ children: [
999
+ icon && /* @__PURE__ */ jsx7("span", { className: "shrink-0 text-muted-foreground group-hover:text-foreground transition-colors", children: icon }),
1000
+ /* @__PURE__ */ jsx7("span", { className: "line-clamp-2", children: suggestion })
1001
+ ]
1002
+ }
1003
+ );
1004
+ }
1005
+ function Suggestions({ children, className, layout = "grid" }) {
1006
+ if (layout === "horizontal") {
1007
+ return /* @__PURE__ */ jsx7("div", { className: cn("flex gap-2 overflow-x-auto pb-2 scrollbar-hide", className), children });
1008
+ }
1009
+ return /* @__PURE__ */ jsx7("div", { className: cn("grid grid-cols-2 gap-3 max-w-2xl mx-auto", className), children });
1010
+ }
1011
+ function ConversationEmptyState({
1012
+ icon,
1013
+ title = "What can I help with?",
1014
+ description,
1015
+ children,
1016
+ className
1017
+ }) {
1018
+ return /* @__PURE__ */ jsxs4("div", { className: cn("flex flex-col items-center justify-center text-center", className), children: [
1019
+ icon && /* @__PURE__ */ jsx7("div", { className: "mb-4 text-muted-foreground", children: icon }),
1020
+ /* @__PURE__ */ jsx7("h1", { className: "text-3xl font-semibold text-foreground", children: title }),
1021
+ description && /* @__PURE__ */ jsx7("p", { className: "mt-2 text-base text-muted-foreground max-w-md", children: description }),
1022
+ children
1023
+ ] });
1024
+ }
1025
+ function ConversationScrollButton({
1026
+ onClick,
1027
+ visible = true,
1028
+ className
1029
+ }) {
1030
+ if (!visible)
1031
+ return null;
1032
+ return /* @__PURE__ */ jsx7(
1033
+ "button",
1034
+ {
1035
+ type: "button",
1036
+ onClick,
1037
+ className: cn(
1038
+ "absolute bottom-4 left-1/2 -translate-x-1/2 rounded-full border border-border bg-background p-2 shadow-lg transition-all hover:bg-muted",
1039
+ className
1040
+ ),
1041
+ children: /* @__PURE__ */ jsx7(ArrowDownIcon, { className: "size-4" })
1042
+ }
1043
+ );
1044
+ }
1045
+ function MessageActions({ content, className }) {
1046
+ const [copied, setCopied] = React8.useState(false);
1047
+ const handleCopy = async () => {
1048
+ try {
1049
+ await navigator.clipboard.writeText(content);
1050
+ setCopied(true);
1051
+ setTimeout(() => setCopied(false), 2e3);
1052
+ } catch {
1053
+ const textarea = document.createElement("textarea");
1054
+ textarea.value = content;
1055
+ document.body.appendChild(textarea);
1056
+ textarea.select();
1057
+ document.execCommand("copy");
1058
+ document.body.removeChild(textarea);
1059
+ setCopied(true);
1060
+ setTimeout(() => setCopied(false), 2e3);
1061
+ }
1062
+ };
1063
+ return /* @__PURE__ */ jsx7("div", { className: cn("flex items-center gap-1 mt-2", className), children: /* @__PURE__ */ jsx7(
1064
+ "button",
1065
+ {
1066
+ type: "button",
1067
+ onClick: handleCopy,
1068
+ className: "inline-flex items-center gap-1 px-2 py-1 text-xs text-muted-foreground hover:text-foreground hover:bg-muted rounded transition-colors",
1069
+ title: copied ? "Copied!" : "Copy to clipboard",
1070
+ children: copied ? /* @__PURE__ */ jsxs4(Fragment4, { children: [
1071
+ /* @__PURE__ */ jsx7(CheckIcon, { className: "size-3" }),
1072
+ /* @__PURE__ */ jsx7("span", { children: "Copied" })
1073
+ ] }) : /* @__PURE__ */ jsxs4(Fragment4, { children: [
1074
+ /* @__PURE__ */ jsx7(CopyIcon, { className: "size-3" }),
1075
+ /* @__PURE__ */ jsx7("span", { children: "Copy" })
1076
+ ] })
1077
+ }
1078
+ ) });
1079
+ }
1080
+ function ToolStatusBadge({ state }) {
1081
+ const labels = {
1082
+ "input-streaming": "Pending",
1083
+ "input-available": "Running",
1084
+ "approval-requested": "Awaiting Approval",
1085
+ "approval-responded": "Responded",
1086
+ "output-available": "Completed",
1087
+ "output-error": "Error",
1088
+ "output-denied": "Denied",
1089
+ // Legacy states
1090
+ "call": "Running",
1091
+ "partial-call": "Running",
1092
+ "result": "Completed",
1093
+ "error": "Error"
1094
+ };
1095
+ const icons = {
1096
+ "input-streaming": /* @__PURE__ */ jsx7(CircleIcon, { className: "size-3.5" }),
1097
+ "input-available": /* @__PURE__ */ jsx7(ClockIcon, { className: "size-3.5 animate-pulse" }),
1098
+ "approval-requested": /* @__PURE__ */ jsx7(ClockIcon, { className: "size-3.5 text-yellow-600" }),
1099
+ "approval-responded": /* @__PURE__ */ jsx7(CheckCircleIcon, { className: "size-3.5 text-blue-600" }),
1100
+ "output-available": /* @__PURE__ */ jsx7(CheckCircleIcon, { className: "size-3.5 text-green-600" }),
1101
+ "output-error": /* @__PURE__ */ jsx7(XCircleIcon, { className: "size-3.5 text-red-600" }),
1102
+ "output-denied": /* @__PURE__ */ jsx7(XCircleIcon, { className: "size-3.5 text-orange-600" }),
1103
+ // Legacy states
1104
+ "call": /* @__PURE__ */ jsx7(ClockIcon, { className: "size-3.5 animate-pulse" }),
1105
+ "partial-call": /* @__PURE__ */ jsx7(ClockIcon, { className: "size-3.5 animate-pulse" }),
1106
+ "result": /* @__PURE__ */ jsx7(CheckCircleIcon, { className: "size-3.5 text-green-600" }),
1107
+ "error": /* @__PURE__ */ jsx7(XCircleIcon, { className: "size-3.5 text-red-600" })
1108
+ };
1109
+ return /* @__PURE__ */ jsxs4("span", { className: "inline-flex items-center gap-1.5 rounded-full bg-secondary px-2.5 py-0.5 text-xs font-medium text-secondary-foreground border border-border", children: [
1110
+ icons[state] || /* @__PURE__ */ jsx7(CircleIcon, { className: "size-3.5" }),
1111
+ labels[state] || state
1112
+ ] });
1113
+ }
1114
+ function formatJsonWithHighlight(obj) {
1115
+ if (obj === void 0 || obj === null)
1116
+ return null;
1117
+ const jsonStr = typeof obj === "string" ? obj : JSON.stringify(obj, null, 2);
1118
+ const highlighted = jsonStr.replace(/"([^"]+)":/g, '<span class="text-green-600 dark:text-green-400">"$1"</span>:').replace(/: "([^"]*)"/g, ': <span class="text-amber-600 dark:text-amber-400">"$1"</span>').replace(/: (\d+)/g, ': <span class="text-blue-600 dark:text-blue-400">$1</span>').replace(/: (true|false)/g, ': <span class="text-purple-600 dark:text-purple-400">$1</span>');
1119
+ return /* @__PURE__ */ jsx7(
1120
+ "pre",
1121
+ {
1122
+ className: "text-sm font-mono whitespace-pre-wrap",
1123
+ dangerouslySetInnerHTML: { __html: highlighted }
1124
+ }
1125
+ );
1126
+ }
1127
+ function renderOutputAsTable(output) {
1128
+ if (!Array.isArray(output) || output.length === 0)
1129
+ return null;
1130
+ const firstItem = output[0];
1131
+ if (typeof firstItem !== "object" || firstItem === null)
1132
+ return null;
1133
+ const keys = Object.keys(firstItem);
1134
+ if (keys.length === 0)
1135
+ return null;
1136
+ return /* @__PURE__ */ jsx7("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs4("table", { className: "min-w-full text-sm", children: [
1137
+ /* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsx7("tr", { className: "border-b border-neutral-200 dark:border-neutral-700", children: keys.map((key) => /* @__PURE__ */ jsx7(
1138
+ "th",
1139
+ {
1140
+ className: "px-4 py-2 text-left font-semibold text-neutral-900 dark:text-neutral-100",
1141
+ children: key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
1142
+ },
1143
+ key
1144
+ )) }) }),
1145
+ /* @__PURE__ */ jsx7("tbody", { children: output.map((row, i) => /* @__PURE__ */ jsx7("tr", { className: "border-b border-neutral-100 dark:border-neutral-800", children: keys.map((key) => /* @__PURE__ */ jsx7("td", { className: "px-4 py-2 text-neutral-700 dark:text-neutral-300", children: String(row[key] ?? "") }, key)) }, i)) })
1146
+ ] }) });
1147
+ }
1148
+ function ToolCallCard({ tool }) {
1149
+ const [isExpanded, setIsExpanded] = React8.useState(true);
1150
+ const tableOutput = tool.output !== void 0 ? renderOutputAsTable(tool.output) : null;
1151
+ return /* @__PURE__ */ jsxs4("div", { className: "not-prose w-full rounded-md border border-border bg-card", children: [
1152
+ /* @__PURE__ */ jsxs4(
1153
+ "button",
1154
+ {
1155
+ type: "button",
1156
+ onClick: () => setIsExpanded(!isExpanded),
1157
+ className: "group flex w-full items-center justify-between gap-4 p-3 hover:bg-muted/50 transition-colors",
1158
+ children: [
1159
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
1160
+ /* @__PURE__ */ jsx7(WrenchIcon, { className: "size-4 text-muted-foreground" }),
1161
+ /* @__PURE__ */ jsx7("span", { className: "font-medium text-sm text-foreground", children: tool.toolName }),
1162
+ /* @__PURE__ */ jsx7(ToolStatusBadge, { state: tool.state })
1163
+ ] }),
1164
+ /* @__PURE__ */ jsx7(
1165
+ ChevronDownIcon,
1166
+ {
1167
+ className: cn(
1168
+ "size-4 text-muted-foreground transition-transform",
1169
+ isExpanded && "rotate-180"
1170
+ )
1171
+ }
1172
+ )
1173
+ ]
1174
+ }
1175
+ ),
1176
+ isExpanded && /* @__PURE__ */ jsxs4("div", { className: "border-t border-border", children: [
1177
+ tool.input !== void 0 && /* @__PURE__ */ jsxs4("div", { className: "space-y-2 overflow-hidden p-4", children: [
1178
+ /* @__PURE__ */ jsx7("h4", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wide", children: "Parameters" }),
1179
+ /* @__PURE__ */ jsx7("div", { className: "rounded-md bg-muted/50 p-3", children: formatJsonWithHighlight(tool.input) })
1180
+ ] }),
1181
+ tool.output !== void 0 && /* @__PURE__ */ jsxs4("div", { className: "space-y-2 p-4 border-t border-border", children: [
1182
+ /* @__PURE__ */ jsx7("h4", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wide", children: "Result" }),
1183
+ /* @__PURE__ */ jsx7("div", { className: "overflow-x-auto rounded-md bg-muted/50 text-foreground", children: tableOutput || /* @__PURE__ */ jsx7("div", { className: "p-3", children: formatJsonWithHighlight(tool.output) }) })
1184
+ ] }),
1185
+ tool.errorText && /* @__PURE__ */ jsxs4("div", { className: "space-y-2 p-4 border-t border-border", children: [
1186
+ /* @__PURE__ */ jsx7("h4", { className: "font-medium text-destructive text-xs uppercase tracking-wide", children: "Error" }),
1187
+ /* @__PURE__ */ jsx7("div", { className: "rounded-md bg-destructive/10 text-destructive p-3 text-sm", children: tool.errorText })
1188
+ ] })
1189
+ ] })
1190
+ ] });
1191
+ }
739
1192
  function getTextContent(message) {
740
1193
  return message.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
741
1194
  }
742
- function getToolParts(message) {
743
- return message.parts.filter(
744
- (p) => p.type.startsWith("tool-") || p.type === "dynamic-tool"
745
- );
1195
+ function isToolPart(part) {
1196
+ return part.type.startsWith("tool-") && part.type !== "tool-result" || part.type === "dynamic-tool";
1197
+ }
1198
+ function isReasoningPart(part) {
1199
+ return part.type === "reasoning";
1200
+ }
1201
+ function groupPartsInOrder(parts) {
1202
+ const groups = [];
1203
+ let currentTextGroup = [];
1204
+ for (const part of parts) {
1205
+ if (part.type === "text") {
1206
+ currentTextGroup.push(part.text);
1207
+ } else if (isToolPart(part)) {
1208
+ if (currentTextGroup.length > 0) {
1209
+ groups.push({ type: "text", content: currentTextGroup.join("") });
1210
+ currentTextGroup = [];
1211
+ }
1212
+ groups.push({ type: "tool", tool: part });
1213
+ } else if (isReasoningPart(part)) {
1214
+ if (currentTextGroup.length > 0) {
1215
+ groups.push({ type: "text", content: currentTextGroup.join("") });
1216
+ currentTextGroup = [];
1217
+ }
1218
+ groups.push({
1219
+ type: "reasoning",
1220
+ text: part.text,
1221
+ isStreaming: part.state === "streaming"
1222
+ });
1223
+ }
1224
+ }
1225
+ if (currentTextGroup.length > 0) {
1226
+ groups.push({ type: "text", content: currentTextGroup.join("") });
1227
+ }
1228
+ return groups;
746
1229
  }
747
1230
  var Chat = React8.forwardRef(
748
1231
  ({
@@ -753,6 +1236,7 @@ var Chat = React8.forwardRef(
753
1236
  onSubmit,
754
1237
  handleSubmit,
755
1238
  stop,
1239
+ reload,
756
1240
  enableVoice = false,
757
1241
  onVoice,
758
1242
  setInput,
@@ -764,7 +1248,12 @@ var Chat = React8.forwardRef(
764
1248
  theme: userTheme,
765
1249
  renderMessage,
766
1250
  renderTool,
767
- multiline = false
1251
+ multiline = false,
1252
+ suggestions,
1253
+ onSuggestionClick,
1254
+ emptyState,
1255
+ showScrollButton = false,
1256
+ showMessageActions = true
768
1257
  }, ref) => {
769
1258
  const theme = mergeThemes(defaultChatTheme, userTheme);
770
1259
  const messagesEndRef = React8.useRef(null);
@@ -796,54 +1285,106 @@ var Chat = React8.forwardRef(
796
1285
  className: cn(theme.container, className),
797
1286
  style: { maxHeight },
798
1287
  children: [
799
- /* @__PURE__ */ jsx7(MessageList, { className: "flex-1 min-h-0 overflow-y-auto", children: /* @__PURE__ */ jsxs4("div", { className: "max-w-2xl mx-auto px-4 py-4 space-y-2", children: [
800
- messages.map((msg) => {
801
- const content = getTextContent(msg);
802
- const toolParts = getToolParts(msg);
803
- return renderMessage ? /* @__PURE__ */ jsx7(React8.Fragment, { children: renderMessage(msg) }, msg.id) : /* @__PURE__ */ jsx7(
804
- MessageItem,
1288
+ /* @__PURE__ */ jsxs4(MessageList, { className: "flex-1 min-h-0 overflow-y-auto relative", children: [
1289
+ messages.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "flex flex-col items-center justify-center h-full px-4", children: [
1290
+ /* @__PURE__ */ jsx7("div", { className: "flex-1" }),
1291
+ /* @__PURE__ */ jsx7(
1292
+ ConversationEmptyState,
805
1293
  {
806
- role: msg.role,
807
- className: cn(
808
- "flex",
809
- msg.role === "user" ? "justify-end" : "justify-start"
810
- ),
811
- children: /* @__PURE__ */ jsxs4("div", { className: theme.message?.[msg.role] || theme.message?.assistant, children: [
812
- msg.role === "user" ? /* @__PURE__ */ jsx7("p", { className: "whitespace-pre-wrap text-[15px] leading-relaxed", children: content }) : /* @__PURE__ */ jsx7(Markdown, { className: "text-[15px] leading-relaxed", children: content }),
813
- toolParts.length > 0 && /* @__PURE__ */ jsx7("div", { className: "mt-2 space-y-1", children: toolParts.map(
814
- (tool) => renderTool ? /* @__PURE__ */ jsx7(React8.Fragment, { children: renderTool(tool) }, tool.toolCallId) : /* @__PURE__ */ jsxs4(
815
- "div",
816
- {
817
- className: cn(
818
- "text-xs rounded px-2 py-1",
819
- tool.type === "dynamic-tool" ? "bg-blue-50 dark:bg-blue-900/20" : "bg-neutral-100 dark:bg-neutral-800"
820
- ),
821
- children: [
822
- /* @__PURE__ */ jsx7("span", { className: "font-mono", children: tool.toolName }),
823
- /* @__PURE__ */ jsxs4("span", { className: "ml-2 opacity-70", children: [
824
- "[",
825
- tool.state,
826
- "]"
827
- ] }),
828
- tool.errorText && /* @__PURE__ */ jsx7("div", { className: "text-red-600 dark:text-red-400 mt-1", children: tool.errorText })
829
- ]
830
- },
831
- tool.toolCallId
832
- )
833
- ) })
834
- ] })
1294
+ icon: emptyState?.icon || /* @__PURE__ */ jsx7(MessageSquareIcon, { className: "size-10" }),
1295
+ title: emptyState?.title || "What can I help with?",
1296
+ description: emptyState?.description
1297
+ }
1298
+ ),
1299
+ suggestions && suggestions.length > 0 && /* @__PURE__ */ jsx7("div", { className: "w-full max-w-2xl mt-6 mb-8", children: /* @__PURE__ */ jsx7(Suggestions, { layout: "grid", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx7(
1300
+ Suggestion,
1301
+ {
1302
+ suggestion,
1303
+ onClick: onSuggestionClick
835
1304
  },
836
- msg.id
837
- );
838
- }),
839
- isLoading && /* @__PURE__ */ jsx7("div", { className: "flex justify-start", children: /* @__PURE__ */ jsx7("div", { className: "bg-neutral-100 dark:bg-neutral-800 rounded-[20px] rounded-bl-[4px] px-4 py-3", children: /* @__PURE__ */ jsxs4("div", { className: "flex gap-1.5 items-center", children: [
840
- /* @__PURE__ */ jsx7("span", { className: cn(theme.loading) }),
841
- /* @__PURE__ */ jsx7("span", { className: cn(theme.loading), style: { animationDelay: "0.15s" } }),
842
- /* @__PURE__ */ jsx7("span", { className: cn(theme.loading), style: { animationDelay: "0.3s" } })
843
- ] }) }) }),
844
- /* @__PURE__ */ jsx7("div", { ref: messagesEndRef })
845
- ] }) }),
846
- error && /* @__PURE__ */ jsx7("div", { className: "mx-4 mb-2 px-4 py-3 bg-red-50 dark:bg-red-900/20 rounded-2xl text-red-600 dark:text-red-400 text-sm", children: error.message }),
1305
+ suggestion
1306
+ )) }) }),
1307
+ /* @__PURE__ */ jsx7("div", { className: "flex-1" })
1308
+ ] }) : /* @__PURE__ */ jsxs4("div", { className: "max-w-2xl mx-auto px-4 py-4 space-y-2", children: [
1309
+ messages.map((msg) => {
1310
+ if (msg.role === "user") {
1311
+ const content = getTextContent(msg);
1312
+ return renderMessage ? /* @__PURE__ */ jsx7(React8.Fragment, { children: renderMessage(msg) }, msg.id) : /* @__PURE__ */ jsx7(
1313
+ MessageItem,
1314
+ {
1315
+ role: msg.role,
1316
+ className: cn("flex", "justify-end"),
1317
+ children: /* @__PURE__ */ jsx7("div", { className: theme.message?.[msg.role] || theme.message?.user, children: /* @__PURE__ */ jsx7("p", { className: "whitespace-pre-wrap text-[15px] leading-relaxed", children: content }) })
1318
+ },
1319
+ msg.id
1320
+ );
1321
+ }
1322
+ const partGroups = groupPartsInOrder(msg.parts);
1323
+ const textContent = getTextContent(msg);
1324
+ return renderMessage ? /* @__PURE__ */ jsx7(React8.Fragment, { children: renderMessage(msg) }, msg.id) : /* @__PURE__ */ jsx7(
1325
+ MessageItem,
1326
+ {
1327
+ role: msg.role,
1328
+ className: cn("flex", "justify-start"),
1329
+ children: /* @__PURE__ */ jsxs4("div", { className: theme.message?.[msg.role] || theme.message?.assistant, children: [
1330
+ partGroups.map((group, index) => {
1331
+ if (group.type === "text") {
1332
+ return /* @__PURE__ */ jsx7(
1333
+ Markdown,
1334
+ {
1335
+ className: "text-[15px] leading-relaxed",
1336
+ children: group.content
1337
+ },
1338
+ `text-${index}`
1339
+ );
1340
+ }
1341
+ if (group.type === "reasoning") {
1342
+ return /* @__PURE__ */ jsx7(
1343
+ ReasoningCard,
1344
+ {
1345
+ text: group.text,
1346
+ isStreaming: group.isStreaming
1347
+ },
1348
+ `reasoning-${index}`
1349
+ );
1350
+ }
1351
+ return /* @__PURE__ */ jsx7("div", { className: "my-3", children: renderTool ? renderTool(group.tool) : /* @__PURE__ */ jsx7(ToolCallCard, { tool: group.tool }) }, group.tool.toolCallId);
1352
+ }),
1353
+ showMessageActions && textContent && /* @__PURE__ */ jsx7(MessageActions, { content: textContent })
1354
+ ] })
1355
+ },
1356
+ msg.id
1357
+ );
1358
+ }),
1359
+ isLoading && /* @__PURE__ */ jsx7("div", { className: "flex justify-start", children: /* @__PURE__ */ jsx7("div", { className: "bg-neutral-100 dark:bg-neutral-800 rounded-[20px] rounded-bl-[4px] px-4 py-3", children: /* @__PURE__ */ jsxs4("div", { className: "flex gap-1.5 items-center", children: [
1360
+ /* @__PURE__ */ jsx7("span", { className: cn(theme.loading) }),
1361
+ /* @__PURE__ */ jsx7("span", { className: cn(theme.loading), style: { animationDelay: "0.15s" } }),
1362
+ /* @__PURE__ */ jsx7("span", { className: cn(theme.loading), style: { animationDelay: "0.3s" } })
1363
+ ] }) }) }),
1364
+ /* @__PURE__ */ jsx7("div", { ref: messagesEndRef })
1365
+ ] }),
1366
+ showScrollButton && /* @__PURE__ */ jsx7(
1367
+ ConversationScrollButton,
1368
+ {
1369
+ onClick: () => messagesEndRef.current?.scrollIntoView({ behavior: "smooth" })
1370
+ }
1371
+ )
1372
+ ] }),
1373
+ error && /* @__PURE__ */ jsxs4("div", { className: "mx-4 mb-2 px-4 py-3 bg-red-50 dark:bg-red-900/20 rounded-2xl text-red-600 dark:text-red-400 text-sm flex items-center justify-between gap-3", children: [
1374
+ /* @__PURE__ */ jsx7("span", { children: error.message }),
1375
+ reload && /* @__PURE__ */ jsxs4(
1376
+ "button",
1377
+ {
1378
+ type: "button",
1379
+ onClick: reload,
1380
+ className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-red-600 dark:text-red-400 bg-red-100 dark:bg-red-900/40 hover:bg-red-200 dark:hover:bg-red-900/60 rounded-lg transition-colors",
1381
+ children: [
1382
+ /* @__PURE__ */ jsx7(RefreshCwIcon, { className: "size-3.5" }),
1383
+ "Retry"
1384
+ ]
1385
+ }
1386
+ )
1387
+ ] }),
847
1388
  /* @__PURE__ */ jsx7("div", { className: "flex-shrink-0 bg-white dark:bg-neutral-900 border-t border-neutral-200 dark:border-neutral-800", children: /* @__PURE__ */ jsx7(
848
1389
  "form",
849
1390
  {