@townco/ui 0.1.6 → 0.1.8

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.
Files changed (255) hide show
  1. package/README.md +11 -11
  2. package/dist/core/hooks/index.d.ts +1 -0
  3. package/dist/core/hooks/index.js +1 -0
  4. package/dist/core/hooks/use-chat-input.d.ts +17 -17
  5. package/dist/core/hooks/use-chat-input.js +55 -64
  6. package/dist/core/hooks/use-chat-messages.d.ts +11 -11
  7. package/dist/core/hooks/use-chat-messages.js +114 -121
  8. package/dist/core/hooks/use-chat-session.d.ts +5 -5
  9. package/dist/core/hooks/use-chat-session.js +80 -78
  10. package/dist/core/hooks/use-media-query.d.ts +5 -5
  11. package/dist/core/hooks/use-media-query.js +42 -38
  12. package/dist/core/index.d.ts +1 -1
  13. package/dist/core/index.js +1 -1
  14. package/dist/core/schemas/chat.d.ts +56 -83
  15. package/dist/core/schemas/chat.js +25 -27
  16. package/dist/core/store/chat-store.d.ts +22 -28
  17. package/dist/core/store/chat-store.js +50 -59
  18. package/dist/gui/components/Button.d.ts +7 -23
  19. package/dist/gui/components/Button.js +27 -40
  20. package/dist/gui/components/Card.d.ts +7 -26
  21. package/dist/gui/components/Card.js +8 -54
  22. package/dist/gui/components/ChatHeader.d.ts +31 -58
  23. package/dist/gui/components/ChatHeader.js +68 -171
  24. package/dist/gui/components/ChatInput.d.ts +54 -58
  25. package/dist/gui/components/ChatInput.js +207 -194
  26. package/dist/gui/components/ChatInputCommandMenu.d.ts +20 -0
  27. package/dist/gui/components/ChatInputCommandMenu.js +62 -0
  28. package/dist/gui/components/ChatLayout.d.ts +41 -71
  29. package/dist/gui/components/ChatLayout.js +87 -214
  30. package/dist/gui/components/ChatPanelTabContent.d.ts +9 -18
  31. package/dist/gui/components/ChatPanelTabContent.js +10 -88
  32. package/dist/gui/components/ChatSecondaryPanel.d.ts +11 -14
  33. package/dist/gui/components/ChatSecondaryPanel.js +38 -115
  34. package/dist/gui/components/ChatSidebar.d.ts +13 -26
  35. package/dist/gui/components/ChatSidebar.js +14 -48
  36. package/dist/gui/components/ChatStatus.d.ts +2 -4
  37. package/dist/gui/components/ChatStatus.js +34 -45
  38. package/dist/gui/components/Conversation.d.ts +14 -17
  39. package/dist/gui/components/Conversation.js +83 -143
  40. package/dist/gui/components/Dialog.d.ts +11 -57
  41. package/dist/gui/components/Dialog.js +8 -84
  42. package/dist/gui/components/DropdownMenu.d.ts +20 -101
  43. package/dist/gui/components/DropdownMenu.js +14 -161
  44. package/dist/gui/components/HeightTransition.d.ts +7 -12
  45. package/dist/gui/components/HeightTransition.js +77 -88
  46. package/dist/gui/components/Input.d.ts +6 -13
  47. package/dist/gui/components/Input.js +16 -27
  48. package/dist/gui/components/Label.d.ts +1 -7
  49. package/dist/gui/components/Label.js +2 -12
  50. package/dist/gui/components/MarkdownRenderer.d.ts +4 -6
  51. package/dist/gui/components/MarkdownRenderer.js +81 -178
  52. package/dist/gui/components/Message.d.ts +22 -25
  53. package/dist/gui/components/Message.js +97 -44
  54. package/dist/gui/components/MessageContent.d.ts +22 -29
  55. package/dist/gui/components/MessageContent.js +85 -157
  56. package/dist/gui/components/Reasoning.d.ts +24 -30
  57. package/dist/gui/components/Reasoning.js +60 -187
  58. package/dist/gui/components/Response.d.ts +9 -11
  59. package/dist/gui/components/Response.js +90 -229
  60. package/dist/gui/components/Select.d.ts +10 -69
  61. package/dist/gui/components/Select.js +12 -118
  62. package/dist/gui/components/Sonner.d.ts +1 -3
  63. package/dist/gui/components/Sonner.js +18 -29
  64. package/dist/gui/components/Tabs.d.ts +4 -24
  65. package/dist/gui/components/Tabs.js +4 -32
  66. package/dist/gui/components/Task.d.ts +24 -28
  67. package/dist/gui/components/Task.js +31 -164
  68. package/dist/gui/components/Textarea.d.ts +7 -15
  69. package/dist/gui/components/Textarea.js +46 -63
  70. package/dist/gui/components/ThinkingBlock.d.ts +10 -20
  71. package/dist/gui/components/ThinkingBlock.js +35 -134
  72. package/dist/gui/components/TodoList.d.ts +10 -12
  73. package/dist/gui/components/TodoList.js +7 -22
  74. package/dist/gui/components/TodoListItem.d.ts +6 -9
  75. package/dist/gui/components/TodoListItem.js +4 -18
  76. package/dist/gui/components/index.d.ts +16 -59
  77. package/dist/gui/components/index.js +18 -42
  78. package/dist/gui/lib/utils.js +1 -1
  79. package/dist/index.d.ts +1 -1
  80. package/dist/index.js +1 -1
  81. package/dist/index.test.js +1 -0
  82. package/dist/sdk/client/acp-client.d.ts +76 -88
  83. package/dist/sdk/client/acp-client.js +217 -215
  84. package/dist/sdk/index.d.ts +1 -1
  85. package/dist/sdk/index.js +1 -1
  86. package/dist/sdk/schemas/agent.d.ts +64 -111
  87. package/dist/sdk/schemas/agent.js +24 -24
  88. package/dist/sdk/schemas/message.d.ts +147 -245
  89. package/dist/sdk/schemas/message.js +40 -40
  90. package/dist/sdk/schemas/session.d.ts +135 -219
  91. package/dist/sdk/schemas/session.js +27 -27
  92. package/dist/sdk/transports/http.d.ts +55 -55
  93. package/dist/sdk/transports/http.js +469 -472
  94. package/dist/sdk/transports/stdio.d.ts +20 -20
  95. package/dist/sdk/transports/stdio.js +286 -289
  96. package/dist/sdk/transports/types.d.ts +42 -42
  97. package/dist/sdk/transports/websocket.d.ts +12 -12
  98. package/dist/sdk/transports/websocket.js +46 -52
  99. package/dist/tui/components/ChatView.d.ts +2 -4
  100. package/dist/tui/components/ChatView.js +18 -51
  101. package/dist/tui/components/GameOfLife.js +35 -64
  102. package/dist/tui/components/InputBox.d.ts +11 -18
  103. package/dist/tui/components/InputBox.js +10 -70
  104. package/dist/tui/components/MessageList.d.ts +2 -4
  105. package/dist/tui/components/MessageList.js +10 -37
  106. package/dist/tui/components/MultiSelect.d.ts +10 -15
  107. package/dist/tui/components/MultiSelect.js +73 -116
  108. package/dist/tui/components/ReadlineInput.d.ts +6 -12
  109. package/dist/tui/components/ReadlineInput.js +237 -252
  110. package/dist/tui/components/SingleSelect.d.ts +9 -15
  111. package/dist/tui/components/SingleSelect.js +43 -84
  112. package/dist/tui/components/StatusBar.d.ts +6 -11
  113. package/dist/tui/components/StatusBar.js +67 -102
  114. package/dist/tui/index.d.ts +1 -1
  115. package/dist/tui/index.js +1 -1
  116. package/package.json +6 -4
  117. package/src/styles/global.css +2 -0
  118. package/dist/core/hooks/index.d.ts.map +0 -1
  119. package/dist/core/hooks/index.js.map +0 -1
  120. package/dist/core/hooks/use-chat-input.d.ts.map +0 -1
  121. package/dist/core/hooks/use-chat-input.js.map +0 -1
  122. package/dist/core/hooks/use-chat-messages.d.ts.map +0 -1
  123. package/dist/core/hooks/use-chat-messages.js.map +0 -1
  124. package/dist/core/hooks/use-chat-session.d.ts.map +0 -1
  125. package/dist/core/hooks/use-chat-session.js.map +0 -1
  126. package/dist/core/index.d.ts.map +0 -1
  127. package/dist/core/index.js.map +0 -1
  128. package/dist/core/schemas/chat.d.ts.map +0 -1
  129. package/dist/core/schemas/chat.js.map +0 -1
  130. package/dist/core/schemas/index.d.ts.map +0 -1
  131. package/dist/core/schemas/index.js.map +0 -1
  132. package/dist/core/store/chat-store.d.ts.map +0 -1
  133. package/dist/core/store/chat-store.js.map +0 -1
  134. package/dist/gui/components/Button.d.ts.map +0 -1
  135. package/dist/gui/components/Button.js.map +0 -1
  136. package/dist/gui/components/Card.d.ts.map +0 -1
  137. package/dist/gui/components/Card.js.map +0 -1
  138. package/dist/gui/components/ChatInput.d.ts.map +0 -1
  139. package/dist/gui/components/ChatInput.js.map +0 -1
  140. package/dist/gui/components/ChatInterface.d.ts +0 -12
  141. package/dist/gui/components/ChatInterface.d.ts.map +0 -1
  142. package/dist/gui/components/ChatInterface.js +0 -204
  143. package/dist/gui/components/ChatInterface.js.map +0 -1
  144. package/dist/gui/components/ChatPreview.d.ts +0 -12
  145. package/dist/gui/components/ChatPreview.d.ts.map +0 -1
  146. package/dist/gui/components/ChatPreview.js +0 -214
  147. package/dist/gui/components/ChatPreview.js.map +0 -1
  148. package/dist/gui/components/ChatSecondaryPanel.d.ts.map +0 -1
  149. package/dist/gui/components/ChatSecondaryPanel.js.map +0 -1
  150. package/dist/gui/components/ChatStatus.d.ts.map +0 -1
  151. package/dist/gui/components/ChatStatus.js.map +0 -1
  152. package/dist/gui/components/ChatView.d.ts +0 -8
  153. package/dist/gui/components/ChatView.d.ts.map +0 -1
  154. package/dist/gui/components/ChatView.js +0 -42
  155. package/dist/gui/components/ChatView.js.map +0 -1
  156. package/dist/gui/components/ConfigPanel.d.ts +0 -20
  157. package/dist/gui/components/ConfigPanel.d.ts.map +0 -1
  158. package/dist/gui/components/ConfigPanel.js +0 -225
  159. package/dist/gui/components/ConfigPanel.js.map +0 -1
  160. package/dist/gui/components/Conversation.d.ts.map +0 -1
  161. package/dist/gui/components/Conversation.js.map +0 -1
  162. package/dist/gui/components/Dialog.d.ts.map +0 -1
  163. package/dist/gui/components/Dialog.js.map +0 -1
  164. package/dist/gui/components/HeightTransition.d.ts.map +0 -1
  165. package/dist/gui/components/HeightTransition.js.map +0 -1
  166. package/dist/gui/components/Input.d.ts.map +0 -1
  167. package/dist/gui/components/Input.js.map +0 -1
  168. package/dist/gui/components/InputBox.d.ts +0 -21
  169. package/dist/gui/components/InputBox.d.ts.map +0 -1
  170. package/dist/gui/components/InputBox.js +0 -90
  171. package/dist/gui/components/InputBox.js.map +0 -1
  172. package/dist/gui/components/Label.d.ts.map +0 -1
  173. package/dist/gui/components/Label.js.map +0 -1
  174. package/dist/gui/components/MarkdownRenderer.d.ts.map +0 -1
  175. package/dist/gui/components/MarkdownRenderer.js.map +0 -1
  176. package/dist/gui/components/Message.d.ts.map +0 -1
  177. package/dist/gui/components/Message.js.map +0 -1
  178. package/dist/gui/components/MessageContent.d.ts.map +0 -1
  179. package/dist/gui/components/MessageContent.js.map +0 -1
  180. package/dist/gui/components/MessageList.d.ts.map +0 -1
  181. package/dist/gui/components/MessageList.js.map +0 -1
  182. package/dist/gui/components/PlaygroundLayout.d.ts +0 -14
  183. package/dist/gui/components/PlaygroundLayout.d.ts.map +0 -1
  184. package/dist/gui/components/PlaygroundLayout.js +0 -49
  185. package/dist/gui/components/PlaygroundLayout.js.map +0 -1
  186. package/dist/gui/components/Reasoning.d.ts.map +0 -1
  187. package/dist/gui/components/Reasoning.js.map +0 -1
  188. package/dist/gui/components/Response.d.ts.map +0 -1
  189. package/dist/gui/components/Response.js.map +0 -1
  190. package/dist/gui/components/Select.d.ts.map +0 -1
  191. package/dist/gui/components/Select.js.map +0 -1
  192. package/dist/gui/components/StatusBar.d.ts +0 -12
  193. package/dist/gui/components/StatusBar.d.ts.map +0 -1
  194. package/dist/gui/components/StatusBar.js +0 -58
  195. package/dist/gui/components/StatusBar.js.map +0 -1
  196. package/dist/gui/components/Tabs.d.ts.map +0 -1
  197. package/dist/gui/components/Tabs.js.map +0 -1
  198. package/dist/gui/components/Task.d.ts.map +0 -1
  199. package/dist/gui/components/Task.js.map +0 -1
  200. package/dist/gui/components/Textarea.d.ts.map +0 -1
  201. package/dist/gui/components/Textarea.js.map +0 -1
  202. package/dist/gui/components/ThinkingBlock.d.ts.map +0 -1
  203. package/dist/gui/components/ThinkingBlock.js.map +0 -1
  204. package/dist/gui/components/TodoList.d.ts.map +0 -1
  205. package/dist/gui/components/TodoList.js.map +0 -1
  206. package/dist/gui/components/TodoListItem.d.ts.map +0 -1
  207. package/dist/gui/components/TodoListItem.js.map +0 -1
  208. package/dist/gui/components/index.d.ts.map +0 -1
  209. package/dist/gui/components/index.js.map +0 -1
  210. package/dist/gui/index.d.ts.map +0 -1
  211. package/dist/gui/index.js.map +0 -1
  212. package/dist/gui/lib/utils.d.ts.map +0 -1
  213. package/dist/gui/lib/utils.js.map +0 -1
  214. package/dist/index.d.ts.map +0 -1
  215. package/dist/index.js.map +0 -1
  216. package/dist/sdk/client/acp-client.d.ts.map +0 -1
  217. package/dist/sdk/client/acp-client.js.map +0 -1
  218. package/dist/sdk/client/index.d.ts.map +0 -1
  219. package/dist/sdk/client/index.js.map +0 -1
  220. package/dist/sdk/index.d.ts.map +0 -1
  221. package/dist/sdk/index.js.map +0 -1
  222. package/dist/sdk/schemas/agent.d.ts.map +0 -1
  223. package/dist/sdk/schemas/agent.js.map +0 -1
  224. package/dist/sdk/schemas/index.d.ts.map +0 -1
  225. package/dist/sdk/schemas/index.js.map +0 -1
  226. package/dist/sdk/schemas/message.d.ts.map +0 -1
  227. package/dist/sdk/schemas/message.js.map +0 -1
  228. package/dist/sdk/schemas/session.d.ts.map +0 -1
  229. package/dist/sdk/schemas/session.js.map +0 -1
  230. package/dist/sdk/transports/http.d.ts.map +0 -1
  231. package/dist/sdk/transports/http.js.map +0 -1
  232. package/dist/sdk/transports/index.d.ts.map +0 -1
  233. package/dist/sdk/transports/index.js.map +0 -1
  234. package/dist/sdk/transports/stdio.d.ts.map +0 -1
  235. package/dist/sdk/transports/stdio.js.map +0 -1
  236. package/dist/sdk/transports/types.d.ts.map +0 -1
  237. package/dist/sdk/transports/types.js.map +0 -1
  238. package/dist/sdk/transports/websocket.d.ts.map +0 -1
  239. package/dist/sdk/transports/websocket.js.map +0 -1
  240. package/dist/tui/components/ChatView.d.ts.map +0 -1
  241. package/dist/tui/components/ChatView.js.map +0 -1
  242. package/dist/tui/components/GameOfLife.d.ts.map +0 -1
  243. package/dist/tui/components/GameOfLife.js.map +0 -1
  244. package/dist/tui/components/InputBox.d.ts.map +0 -1
  245. package/dist/tui/components/InputBox.js.map +0 -1
  246. package/dist/tui/components/MessageList.d.ts.map +0 -1
  247. package/dist/tui/components/MessageList.js.map +0 -1
  248. package/dist/tui/components/ReadlineInput.d.ts.map +0 -1
  249. package/dist/tui/components/ReadlineInput.js.map +0 -1
  250. package/dist/tui/components/StatusBar.d.ts.map +0 -1
  251. package/dist/tui/components/StatusBar.js.map +0 -1
  252. package/dist/tui/components/index.d.ts.map +0 -1
  253. package/dist/tui/components/index.js.map +0 -1
  254. package/dist/tui/index.d.ts.map +0 -1
  255. package/dist/tui/index.js.map +0 -1
