@townco/ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/README.md +175 -0
  2. package/dist/core/hooks/index.d.ts +6 -0
  3. package/dist/core/hooks/index.d.ts.map +1 -0
  4. package/dist/core/hooks/index.js +6 -0
  5. package/dist/core/hooks/index.js.map +1 -0
  6. package/dist/core/hooks/use-chat-input.d.ts +23 -0
  7. package/dist/core/hooks/use-chat-input.d.ts.map +1 -0
  8. package/dist/core/hooks/use-chat-input.js +63 -0
  9. package/dist/core/hooks/use-chat-input.js.map +1 -0
  10. package/dist/core/hooks/use-chat-messages.d.ts +17 -0
  11. package/dist/core/hooks/use-chat-messages.d.ts.map +1 -0
  12. package/dist/core/hooks/use-chat-messages.js +121 -0
  13. package/dist/core/hooks/use-chat-messages.js.map +1 -0
  14. package/dist/core/hooks/use-chat-session.d.ts +11 -0
  15. package/dist/core/hooks/use-chat-session.d.ts.map +1 -0
  16. package/dist/core/hooks/use-chat-session.js +87 -0
  17. package/dist/core/hooks/use-chat-session.js.map +1 -0
  18. package/dist/core/hooks/use-media-query.d.ts +39 -0
  19. package/dist/core/hooks/use-media-query.js +80 -0
  20. package/dist/core/index.d.ts +9 -0
  21. package/dist/core/index.d.ts.map +1 -0
  22. package/dist/core/index.js +9 -0
  23. package/dist/core/index.js.map +1 -0
  24. package/dist/core/schemas/chat.d.ts +78 -0
  25. package/dist/core/schemas/chat.d.ts.map +1 -0
  26. package/dist/core/schemas/chat.js +49 -0
  27. package/dist/core/schemas/chat.js.map +1 -0
  28. package/dist/core/schemas/index.d.ts +4 -0
  29. package/dist/core/schemas/index.d.ts.map +1 -0
  30. package/dist/core/schemas/index.js +4 -0
  31. package/dist/core/schemas/index.js.map +1 -0
  32. package/dist/core/store/chat-store.d.ts +30 -0
  33. package/dist/core/store/chat-store.d.ts.map +1 -0
  34. package/dist/core/store/chat-store.js +56 -0
  35. package/dist/core/store/chat-store.js.map +1 -0
  36. package/dist/gui/components/Button.d.ts +11 -0
  37. package/dist/gui/components/Button.d.ts.map +1 -0
  38. package/dist/gui/components/Button.js +33 -0
  39. package/dist/gui/components/Button.js.map +1 -0
  40. package/dist/gui/components/Card.d.ts +8 -0
  41. package/dist/gui/components/Card.d.ts.map +1 -0
  42. package/dist/gui/components/Card.js +16 -0
  43. package/dist/gui/components/Card.js.map +1 -0
  44. package/dist/gui/components/ChatHeader.d.ts +38 -0
  45. package/dist/gui/components/ChatHeader.js +84 -0
  46. package/dist/gui/components/ChatInput.d.ts +42 -0
  47. package/dist/gui/components/ChatInput.d.ts.map +1 -0
  48. package/dist/gui/components/ChatInput.js +137 -0
  49. package/dist/gui/components/ChatInput.js.map +1 -0
  50. package/dist/gui/components/ChatInterface.d.ts +9 -0
  51. package/dist/gui/components/ChatInterface.d.ts.map +1 -0
  52. package/dist/gui/components/ChatInterface.js +132 -0
  53. package/dist/gui/components/ChatInterface.js.map +1 -0
  54. package/dist/gui/components/ChatLayout.d.ts +52 -0
  55. package/dist/gui/components/ChatLayout.js +105 -0
  56. package/dist/gui/components/ChatPanelTabContent.d.ts +18 -0
  57. package/dist/gui/components/ChatPanelTabContent.js +15 -0
  58. package/dist/gui/components/ChatPreview.d.ts +9 -0
  59. package/dist/gui/components/ChatPreview.d.ts.map +1 -0
  60. package/dist/gui/components/ChatPreview.js +164 -0
  61. package/dist/gui/components/ChatPreview.js.map +1 -0
  62. package/dist/gui/components/ChatSecondaryPanel.d.ts +20 -0
  63. package/dist/gui/components/ChatSecondaryPanel.d.ts.map +1 -0
  64. package/dist/gui/components/ChatSecondaryPanel.js +44 -0
  65. package/dist/gui/components/ChatSecondaryPanel.js.map +1 -0
  66. package/dist/gui/components/ChatSidebar.d.ts +14 -0
  67. package/dist/gui/components/ChatSidebar.js +23 -0
  68. package/dist/gui/components/ChatStatus.d.ts +6 -0
  69. package/dist/gui/components/ChatStatus.d.ts.map +1 -0
  70. package/dist/gui/components/ChatStatus.js +38 -0
  71. package/dist/gui/components/ChatStatus.js.map +1 -0
  72. package/dist/gui/components/ChatView.d.ts +6 -0
  73. package/dist/gui/components/ChatView.d.ts.map +1 -0
  74. package/dist/gui/components/ChatView.js +13 -0
  75. package/dist/gui/components/ChatView.js.map +1 -0
  76. package/dist/gui/components/ConfigPanel.d.ts +16 -0
  77. package/dist/gui/components/ConfigPanel.d.ts.map +1 -0
  78. package/dist/gui/components/ConfigPanel.js +48 -0
  79. package/dist/gui/components/ConfigPanel.js.map +1 -0
  80. package/dist/gui/components/Conversation.d.ts +20 -0
  81. package/dist/gui/components/Conversation.d.ts.map +1 -0
  82. package/dist/gui/components/Conversation.js +87 -0
  83. package/dist/gui/components/Conversation.js.map +1 -0
  84. package/dist/gui/components/Dialog.d.ts +19 -0
  85. package/dist/gui/components/Dialog.d.ts.map +1 -0
  86. package/dist/gui/components/Dialog.js +22 -0
  87. package/dist/gui/components/Dialog.js.map +1 -0
  88. package/dist/gui/components/DropdownMenu.d.ts +27 -0
  89. package/dist/gui/components/DropdownMenu.js +68 -0
  90. package/dist/gui/components/HeightTransition.d.ts +10 -0
  91. package/dist/gui/components/HeightTransition.d.ts.map +1 -0
  92. package/dist/gui/components/HeightTransition.js +80 -0
  93. package/dist/gui/components/HeightTransition.js.map +1 -0
  94. package/dist/gui/components/Input.d.ts +9 -0
  95. package/dist/gui/components/Input.d.ts.map +1 -0
  96. package/dist/gui/components/Input.js +21 -0
  97. package/dist/gui/components/Input.js.map +1 -0
  98. package/dist/gui/components/InputBox.d.ts +14 -0
  99. package/dist/gui/components/InputBox.d.ts.map +1 -0
  100. package/dist/gui/components/InputBox.js +18 -0
  101. package/dist/gui/components/InputBox.js.map +1 -0
  102. package/dist/gui/components/Label.d.ts +4 -0
  103. package/dist/gui/components/Label.d.ts.map +1 -0
  104. package/dist/gui/components/Label.js +7 -0
  105. package/dist/gui/components/Label.js.map +1 -0
  106. package/dist/gui/components/MarkdownRenderer.d.ts +6 -0
  107. package/dist/gui/components/MarkdownRenderer.d.ts.map +1 -0
  108. package/dist/gui/components/MarkdownRenderer.js +86 -0
  109. package/dist/gui/components/MarkdownRenderer.js.map +1 -0
  110. package/dist/gui/components/Message.d.ts +26 -0
  111. package/dist/gui/components/Message.d.ts.map +1 -0
  112. package/dist/gui/components/Message.js +33 -0
  113. package/dist/gui/components/Message.js.map +1 -0
  114. package/dist/gui/components/MessageContent.d.ts +26 -0
  115. package/dist/gui/components/MessageContent.d.ts.map +1 -0
  116. package/dist/gui/components/MessageContent.js +104 -0
  117. package/dist/gui/components/MessageContent.js.map +1 -0
  118. package/dist/gui/components/MessageList.d.ts +6 -0
  119. package/dist/gui/components/MessageList.d.ts.map +1 -0
  120. package/dist/gui/components/MessageList.js +1 -0
  121. package/dist/gui/components/MessageList.js.map +1 -0
  122. package/dist/gui/components/PlaygroundLayout.d.ts +10 -0
  123. package/dist/gui/components/PlaygroundLayout.d.ts.map +1 -0
  124. package/dist/gui/components/PlaygroundLayout.js +18 -0
  125. package/dist/gui/components/PlaygroundLayout.js.map +1 -0
  126. package/dist/gui/components/Reasoning.d.ts +31 -0
  127. package/dist/gui/components/Reasoning.d.ts.map +1 -0
  128. package/dist/gui/components/Reasoning.js +70 -0
  129. package/dist/gui/components/Reasoning.js.map +1 -0
  130. package/dist/gui/components/Response.d.ts +16 -0
  131. package/dist/gui/components/Response.d.ts.map +1 -0
  132. package/dist/gui/components/Response.js +95 -0
  133. package/dist/gui/components/Response.js.map +1 -0
  134. package/dist/gui/components/Select.d.ts +13 -0
  135. package/dist/gui/components/Select.d.ts.map +1 -0
  136. package/dist/gui/components/Select.js +26 -0
  137. package/dist/gui/components/Select.js.map +1 -0
  138. package/dist/gui/components/Sonner.d.ts +5 -0
  139. package/dist/gui/components/Sonner.js +23 -0
  140. package/dist/gui/components/StatusBar.d.ts +8 -0
  141. package/dist/gui/components/StatusBar.d.ts.map +1 -0
  142. package/dist/gui/components/StatusBar.js +11 -0
  143. package/dist/gui/components/StatusBar.js.map +1 -0
  144. package/dist/gui/components/Tabs.d.ts +7 -0
  145. package/dist/gui/components/Tabs.d.ts.map +1 -0
  146. package/dist/gui/components/Tabs.js +12 -0
  147. package/dist/gui/components/Tabs.js.map +1 -0
  148. package/dist/gui/components/Task.d.ts +35 -0
  149. package/dist/gui/components/Task.d.ts.map +1 -0
  150. package/dist/gui/components/Task.js +37 -0
  151. package/dist/gui/components/Task.js.map +1 -0
  152. package/dist/gui/components/Textarea.d.ts +11 -0
  153. package/dist/gui/components/Textarea.d.ts.map +1 -0
  154. package/dist/gui/components/Textarea.js +51 -0
  155. package/dist/gui/components/Textarea.js.map +1 -0
  156. package/dist/gui/components/ThinkingBlock.d.ts +12 -0
  157. package/dist/gui/components/ThinkingBlock.d.ts.map +1 -0
  158. package/dist/gui/components/ThinkingBlock.js +40 -0
  159. package/dist/gui/components/ThinkingBlock.js.map +1 -0
  160. package/dist/gui/components/TodoList.d.ts +20 -0
  161. package/dist/gui/components/TodoList.d.ts.map +1 -0
  162. package/dist/gui/components/TodoList.js +11 -0
  163. package/dist/gui/components/TodoList.js.map +1 -0
  164. package/dist/gui/components/TodoListItem.d.ts +10 -0
  165. package/dist/gui/components/TodoListItem.d.ts.map +1 -0
  166. package/dist/gui/components/TodoListItem.js +7 -0
  167. package/dist/gui/components/TodoListItem.js.map +1 -0
  168. package/dist/gui/components/index.d.ts +23 -0
  169. package/dist/gui/components/index.d.ts.map +1 -0
  170. package/dist/gui/components/index.js +28 -0
  171. package/dist/gui/components/index.js.map +1 -0
  172. package/dist/gui/index.d.ts +2 -0
  173. package/dist/gui/index.d.ts.map +1 -0
  174. package/dist/gui/index.js +4 -0
  175. package/dist/gui/index.js.map +1 -0
  176. package/dist/gui/lib/utils.d.ts +2 -0
  177. package/dist/gui/lib/utils.d.ts.map +1 -0
  178. package/dist/gui/lib/utils.js +5 -0
  179. package/dist/gui/lib/utils.js.map +1 -0
  180. package/dist/index.d.ts +11 -0
  181. package/dist/index.d.ts.map +1 -0
  182. package/dist/index.js +12 -0
  183. package/dist/index.js.map +1 -0
  184. package/dist/index.test.d.ts +0 -0
  185. package/dist/index.test.js +1 -0
  186. package/dist/sdk/client/acp-client.d.ts +84 -0
  187. package/dist/sdk/client/acp-client.d.ts.map +1 -0
  188. package/dist/sdk/client/acp-client.js +225 -0
  189. package/dist/sdk/client/acp-client.js.map +1 -0
  190. package/dist/sdk/client/index.d.ts +4 -0
  191. package/dist/sdk/client/index.d.ts.map +1 -0
  192. package/dist/sdk/client/index.js +4 -0
  193. package/dist/sdk/client/index.js.map +1 -0
  194. package/dist/sdk/index.d.ts +9 -0
  195. package/dist/sdk/index.d.ts.map +1 -0
  196. package/dist/sdk/index.js +9 -0
  197. package/dist/sdk/index.js.map +1 -0
  198. package/dist/sdk/schemas/agent.d.ts +87 -0
  199. package/dist/sdk/schemas/agent.d.ts.map +1 -0
  200. package/dist/sdk/schemas/agent.js +50 -0
  201. package/dist/sdk/schemas/agent.js.map +1 -0
  202. package/dist/sdk/schemas/index.d.ts +6 -0
  203. package/dist/sdk/schemas/index.d.ts.map +1 -0
  204. package/dist/sdk/schemas/index.js +6 -0
  205. package/dist/sdk/schemas/index.js.map +1 -0
  206. package/dist/sdk/schemas/message.d.ts +195 -0
  207. package/dist/sdk/schemas/message.d.ts.map +1 -0
  208. package/dist/sdk/schemas/message.js +95 -0
  209. package/dist/sdk/schemas/message.js.map +1 -0
  210. package/dist/sdk/schemas/session.d.ts +158 -0
  211. package/dist/sdk/schemas/session.d.ts.map +1 -0
  212. package/dist/sdk/schemas/session.js +54 -0
  213. package/dist/sdk/schemas/session.js.map +1 -0
  214. package/dist/sdk/transports/http.d.ts +63 -0
  215. package/dist/sdk/transports/http.d.ts.map +1 -0
  216. package/dist/sdk/transports/http.js +476 -0
  217. package/dist/sdk/transports/http.js.map +1 -0
  218. package/dist/sdk/transports/index.d.ts +7 -0
  219. package/dist/sdk/transports/index.d.ts.map +1 -0
  220. package/dist/sdk/transports/index.js +7 -0
  221. package/dist/sdk/transports/index.js.map +1 -0
  222. package/dist/sdk/transports/stdio.d.ts +28 -0
  223. package/dist/sdk/transports/stdio.d.ts.map +1 -0
  224. package/dist/sdk/transports/stdio.js +294 -0
  225. package/dist/sdk/transports/stdio.js.map +1 -0
  226. package/dist/sdk/transports/types.d.ts +63 -0
  227. package/dist/sdk/transports/types.d.ts.map +1 -0
  228. package/dist/sdk/transports/types.js +1 -0
  229. package/dist/sdk/transports/types.js.map +1 -0
  230. package/dist/sdk/transports/websocket.d.ts +20 -0
  231. package/dist/sdk/transports/websocket.d.ts.map +1 -0
  232. package/dist/sdk/transports/websocket.js +52 -0
  233. package/dist/sdk/transports/websocket.js.map +1 -0
  234. package/dist/tui/components/ChatView.d.ts +5 -0
  235. package/dist/tui/components/ChatView.d.ts.map +1 -0
  236. package/dist/tui/components/ChatView.js +24 -0
  237. package/dist/tui/components/ChatView.js.map +1 -0
  238. package/dist/tui/components/GameOfLife.d.ts +1 -0
  239. package/dist/tui/components/GameOfLife.d.ts.map +1 -0
  240. package/dist/tui/components/GameOfLife.js +50 -0
  241. package/dist/tui/components/GameOfLife.js.map +1 -0
  242. package/dist/tui/components/InputBox.d.ts +13 -0
  243. package/dist/tui/components/InputBox.d.ts.map +1 -0
  244. package/dist/tui/components/InputBox.js +15 -0
  245. package/dist/tui/components/InputBox.js.map +1 -0
  246. package/dist/tui/components/MessageList.d.ts +5 -0
  247. package/dist/tui/components/MessageList.d.ts.map +1 -0
  248. package/dist/tui/components/MessageList.js +16 -0
  249. package/dist/tui/components/MessageList.js.map +1 -0
  250. package/dist/tui/components/MultiSelect.d.ts +13 -0
  251. package/dist/tui/components/MultiSelect.js +72 -0
  252. package/dist/tui/components/ReadlineInput.d.ts +8 -0
  253. package/dist/tui/components/ReadlineInput.d.ts.map +1 -0
  254. package/dist/tui/components/ReadlineInput.js +240 -0
  255. package/dist/tui/components/ReadlineInput.js.map +1 -0
  256. package/dist/tui/components/SingleSelect.d.ts +13 -0
  257. package/dist/tui/components/SingleSelect.js +46 -0
  258. package/dist/tui/components/StatusBar.d.ts +9 -0
  259. package/dist/tui/components/StatusBar.d.ts.map +1 -0
  260. package/dist/tui/components/StatusBar.js +82 -0
  261. package/dist/tui/components/StatusBar.js.map +1 -0
  262. package/dist/tui/components/index.d.ts +11 -0
  263. package/dist/tui/components/index.d.ts.map +1 -0
  264. package/dist/tui/components/index.js +11 -0
  265. package/dist/tui/components/index.js.map +1 -0
  266. package/dist/tui/index.d.ts +7 -0
  267. package/dist/tui/index.d.ts.map +1 -0
  268. package/dist/tui/index.js +7 -0
  269. package/dist/tui/index.js.map +1 -0
  270. package/package.json +86 -0
  271. package/src/styles/global.css +152 -0