@@ -1,54 +1,107 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  import { cva } from "class-variance-authority";
2
3
  import * as React from "react";
3
- import { jsx as _jsx } from "react/jsx-runtime";
4
4
  import { cn } from "../lib/utils.js";
5
-
6
5
  /**
7
6
  * Message wrapper component inspired by shadcn.io/ai
8
7
  * Provides role-based layout and styling for chat messages
9
8
  */
10
9
  const messageVariants = cva("flex animate-fadeIn", {
11
- variants: {
12
- role: {
13
- user: "max-w-[80%] self-end ml-auto",
14
- assistant: "self-start mr-auto",
15
- system: "self-start mr-auto max-w-full",
16
- },
17
- layout: {
18
- default: "",
19
- full: "max-w-full",
20
- compact: "max-w-[90%]",
21
- },
22
- },
23
- defaultVariants: {
24
- role: "assistant",
25
- layout: "default",
26
- },
10
+ variants: {
11
+ role: {
12
+ user: "max-w-[80%] self-end ml-auto mr-2",
13
+ assistant: "self-start mr-auto",
14
+ system: "self-start mr-auto max-w-full",
15
+ },
16
+ layout: {
17
+ default: "",
18
+ full: "max-w-full",
19
+ compact: "max-w-[90%]",
20
+ },
21
+ },
22
+ defaultVariants: {
23
+ role: "assistant",
24
+ layout: "default",
25
+ },
26
+ });
27
+ export const Message = React.forwardRef(({ message, role: roleProp, layout, className, children, messageId: messageIdProp, autoScroll, isLastMessage = false, ...props }, ref) => {
28
+ // Extract role and messageId from message if provided
29
+ const role = message ? message.role : roleProp || "assistant";
30
+ const messageId = message ? message.id : messageIdProp;
31
+ const messageRef = React.useRef(null);
32
+ const [minHeight, setMinHeight] = React.useState(undefined);
33
+ // Merge refs
34
+ React.useImperativeHandle(ref, () => messageRef.current);
35
+ // Calculate dynamic min-height for last assistant message following a user message
36
+ React.useEffect(() => {
37
+ if (!isLastMessage || role !== "assistant") {
38
+ setMinHeight(undefined);
39
+ return;
40
+ }
41
+ const calculateMinHeight = () => {
42
+ const messageElement = messageRef.current;
43
+ if (!messageElement)
44
+ return;
45
+ // Find the ChatLayout.Messages container (scrollable parent)
46
+ let scrollContainer = messageElement.parentElement;
47
+ while (scrollContainer &&
48
+ !scrollContainer.classList.contains("overflow-y-auto")) {
49
+ scrollContainer = scrollContainer.parentElement;
50
+ }
51
+ if (!scrollContainer)
52
+ return;
53
+ // Find the previous user message
54
+ const previousSibling = messageElement.previousElementSibling;
55
+ if (!previousSibling ||
56
+ previousSibling.getAttribute("aria-label") !== "user message") {
57
+ setMinHeight(undefined);
58
+ return;
59
+ }
60
+ // Calculate: containerHeight - previousUserMessageHeight - spacing
61
+ const containerHeight = scrollContainer.clientHeight;
62
+ const previousMessageHeight = previousSibling.offsetHeight;
63
+ const spacing = 32; // gap-4 = 16px
64
+ // Min height = container height - user message height - spacing
65
+ // This ensures the user message can scroll to the top
66
+ const calculatedMinHeight = Math.max(0, containerHeight - previousMessageHeight - spacing);
67
+ setMinHeight(calculatedMinHeight);
68
+ };
69
+ // Calculate on mount and recalculate on resize
70
+ calculateMinHeight();
71
+ const resizeObserver = new ResizeObserver(calculateMinHeight);
72
+ // Observe the message element and its parent container
73
+ if (messageRef.current) {
74
+ resizeObserver.observe(messageRef.current);
75
+ let scrollContainer = messageRef.current.parentElement;
76
+ while (scrollContainer &&
77
+ !scrollContainer.classList.contains("overflow-y-auto")) {
78
+ scrollContainer = scrollContainer.parentElement;
79
+ }
80
+ if (scrollContainer) {
81
+ resizeObserver.observe(scrollContainer);
82
+ }
83
+ }
84
+ return () => resizeObserver.disconnect();
85
+ }, [isLastMessage, role]);
86
+ // Auto-scroll for user messages when they first appear
87
+ React.useEffect(() => {
88
+ // Default to auto-scroll for user messages unless explicitly disabled
89
+ const shouldAutoScroll = autoScroll !== undefined ? autoScroll : role === "user";
90
+ if (shouldAutoScroll && messageRef.current) {
91
+ // Small delay to ensure the message is fully rendered
92
+ const timeoutId = setTimeout(() => {
93
+ messageRef.current?.scrollIntoView({
94
+ behavior: "smooth",
95
+ block: "start",
96
+ inline: "nearest",
97
+ });
98
+ }, 50);
99
+ return () => clearTimeout(timeoutId);
100
+ }
101
+ return undefined;
102
+ }, [role, autoScroll]);
103
+ return (_jsx("article", { ref: messageRef, "aria-label": `${role} message`, "data-message-id": messageId, className: cn(messageVariants({ role, layout }), className), style: {
104
+ minHeight: minHeight !== undefined ? `${minHeight}px` : undefined,
105
+ }, ...props, children: children }));
27
106
  });