package/README.md ADDED
@@ -0,0 +1,175 @@
1
+ # @town/ui
2
+
3
+ Unified UI package with composable components for chat interfaces.
4
+
5
+ ## Architecture
6
+
7
+ Three layers:
8
+
9
+ 1. **Core** (`@town/ui/core`) - Headless business logic
10
+ 1. **TUI** (`@town/ui/tui`) - Terminal renderers (Ink)
11
+ 1. **GUI** (`@town/ui/gui`) - Web renderers (React + Tailwind)
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ bun add @town/ui @town/ui
17
+
18
+ # For TUI
19
+ bun add ink react
20
+
21
+ # For GUI
22
+ bun add react react-dom
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Core (Headless Hooks)
28
+
29
+ ```typescript
30
+ import { useChatSession, useChatMessages, useChatInput } from "@town/ui/core";
31
+
32
+ function MyComponent({ client }) {
33
+ const { connectionStatus, sessionId } = useChatSession(client);
34
+ const { messages, isStreaming, sendMessage } = useChatMessages(client);
35
+ const { value, onChange, onSubmit } = useChatInput(client);
36
+
37
+ // Use these hooks to build any UI!
38
+ }
39
+ ```
40
+
41
+ ### TUI (Terminal)
42
+
43
+ ```typescript
44
+ import { render } from "ink";
45
+ import { ChatView } from "@town/ui/tui";
46
+ import { AcpClient } from "@town/ui";
47
+
48
+ const client = new AcpClient({ stdio: { agentPath: "./agent" } });
49
+ render(<ChatView client={client} />);
50
+ ```
51
+
52
+ ### GUI (Web)
53
+
54
+ ```typescript
55
+ import ReactDOM from "react-dom/client";
56
+ import { ChatView } from "@town/ui/gui";
57
+ import { AcpClient } from "@town/ui";
58
+
59
+ const client = new AcpClient({ http: { baseUrl: "http://localhost:8080" } });
60
+ ReactDOM.createRoot(root).render(<ChatView client={client} />);
61
+ ```
62
+
63
+ ## Components
64
+
65
+ ### Core Hooks
66
+
67
+ All hooks accept an `AcpClient | null` parameter.
68
+
69
+ #### `useChatSession(client)`
70
+
71
+ Manages connection and session lifecycle.
72
+
73
+ **Returns**:
74
+
75
+ - `connectionStatus` - Current connection state
76
+ - `sessionId` - Active session ID
77
+ - `connect()` - Connect to agent
78
+ - `startSession()` - Start new session
79
+ - `disconnect()` - Disconnect from agent
80
+
81
+ #### `useChatMessages(client)`
82
+
83
+ Manages message sending and receiving.
84
+
85
+ **Returns**:
86
+
87
+ - `messages` - Array of display messages
88
+ - `isStreaming` - Whether currently streaming
89
+ - `sendMessage(content)` - Send a message
90
+
91
+ #### `useChatInput(client)`
92
+
93
+ Manages input state and submission.
94
+
95
+ **Returns**:
96
+
97
+ - `value` - Current input value
98
+ - `isSubmitting` - Whether submitting
99
+ - `attachedFiles` - File attachments
100
+ - `onChange(value)` - Update input
101
+ - `onSubmit()` - Submit message
102
+ - `onAttachFile(file)` - Attach file
103
+ - `onRemoveFile(index)` - Remove file
104
+
105
+ ### TUI Components
106
+
107
+ Built with Ink for terminal UIs.
108
+
109
+ #### `<ChatView client={client} />`
110
+
111
+ Complete chat interface.
112
+
113
+ #### `<StatusBar connectionStatus sessionId isStreaming />`
114
+
115
+ Status indicator bar.
116
+
117
+ #### `<MessageList messages />`
118
+
119
+ Scrollable message list.
120
+
121
+ #### `<InputBox value isSubmitting attachedFiles onChange onSubmit onRemoveFile />`
122
+
123
+ Input field with file attachments.
124
+
125
+ ### GUI Components
126
+
127
+ Built with React + Tailwind for web UIs.
128
+
129
+ Same props as TUI components, but with web-friendly styling!
130
+
131
+ ## Key Benefits
132
+
133
+ 1. **Shared Logic**: TUI and GUI use identical hooks
134
+ 1. **Composable**: Build custom UIs from primitives
135
+ 1. **Type-Safe**: Full TypeScript support
136
+ 1. **State Management**: Zustand for global state
137
+ 1. **Validation**: Zod schemas for all data
138
+
139
+ ## Development
140
+
141
+ ```bash
142
+ # Install dependencies
143
+ bun install
144
+
145
+ # Build
146
+ bun run build
147
+
148
+ # Test
149
+ bun test
150
+ ```
151
+
152
+ ## Example: Custom Component
153
+
154
+ ```typescript
155
+ import { useChatMessages, useChatInput } from "@town/ui/core";
156
+
157
+ function CustomChat({ client }) {
158
+ const { messages, sendMessage } = useChatMessages(client);
159
+ const { value, onChange, onSubmit } = useChatInput(client);
160
+
161
+ return (
162
+ <div>
163
+ <div>
164
+ {messages.map(msg => (
165
+ <div key={msg.id}>{msg.content}</div>
166
+ ))}
167
+ </div>
168
+ <input value={value} onChange={e => onChange(e.target.value)} />
169
+ <button onClick={onSubmit}>Send</button>
170
+ </div>
171
+ );
172
+ }
173
+ ```
174
+
175
+ The headless core makes it easy to build any UI!
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Export all core hooks
3
+ */
4
+ export * from "./use-chat-input.js";
5
+ export * from "./use-chat-messages.js";
6
+ export * from "./use-chat-session.js";
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Export all core hooks
3
+ */
4
+ export * from "./use-chat-input.js";
5
+ export * from "./use-chat-messages.js";
6
+ export * from "./use-chat-session.js";
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { AcpClient } from "../../sdk/client/index.js";
2
+ /**
3
+ * Hook for managing chat input
4
+ */
5
+ export declare function useChatInput(client: AcpClient | null): {
6
+ value: string;
7
+ isSubmitting: boolean;
8
+ attachedFiles: {
9
+ name: string;
10
+ path: string;
11
+ size: number;
12
+ mimeType: string;
13
+ }[];
14
+ onChange: (value: string) => void;
15
+ onSubmit: () => Promise<void>;
16
+ onAttachFile: (file: {
17
+ name: string;
18
+ path: string;
19
+ size: number;
20
+ mimeType: string;
21
+ }) => void;
22
+ onRemoveFile: (index: number) => void;
23
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-chat-input.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/use-chat-input.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAI3D;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;;;;;;;;;sBAezC,MAAM;;yBAkCP;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;0BAU7D,MAAM;EAejB"}
@@ -0,0 +1,63 @@
1
+ import { useCallback } from "react";
2
+ import { useChatStore } from "../store/chat-store.js";
3
+ import { useChatMessages } from "./use-chat-messages.js";
4
+ /**
5
+ * Hook for managing chat input
6
+ */
7
+ export function useChatInput(client) {
8
+ const input = useChatStore((state) => state.input);
9
+ const setInputValue = useChatStore((state) => state.setInputValue);
10
+ const setInputSubmitting = useChatStore((state) => state.setInputSubmitting);
11
+ const addFileAttachment = useChatStore((state) => state.addFileAttachment);
12
+ const removeFileAttachment = useChatStore((state) => state.removeFileAttachment);
13
+ const { sendMessage } = useChatMessages(client);
14
+ /**
15
+ * Handle input value change
16
+ */
17
+ const handleInputChange = useCallback((value) => {
18
+ setInputValue(value);
19
+ }, [setInputValue]);
20
+ /**
21
+ * Handle input submission
22
+ */
23
+ const handleSubmit = useCallback(async () => {
24
+ if (!input.value.trim() || input.isSubmitting) {
25
+ return;
26
+ }
27
+ const message = input.value;
28
+ // Clear input immediately for better UX
29
+ setInputValue("");
30
+ setInputSubmitting(true);
31
+ try {
32
+ await sendMessage(message);
33
+ }
34
+ catch (error) {
35
+ // Error is handled in useChatMessages
36
+ console.error("Failed to send message:", error);
37
+ }
38
+ finally {
39
+ setInputSubmitting(false);
40
+ }
41
+ }, [input, setInputValue, setInputSubmitting, sendMessage]);
42
+ /**
43
+ * Handle file attachment
44
+ */
45
+ const handleAttachFile = useCallback((file) => {
46
+ addFileAttachment(file);
47
+ }, [addFileAttachment]);
48
+ /**
49
+ * Handle file removal
50
+ */
51
+ const handleRemoveFile = useCallback((index) => {
52
+ removeFileAttachment(index);
53
+ }, [removeFileAttachment]);
54
+ return {
55
+ value: input.value,
56
+ isSubmitting: input.isSubmitting,
57
+ attachedFiles: input.attachedFiles,
58
+ onChange: handleInputChange,
59
+ onSubmit: handleSubmit,
60
+ onAttachFile: handleAttachFile,
61
+ onRemoveFile: handleRemoveFile,
62
+ };
63
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-chat-input.js","sourceRoot":"","sources":["../../../src/core/hooks/use-chat-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAwB;IACnD,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,aAAa,GAAG,YAAY,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACnE,MAAM,kBAAkB,GAAG,YAAY,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC7E,MAAM,iBAAiB,GAAG,YAAY,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC3E,MAAM,oBAAoB,GAAG,YAAY,CACvC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,oBAAoB,CACtC,CAAC;IAEF,MAAM,EAAE,WAAW,EAAE,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAEhD;;OAEG;IACH,MAAM,iBAAiB,GAAG,WAAW,CACnC,CAAC,KAAa,EAAE,EAAE;QAChB,aAAa,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC,EACD,CAAC,aAAa,CAAC,CAChB,CAAC;IAEF;;OAEG;IACH,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC;QAE5B,wCAAwC;QACxC,aAAa,CAAC,EAAE,CAAC,CAAC;QAClB,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAEzB,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,sCAAsC;YACtC,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;gBAAS,CAAC;YACT,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,CAAC,CAAC,CAAC;IAE5D;;OAEG;IACH,MAAM,gBAAgB,GAAG,WAAW,CAClC,CAAC,IAAoE,EAAE,EAAE;QACvE,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,EACD,CAAC,iBAAiB,CAAC,CACpB,CAAC;IAEF;;OAEG;IACH,MAAM,gBAAgB,GAAG,WAAW,CAClC,CAAC,KAAa,EAAE,EAAE;QAChB,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC,EACD,CAAC,oBAAoB,CAAC,CACvB,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,QAAQ,EAAE,iBAAiB;QAC3B,QAAQ,EAAE,YAAY;QACtB,YAAY,EAAE,gBAAgB;QAC9B,YAAY,EAAE,gBAAgB;KAC/B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { AcpClient } from "../../sdk/client/index.js";
2
+ /**
3
+ * Hook for managing chat messages
4
+ */
5
+ export declare function useChatMessages(client: AcpClient | null): {
6
+ messages: {
7
+ id: string;
8
+ role: "user" | "assistant" | "system";
9
+ content: string;
10
+ timestamp: string;
11
+ isStreaming: boolean;
12
+ streamingStartTime?: number | undefined;
13
+ metadata?: Record<string, unknown> | undefined;
14
+ }[];
15
+ isStreaming: boolean;
16
+ sendMessage: (content: string) => Promise<void>;
17
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-chat-messages.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/use-chat-messages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAI3D;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;;;;;;;;;;;2BAgBpC,MAAM;EAsHzB"}
@@ -0,0 +1,121 @@
1
+ import { useCallback } from "react";
2
+ import { useChatStore } from "../store/chat-store.js";
3
+ /**
4
+ * Hook for managing chat messages
5
+ */
6
+ export function useChatMessages(client) {
7
+ const messages = useChatStore((state) => state.messages);
8
+ const isStreaming = useChatStore((state) => state.isStreaming);
9
+ const sessionId = useChatStore((state) => state.sessionId);
10
+ const setIsStreaming = useChatStore((state) => state.setIsStreaming);
11
+ const setStreamingStartTime = useChatStore((state) => state.setStreamingStartTime);
12
+ const addMessage = useChatStore((state) => state.addMessage);
13
+ const updateMessage = useChatStore((state) => state.updateMessage);
14
+ const setError = useChatStore((state) => state.setError);
15
+ /**
16
+ * Send a message to the agent
17
+ */
18
+ const sendMessage = useCallback(async (content) => {
19
+ if (!client) {
20
+ console.error("❌ No client available");
21
+ setError("No client available");
22
+ return;
23
+ }
24
+ if (!sessionId) {
25
+ console.error("❌ No active session");
26
+ setError("No active session");
27
+ return;
28
+ }
29
+ try {
30
+ // Start streaming and track time immediately
31
+ const startTime = Date.now();
32
+ setIsStreaming(true);
33
+ setStreamingStartTime(startTime);
34
+ // Add user message to UI
35
+ const userMessage = {
36
+ id: `msg_${Date.now()}_user`,
37
+ role: "user",
38
+ content,
39
+ timestamp: new Date().toISOString(),
40
+ isStreaming: false,
41
+ };
42
+ addMessage(userMessage);
43
+ // Create placeholder for assistant message BEFORE sending
44
+ const assistantMessageId = `msg_${Date.now()}_assistant`;
45
+ const assistantMessage = {
46
+ id: assistantMessageId,
47
+ role: "assistant",
48
+ content: "",
49
+ timestamp: new Date().toISOString(),
50
+ isStreaming: true,
51
+ streamingStartTime: startTime, // Use the same start time from when user sent message
52
+ };
53
+ addMessage(assistantMessage);
54
+ // Build full conversation history (excluding system messages)
55
+ const conversationHistory = messages
56
+ .filter((msg) => msg.role !== "system")
57
+ .map((msg) => `${msg.role === "user" ? "Human" : "Assistant"}: ${msg.content}`)
58
+ .join("\n\n");
59
+ // Combine history with new message
60
+ const fullPrompt = conversationHistory
61
+ ? `${conversationHistory}\n\nHuman: ${content}`
62
+ : content;
63
+ // Start receiving chunks (async iterator)
64
+ const messageStream = client.receiveMessages();
65
+ // Send full conversation without awaiting (fire and forget)
66
+ // This allows chunks to start arriving while we're listening
67
+ client.sendMessage(fullPrompt, sessionId).catch((error) => {
68
+ const message = error instanceof Error ? error.message : String(error);
69
+ setError(message);
70
+ setIsStreaming(false);
71
+ setStreamingStartTime(null);
72
+ });
73
+ // Listen for streaming chunks
74
+ let accumulatedContent = "";
75
+ for await (const chunk of messageStream) {
76
+ if (chunk.isComplete) {
77
+ // Update final message
78
+ updateMessage(assistantMessageId, {
79
+ content: accumulatedContent,
80
+ isStreaming: false,
81
+ streamingStartTime: undefined, // Clear streaming start time
82
+ });
83
+ setIsStreaming(false);
84
+ setStreamingStartTime(null); // Clear global streaming start time
85
+ break;
86
+ }
87
+ else {
88
+ // Update streaming content
89
+ if (chunk.contentDelta.type === "text") {
90
+ accumulatedContent += chunk.contentDelta.text;
91
+ updateMessage(assistantMessageId, {
92
+ content: accumulatedContent,
93
+ });
94
+ // Small delay to allow Ink to render between chunks (~60fps)
95
+ await new Promise((resolve) => setTimeout(resolve, 16));
96
+ }
97
+ }
98
+ }
99
+ }
100
+ catch (error) {
101
+ const message = error instanceof Error ? error.message : String(error);
102
+ setError(message);
103
+ setIsStreaming(false);
104
+ setStreamingStartTime(null); // Clear streaming start time on error
105
+ }
106
+ }, [
107
+ client,
108
+ sessionId,
109
+ messages,
110
+ addMessage,
111
+ updateMessage,
112
+ setIsStreaming,
113
+ setStreamingStartTime,
114
+ setError,
115
+ ]);
116
+ return {
117
+ messages,
118
+ isStreaming,
119
+ sendMessage,
120
+ };
121
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-chat-messages.js","sourceRoot":"","sources":["../../../src/core/hooks/use-chat-messages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { AcpClient } from "../../sdk/client/index.js";
2
+ /**
3
+ * Hook for managing chat session lifecycle
4
+ */
5
+ export declare function useChatSession(client: AcpClient | null): {
6
+ connectionStatus: "error" | "connecting" | "connected" | "disconnected";
7
+ sessionId: string | null;
8
+ connect: () => Promise<void>;
9
+ startSession: () => Promise<void>;
10
+ disconnect: () => Promise<void>;
11
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-chat-session.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/use-chat-session.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAG3D;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;;;;;;EAuFtD"}
@@ -0,0 +1,87 @@
1
+ import { useCallback, useEffect } from "react";
2
+ import { useChatStore } from "../store/chat-store.js";
3
+ /**
4
+ * Hook for managing chat session lifecycle
5
+ */
6
+ export function useChatSession(client) {
7
+ const connectionStatus = useChatStore((state) => state.connectionStatus);
8
+ const sessionId = useChatStore((state) => state.sessionId);
9
+ const setConnectionStatus = useChatStore((state) => state.setConnectionStatus);
10
+ const setSessionId = useChatStore((state) => state.setSessionId);
11
+ const setError = useChatStore((state) => state.setError);
12
+ const clearMessages = useChatStore((state) => state.clearMessages);
13
+ /**
14
+ * Connect to the agent
15
+ */
16
+ const connect = useCallback(async () => {
17
+ if (!client) {
18
+ setError("No client available");
19
+ return;
20
+ }
21
+ try {
22
+ setConnectionStatus("connecting");
23
+ setError(null);
24
+ await client.connect();
25
+ setConnectionStatus("connected");
26
+ }
27
+ catch (error) {
28
+ console.log(error);
29
+ const message = error instanceof Error ? error.message : String(error);
30
+ setError(message);
31
+ setConnectionStatus("error");
32
+ }
33
+ }, [client, setConnectionStatus, setError]);
34
+ /**
35
+ * Start a new session
36
+ */
37
+ const startSession = useCallback(async () => {
38
+ if (!client) {
39
+ setError("No client available");
40
+ return;
41
+ }
42
+ try {
43
+ const id = await client.startSession();
44
+ setSessionId(id);
45
+ clearMessages();
46
+ }
47
+ catch (error) {
48
+ const message = error instanceof Error ? error.message : String(error);
49
+ setError(message);
50
+ }
51
+ }, [client, setSessionId, setError, clearMessages]);
52
+ /**
53
+ * Disconnect from the agent
54
+ */
55
+ const disconnect = useCallback(async () => {
56
+ if (!client)
57
+ return;
58
+ try {
59
+ await client.disconnect();
60
+ setConnectionStatus("disconnected");
61
+ setSessionId(null);
62
+ }
63
+ catch (error) {
64
+ const message = error instanceof Error ? error.message : String(error);
65
+ setError(message);
66
+ }
67
+ }, [client, setConnectionStatus, setSessionId, setError]);
68
+ // Auto-connect on mount if client is available
69
+ useEffect(() => {
70
+ if (client && connectionStatus === "disconnected") {
71
+ connect();
72
+ }
73
+ }, [client, connectionStatus, connect]);
74
+ // Auto-start session after connecting
75
+ useEffect(() => {
76
+ if (connectionStatus === "connected" && !sessionId) {
77
+ startSession();
78
+ }
79
+ }, [connectionStatus, sessionId, startSession]);
80
+ return {
81
+ connectionStatus,
82
+ sessionId,
83
+ connect,
84
+ startSession,
85
+ disconnect,
86
+ };
87
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-chat-session.js","sourceRoot":"","sources":["../../../src/core/hooks/use-chat-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Custom hook for responsive breakpoints with SSR-safe implementation
3
+ *
4
+ * @param query - Media query string (e.g., "(min-width: 768px)")
5
+ * @returns boolean indicating if the media query matches
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const isMobile = useMediaQuery("(max-width: 640px)");
10
+ * const isDesktop = useMediaQuery("(min-width: 1024px)");
11
+ *
12
+ * return (
13
+ * <div>
14
+ * {isMobile && <MobileMenu />}
15
+ * {isDesktop && <DesktopSidebar />}
16
+ * </div>
17
+ * );
18
+ * ```
19
+ */
20
+ export declare function useMediaQuery(query: string): boolean;
21
+ /**
22
+ * Common breakpoint presets for convenience
23
+ */
24
+ export declare const breakpoints: {
25
+ readonly sm: "(min-width: 640px)";
26
+ readonly md: "(min-width: 768px)";
27
+ readonly lg: "(min-width: 1024px)";
28
+ readonly xl: "(min-width: 1280px)";
29
+ readonly "2xl": "(min-width: 1536px)";
30
+ };
31
+ /**
32
+ * Convenience hooks for common breakpoints
33
+ */
34
+ export declare function useIsSmallScreen(): boolean;
35
+ export declare function useIsMediumScreen(): boolean;
36
+ export declare function useIsLargeScreen(): boolean;
37
+ export declare function useIsDesktop(): boolean;
38
+ export declare function useIsMobile(): boolean;
39
+ export declare function useIsTablet(): boolean;
@@ -0,0 +1,80 @@
1
+ import { useEffect, useState } from "react";
2
+ /**
3
+ * Custom hook for responsive breakpoints with SSR-safe implementation
4
+ *
5
+ * @param query - Media query string (e.g., "(min-width: 768px)")
6
+ * @returns boolean indicating if the media query matches
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const isMobile = useMediaQuery("(max-width: 640px)");
11
+ * const isDesktop = useMediaQuery("(min-width: 1024px)");
12
+ *
13
+ * return (
14
+ * <div>
15
+ * {isMobile && <MobileMenu />}
16
+ * {isDesktop && <DesktopSidebar />}
17
+ * </div>
18
+ * );
19
+ * ```
20
+ */
21
+ export function useMediaQuery(query) {
22
+ const [matches, setMatches] = useState(() => {
23
+ // SSR-safe: return false on server, check on client
24
+ if (typeof window === "undefined") {
25
+ return false;
26
+ }
27
+ return window.matchMedia(query).matches;
28
+ });
29
+ useEffect(() => {
30
+ // SSR guard
31
+ if (typeof window === "undefined") {
32
+ return;
33
+ }
34
+ const mediaQueryList = window.matchMedia(query);
35
+ // Update state if query evaluation changes
36
+ const handleChange = (event) => {
37
+ setMatches(event.matches);
38
+ };
39
+ // Set initial value
40
+ setMatches(mediaQueryList.matches);
41
+ // Listen for changes
42
+ mediaQueryList.addEventListener("change", handleChange);
43
+ // Cleanup
44
+ return () => {
45
+ mediaQueryList.removeEventListener("change", handleChange);
46
+ };
47
+ }, [query]);
48
+ return matches;
49
+ }
50
+ /**
51
+ * Common breakpoint presets for convenience
52
+ */
53
+ export const breakpoints = {
54
+ sm: "(min-width: 640px)",
55
+ md: "(min-width: 768px)",
56
+ lg: "(min-width: 1024px)",
57
+ xl: "(min-width: 1280px)",
58
+ "2xl": "(min-width: 1536px)",
59
+ };
60
+ /**
61
+ * Convenience hooks for common breakpoints
62
+ */
63
+ export function useIsSmallScreen() {
64
+ return useMediaQuery("(max-width: 639px)");
65
+ }
66
+ export function useIsMediumScreen() {
67
+ return useMediaQuery(breakpoints.md);
68
+ }
69
+ export function useIsLargeScreen() {
70
+ return useMediaQuery(breakpoints.lg);
71
+ }
72
+ export function useIsDesktop() {
73
+ return useMediaQuery(breakpoints.lg);
74
+ }
75
+ export function useIsMobile() {
76
+ return useMediaQuery("(max-width: 767px)");
77
+ }
78
+ export function useIsTablet() {
79
+ return useMediaQuery("(min-width: 768px) and (max-width: 1023px)");
80
+ }