28
- export const Message = React.forwardRef(
29
- (
30
- {
31
- message,
32
- role: roleProp,
33
- layout,
34
- className,
35
- children,
36
- messageId: messageIdProp,
37
- ...props
38
- },
39
- ref,
40
- ) => {
41
- // Extract role and messageId from message if provided
42
- const role = message ? message.role : roleProp || "assistant";
43
- const messageId = message ? message.id : messageIdProp;
44
- return _jsx("article", {
45
- ref: ref,
46
- "aria-label": `${role} message`,
47
- "data-message-id": messageId,
48
- className: cn(messageVariants({ role, layout }), className),
49
- ...props,
50
- children: children,
51
- });
52
- },
53
- );
54
107
  Message.displayName = "Message";
@@ -1,33 +1,26 @@
1
1
  import { type VariantProps } from "class-variance-authority";
2
2
  import * as React from "react";
3
3
  import type { DisplayMessage } from "./MessageList.js";
4
- declare const messageContentVariants: (
5
- props?:
6
- | ({
7
- role?: "user" | "assistant" | "system" | null | undefined;
8
- variant?: "default" | "outline" | "ghost" | null | undefined;
9
- } & import("class-variance-authority/types").ClassProp)
10
- | undefined,
11
- ) => string;
12
- export interface MessageContentProps
13
- extends Omit<React.HTMLAttributes<HTMLDivElement>, "children">,
14
- VariantProps<typeof messageContentVariants> {
15
- /** Message role - determines styling */
16
- role?: "user" | "assistant" | "system";
17
- /** Visual variant */
18
- variant?: "default" | "outline" | "ghost";
19
- /** Whether the message is currently streaming */
20
- isStreaming?: boolean;
21
- /**
22
- * Message object for smart rendering (optional)
23
- * When provided, automatically renders thinking, waiting, and content
24
- */
25
- message?: DisplayMessage;
26
- /** Display style for thinking/reasoning blocks (when using smart rendering) */
27
- thinkingDisplayStyle?: "collapsible" | "inline";
28
- /** Custom content (overrides smart rendering) */
29
- children?: React.ReactNode;
4
+ declare const messageContentVariants: (props?: ({
5
+ role?: "user" | "assistant" | "system" | null | undefined;
6
+ variant?: "default" | "outline" | "ghost" | null | undefined;
7
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
+ export interface MessageContentProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children">, VariantProps<typeof messageContentVariants> {
9
+ /** Message role - determines styling */
10
+ role?: "user" | "assistant" | "system";
11
+ /** Visual variant */
12
+ variant?: "default" | "outline" | "ghost";
13
+ /** Whether the message is currently streaming */
14
+ isStreaming?: boolean;
15
+ /**
16
+ * Message object for smart rendering (optional)
17
+ * When provided, automatically renders thinking, waiting, and content
18
+ */
19
+ message?: DisplayMessage;
20
+ /** Display style for thinking/reasoning blocks (when using smart rendering) */
21
+ thinkingDisplayStyle?: "collapsible" | "inline";
22
+ /** Custom content (overrides smart rendering) */
23
+ children?: React.ReactNode;
30
24
  }
31
- export declare const MessageContent: React.ForwardRefExoticComponent<
32
- MessageContentProps & React.RefAttributes<HTMLDivElement>
33
- >;
25
+ export declare const MessageContent: React.ForwardRefExoticComponent<MessageContentProps & React.RefAttributes<HTMLDivElement>>;
26
+ export {};
@@ -1,16 +1,11 @@
1
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
1
2
  import { cva } from "class-variance-authority";
2
3
  import { Loader2Icon } from "lucide-react";
3
4
  import * as React from "react";
4
- import {
5
- Fragment as _Fragment,
6
- jsx as _jsx,
7
- jsxs as _jsxs,
8
- } from "react/jsx-runtime";
9
5
  import { useChatStore } from "../../core/store/chat-store.js";
10
6
  import { cn } from "../lib/utils.js";
11
7
  import { Reasoning } from "./Reasoning.js";
12
8
  import { Response } from "./Response.js";
13
-
14
9
  /**
15
10
  * MessageContent component inspired by shadcn.io/ai
16
11
  * Provides the content container with role-based styling
@@ -18,159 +13,92 @@ import { Response } from "./Response.js";
18
13
  */
19
14
  // Synonyms of "thinking" in multiple languages
20
15
  const THINKING_WORDS = [
21
- "Thinking",
22
- "Pensando",
23
- "Pensant",
24
- "Denkend",
25
- "Pensando",
26
- "考えている",
27
- "생각 중",
28
- "思考中",
29
- "Размышляя",
30
- "Düşünüyor",
31
- "Myślący",
32
- "Tänkande",
33
- "Pensando",
34
- "Ajatellen",
35
- "Σκεπτόμενος",
36
- "חושב",
37
- "सोच रहा है",
38
- "Berpikir",
16
+ "Thinking",
17
+ "Pensando",
18
+ "Pensant",
19
+ "Denkend",
20
+ "Pensando",
21
+ "考えている",
22
+ "생각 중",
23
+ "思考中",
24
+ "Размышляя",
25
+ "Düşünüyor",
26
+ "Myślący",
27
+ "Tänkande",
28
+ "Pensando",
29
+ "Ajatellen",
30
+ "Σκεπτόμενος",
31
+ "חושב",
32
+ "सोच रहा है",
33
+ "Berpikir",
39
34
  ];
40
35
  const DOT_ANIMATIONS = ["...", "·..", ".·.", "..·", ".·.", "·.."];
41
36
  function WaitingElapsedTime({ startTime }) {
42
- const [elapsed, setElapsed] = React.useState(0);
43
- const [thinkingWord, setThinkingWord] = React.useState(
44
- () => THINKING_WORDS[Math.floor(Math.random() * THINKING_WORDS.length)],
45
- );
46
- const [dotIndex, setDotIndex] = React.useState(0);
47
- React.useEffect(() => {
48
- const interval = setInterval(() => {
49
- const now = Date.now();
50
- const elapsedMs = now - startTime;
51
- setElapsed(elapsedMs);
52
- }, 100);
53
- return () => clearInterval(interval);
54
- }, [startTime]);
55
- React.useEffect(() => {
56
- const wordInterval = setInterval(() => {
57
- const randomIndex = Math.floor(Math.random() * THINKING_WORDS.length);
58
- setThinkingWord(THINKING_WORDS[randomIndex]);
59
- }, 1500);
60
- return () => clearInterval(wordInterval);
61
- }, []);
62
- React.useEffect(() => {
63
- const dotInterval = setInterval(() => {
64
- setDotIndex((prev) => (prev + 1) % DOT_ANIMATIONS.length);
65
- }, 100);
66
- return () => clearInterval(dotInterval);
67
- }, []);
68
- const seconds = (elapsed / 1000).toFixed(1);
69
- const animatedDots = DOT_ANIMATIONS[dotIndex];
70
- return _jsxs("span", {
71
- className: "text-muted-foreground text-sm",
72
- children: [thinkingWord, animatedDots, " ", seconds, "s"],
73
- });
37
+ const [elapsed, setElapsed] = React.useState(0);
38
+ const [thinkingWord, setThinkingWord] = React.useState(() => THINKING_WORDS[Math.floor(Math.random() * THINKING_WORDS.length)]);
39
+ const [dotIndex, setDotIndex] = React.useState(0);
40
+ React.useEffect(() => {
41
+ const interval = setInterval(() => {
42
+ const now = Date.now();
43
+ const elapsedMs = now - startTime;
44
+ setElapsed(elapsedMs);
45
+ }, 100);
46
+ return () => clearInterval(interval);
47
+ }, [startTime]);
48
+ React.useEffect(() => {
49
+ const wordInterval = setInterval(() => {
50
+ const randomIndex = Math.floor(Math.random() * THINKING_WORDS.length);
51
+ setThinkingWord(THINKING_WORDS[randomIndex]);
52
+ }, 1500);
53
+ return () => clearInterval(wordInterval);
54
+ }, []);
55
+ React.useEffect(() => {
56
+ const dotInterval = setInterval(() => {
57
+ setDotIndex((prev) => (prev + 1) % DOT_ANIMATIONS.length);
58
+ }, 100);
59
+ return () => clearInterval(dotInterval);
60
+ }, []);
61
+ const seconds = (elapsed / 1000).toFixed(1);
62
+ const animatedDots = DOT_ANIMATIONS[dotIndex];
63
+ return (_jsxs("span", { className: "text-muted-foreground text-sm", children: [thinkingWord, animatedDots, " ", seconds, "s"] }));
74
64
  }
75
- const messageContentVariants = cva(
76
- "w-full px-4 py-3 rounded-xl text-[var(--font-size)] font-[var(--font-family)] leading-relaxed break-words transition-colors",
77
- {
78
- variants: {
79
- role: {
80
- user: "bg-primary text-primary-foreground shadow-sm",
81
- assistant: "bg-muted text-foreground",
82
- system:
83
- "bg-card border border-border text-foreground opacity-80 text-sm",
84
- },
85
- variant: {
86
- default: "",
87
- outline: "border border-border",
88
- ghost: "bg-transparent",
89
- },
90
- },
91
- defaultVariants: {
92
- role: "assistant",
93
- variant: "default",
94
- },
95
- },
96
- );
97
- export const MessageContent = React.forwardRef(
98
- (
99
- {
100
- role: roleProp,
101
- variant,
102
- isStreaming: isStreamingProp,
103
- message,
104
- thinkingDisplayStyle = "collapsible",
105
- className,
106
- children,
107
- ...props
108
- },
109
- ref,
110
- ) => {
111
- // Get streaming start time from store (when using smart rendering)
112
- const streamingStartTime = useChatStore(
113
- (state) => state.streamingStartTime,
114
- );
115
- // Use smart rendering if message is provided and no custom children
116
- const useSmartRendering = message && !children;
117
- // Derive props from message if using smart rendering
118
- const role = useSmartRendering ? message.role : roleProp || "assistant";
119
- const isStreaming = useSmartRendering
120
- ? message.isStreaming
121
- : isStreamingProp;
122
- let content = children;
123
- if (useSmartRendering) {
124
- // Extract thinking from metadata
125
- const thinking = message.metadata?.thinking;
126
- const hasThinking = !!thinking;
127
- // Check if waiting (streaming but no content yet)
128
- const isWaiting =
129
- message.isStreaming && !message.content && message.role === "assistant";
130
- content = _jsxs(_Fragment, {
131
- children: [
132
- message.role === "assistant" &&
133
- hasThinking &&
134
- _jsx(Reasoning, {
135
- content: thinking,
136
- isStreaming: message.isStreaming,
137
- mode: thinkingDisplayStyle,
138
- autoCollapse: true,
139
- }),
140
- isWaiting &&
141
- streamingStartTime &&
142
- _jsxs("div", {
143
- className: "flex items-center gap-2 opacity-50",
144
- children: [
145
- _jsx(Loader2Icon, {
146
- className: "size-4 animate-spin text-muted-foreground",
147
- }),
148
- _jsx(WaitingElapsedTime, { startTime: streamingStartTime }),
149
- ],
150
- }),
151
- message.role === "user"
152
- ? _jsx("div", {
153
- className: "whitespace-pre-wrap",
154
- children: message.content,
155
- })
156
- : _jsx(Response, {
157
- content: message.content,
158
- isStreaming: message.isStreaming,
159
- showEmpty: false,
160
- }),
161
- ],
162
- });
163
- }
164
- return _jsx("div", {
165
- ref: ref,
166
- className: cn(
167
- messageContentVariants({ role, variant }),
168
- isStreaming && "animate-pulse-subtle",
169
- className,
170
- ),
171
- ...props,
172
- children: content,
173
- });
174
- },
175
- );
65
+ const messageContentVariants = cva("w-full px-4 py-3 rounded-xl text-[var(--font-size)] font-[var(--font-family)] leading-relaxed break-words transition-colors", {
66
+ variants: {
67
+ role: {
68
+ user: "bg-primary text-primary-foreground shadow-sm",
69
+ assistant: "text-foreground",
70
+ system: "bg-card border border-border text-foreground opacity-80 text-sm",
71
+ },
72
+ variant: {
73
+ default: "",
74
+ outline: "border border-border",
75
+ ghost: "bg-transparent",
76
+ },
77
+ },
78
+ defaultVariants: {
79
+ role: "assistant",
80
+ variant: "default",
81
+ },
82
+ });
83
+ export const MessageContent = React.forwardRef(({ role: roleProp, variant, isStreaming: isStreamingProp, message, thinkingDisplayStyle = "collapsible", className, children, ...props }, ref) => {
84
+ // Get streaming start time from store (when using smart rendering)
85
+ const streamingStartTime = useChatStore((state) => state.streamingStartTime);
86
+ // Use smart rendering if message is provided and no custom children
87
+ const useSmartRendering = message && !children;
88
+ // Derive props from message if using smart rendering
89
+ const role = useSmartRendering ? message.role : roleProp || "assistant";
90
+ const isStreaming = useSmartRendering
91
+ ? message.isStreaming
92
+ : isStreamingProp;
93
+ let content = children;
94
+ if (useSmartRendering) {
95
+ // Extract thinking from metadata
96
+ const thinking = message.metadata?.thinking;
97
+ const hasThinking = !!thinking;
98
+ // Check if waiting (streaming but no content yet)
99
+ const isWaiting = message.isStreaming && !message.content && message.role === "assistant";
100
+ content = (_jsxs(_Fragment, { children: [message.role === "assistant" && hasThinking && (_jsx(Reasoning, { content: thinking, isStreaming: message.isStreaming, mode: thinkingDisplayStyle, autoCollapse: true })), isWaiting && streamingStartTime && (_jsxs("div", { className: "flex items-center gap-2 opacity-50", children: [_jsx(Loader2Icon, { className: "size-4 animate-spin text-muted-foreground" }), _jsx(WaitingElapsedTime, { startTime: streamingStartTime })] })), message.role === "user" ? (_jsx("div", { className: "whitespace-pre-wrap", children: message.content })) : (_jsx(Response, { content: message.content, isStreaming: message.isStreaming, showEmpty: false }))] }));
101
+ }
102
+ return (_jsx("div", { ref: ref, className: cn(messageContentVariants({ role, variant }), isStreaming && "animate-pulse-subtle", className), ...props, children: content }));
103
+ });
176
104
  MessageContent.displayName = "MessageContent";
@@ -4,34 +4,28 @@ import * as React from "react";
4
4
  * Reasoning component inspired by shadcn.io/ai
5
5
  * Displays AI thinking/reasoning process with auto-collapse support
6
6
  */
7
- declare const reasoningContainerVariants: (
8
- props?:
9
- | ({
10
- variant?: "default" | "subtle" | "prominent" | null | undefined;
11
- } & import("class-variance-authority/types").ClassProp)
12
- | undefined,
13
- ) => string;
14
- export interface ReasoningProps
15
- extends VariantProps<typeof reasoningContainerVariants> {
16
- /** The reasoning/thinking content */
17
- content?: string;
18
- /** Whether the content is currently streaming */
19
- isStreaming?: boolean;
20
- /** Display mode - collapsible or always visible */
21
- mode?: "collapsible" | "inline";
22
- /** Default expanded state (default: false - collapsed by default) */
23
- defaultExpanded?: boolean;
24
- /** Auto-expand when streaming starts (default: false) */
25
- autoExpand?: boolean;
26
- /** Auto-collapse after streaming completes */
27
- autoCollapse?: boolean;
28
- /** Delay before auto-collapsing (ms) */
29
- autoCollapseDelay?: number;
30
- /** Custom label */
31
- label?: string;
32
- /** Additional CSS class */
33
- className?: string;
7
+ declare const reasoningContainerVariants: (props?: ({
8
+ variant?: "default" | "subtle" | "prominent" | null | undefined;
9
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
10
+ export interface ReasoningProps extends VariantProps<typeof reasoningContainerVariants> {
11
+ /** The reasoning/thinking content */
12
+ content?: string;
13
+ /** Whether the content is currently streaming */
14
+ isStreaming?: boolean;
15
+ /** Display mode - collapsible or always visible */
16
+ mode?: "collapsible" | "inline";
17
+ /** Default expanded state (default: false - collapsed by default) */
18
+ defaultExpanded?: boolean;
19
+ /** Auto-expand when streaming starts (default: false) */
20
+ autoExpand?: boolean;
21
+ /** Auto-collapse after streaming completes */
22
+ autoCollapse?: boolean;
23
+ /** Delay before auto-collapsing (ms) */
24
+ autoCollapseDelay?: number;
25
+ /** Custom label */
26
+ label?: string;
27
+ /** Additional CSS class */
28
+ className?: string;
34
29
  }
35
- export declare const Reasoning: React.ForwardRefExoticComponent<
36
- ReasoningProps & React.RefAttributes<HTMLDivElement>
37
- >;
30
+ export declare const Reasoning: React.ForwardRefExoticComponent<ReasoningProps & React.RefAttributes<HTMLDivElement>>;
31
+ export {};