@townco/ui 0.1.3 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/dist/core/hooks/use-chat-input.d.ts +17 -17
- package/dist/core/hooks/use-chat-input.js +55 -64
- package/dist/core/hooks/use-chat-messages.d.ts +11 -11
- package/dist/core/hooks/use-chat-messages.js +114 -121
- package/dist/core/hooks/use-chat-session.d.ts +5 -5
- package/dist/core/hooks/use-chat-session.js +80 -78
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/schemas/chat.d.ts +56 -83
- package/dist/core/schemas/chat.js +25 -27
- package/dist/core/store/chat-store.d.ts +22 -28
- package/dist/core/store/chat-store.js +50 -59
- package/dist/gui/components/Button.d.ts +7 -23
- package/dist/gui/components/Button.js +27 -40
- package/dist/gui/components/Card.d.ts +7 -26
- package/dist/gui/components/Card.js +8 -54
- package/dist/gui/components/ChatInput.d.ts +36 -58
- package/dist/gui/components/ChatInput.js +121 -191
- package/dist/gui/components/ChatSecondaryPanel.d.ts +11 -14
- package/dist/gui/components/ChatSecondaryPanel.js +38 -115
- package/dist/gui/components/ChatStatus.d.ts +2 -4
- package/dist/gui/components/ChatStatus.js +34 -45
- package/dist/gui/components/Conversation.d.ts +14 -17
- package/dist/gui/components/Conversation.js +83 -143
- package/dist/gui/components/Dialog.d.ts +11 -57
- package/dist/gui/components/Dialog.js +8 -84
- package/dist/gui/components/HeightTransition.d.ts +7 -12
- package/dist/gui/components/HeightTransition.js +77 -88
- package/dist/gui/components/Input.d.ts +6 -13
- package/dist/gui/components/Input.js +16 -27
- package/dist/gui/components/Label.d.ts +1 -7
- package/dist/gui/components/Label.js +2 -12
- package/dist/gui/components/MarkdownRenderer.d.ts +4 -6
- package/dist/gui/components/MarkdownRenderer.js +81 -178
- package/dist/gui/components/Message.d.ts +18 -25
- package/dist/gui/components/Message.js +23 -44
- package/dist/gui/components/MessageContent.d.ts +22 -29
- package/dist/gui/components/MessageContent.js +85 -157
- package/dist/gui/components/Reasoning.d.ts +24 -30
- package/dist/gui/components/Reasoning.js +60 -187
- package/dist/gui/components/Response.d.ts +9 -11
- package/dist/gui/components/Response.js +90 -229
- package/dist/gui/components/Select.d.ts +10 -69
- package/dist/gui/components/Select.js +12 -118
- package/dist/gui/components/Tabs.d.ts +4 -24
- package/dist/gui/components/Tabs.js +4 -32
- package/dist/gui/components/Task.d.ts +24 -28
- package/dist/gui/components/Task.js +31 -164
- package/dist/gui/components/Textarea.d.ts +7 -15
- package/dist/gui/components/Textarea.js +46 -63
- package/dist/gui/components/ThinkingBlock.d.ts +10 -20
- package/dist/gui/components/ThinkingBlock.js +35 -134
- package/dist/gui/components/TodoList.d.ts +10 -12
- package/dist/gui/components/TodoList.js +7 -22
- package/dist/gui/components/TodoListItem.d.ts +6 -9
- package/dist/gui/components/TodoListItem.js +4 -18
- package/dist/gui/components/index.d.ts +8 -59
- package/dist/gui/components/index.js +8 -42
- package/dist/gui/lib/utils.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.test.js +1 -0
- package/dist/sdk/client/acp-client.d.ts +76 -88
- package/dist/sdk/client/acp-client.js +217 -215
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/schemas/agent.d.ts +64 -111
- package/dist/sdk/schemas/agent.js +24 -24
- package/dist/sdk/schemas/message.d.ts +147 -245
- package/dist/sdk/schemas/message.js +40 -40
- package/dist/sdk/schemas/session.d.ts +135 -219
- package/dist/sdk/schemas/session.js +27 -27
- package/dist/sdk/transports/http.d.ts +55 -55
- package/dist/sdk/transports/http.js +469 -472
- package/dist/sdk/transports/stdio.d.ts +20 -20
- package/dist/sdk/transports/stdio.js +286 -289
- package/dist/sdk/transports/types.d.ts +42 -42
- package/dist/sdk/transports/websocket.d.ts +12 -12
- package/dist/sdk/transports/websocket.js +46 -52
- package/dist/tui/components/ChatView.d.ts +2 -4
- package/dist/tui/components/ChatView.js +18 -51
- package/dist/tui/components/GameOfLife.js +35 -64
- package/dist/tui/components/InputBox.d.ts +11 -18
- package/dist/tui/components/InputBox.js +10 -70
- package/dist/tui/components/MessageList.d.ts +2 -4
- package/dist/tui/components/MessageList.js +10 -37
- package/dist/tui/components/MultiSelect.d.ts +10 -15
- package/dist/tui/components/MultiSelect.js +73 -116
- package/dist/tui/components/ReadlineInput.d.ts +6 -12
- package/dist/tui/components/ReadlineInput.js +237 -252
- package/dist/tui/components/SingleSelect.d.ts +9 -15
- package/dist/tui/components/SingleSelect.js +43 -84
- package/dist/tui/components/StatusBar.d.ts +6 -11
- package/dist/tui/components/StatusBar.js +67 -102
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +1 -1
- package/package.json +2 -2
- package/dist/core/hooks/index.d.ts.map +0 -1
- package/dist/core/hooks/index.js.map +0 -1
- package/dist/core/hooks/use-chat-input.d.ts.map +0 -1
- package/dist/core/hooks/use-chat-input.js.map +0 -1
- package/dist/core/hooks/use-chat-messages.d.ts.map +0 -1
- package/dist/core/hooks/use-chat-messages.js.map +0 -1
- package/dist/core/hooks/use-chat-session.d.ts.map +0 -1
- package/dist/core/hooks/use-chat-session.js.map +0 -1
- package/dist/core/hooks/use-media-query.d.ts +0 -39
- package/dist/core/hooks/use-media-query.js +0 -80
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js.map +0 -1
- package/dist/core/schemas/chat.d.ts.map +0 -1
- package/dist/core/schemas/chat.js.map +0 -1
- package/dist/core/schemas/index.d.ts.map +0 -1
- package/dist/core/schemas/index.js.map +0 -1
- package/dist/core/store/chat-store.d.ts.map +0 -1
- package/dist/core/store/chat-store.js.map +0 -1
- package/dist/gui/components/Button.d.ts.map +0 -1
- package/dist/gui/components/Button.js.map +0 -1
- package/dist/gui/components/Card.d.ts.map +0 -1
- package/dist/gui/components/Card.js.map +0 -1
- package/dist/gui/components/ChatHeader.d.ts +0 -65
- package/dist/gui/components/ChatHeader.js +0 -189
- package/dist/gui/components/ChatInput.d.ts.map +0 -1
- package/dist/gui/components/ChatInput.js.map +0 -1
- package/dist/gui/components/ChatInterface.d.ts +0 -12
- package/dist/gui/components/ChatInterface.d.ts.map +0 -1
- package/dist/gui/components/ChatInterface.js +0 -204
- package/dist/gui/components/ChatInterface.js.map +0 -1
- package/dist/gui/components/ChatLayout.d.ts +0 -82
- package/dist/gui/components/ChatLayout.js +0 -232
- package/dist/gui/components/ChatPanelTabContent.d.ts +0 -27
- package/dist/gui/components/ChatPanelTabContent.js +0 -93
- package/dist/gui/components/ChatPreview.d.ts +0 -12
- package/dist/gui/components/ChatPreview.d.ts.map +0 -1
- package/dist/gui/components/ChatPreview.js +0 -214
- package/dist/gui/components/ChatPreview.js.map +0 -1
- package/dist/gui/components/ChatSecondaryPanel.d.ts.map +0 -1
- package/dist/gui/components/ChatSecondaryPanel.js.map +0 -1
- package/dist/gui/components/ChatSidebar.d.ts +0 -27
- package/dist/gui/components/ChatSidebar.js +0 -57
- package/dist/gui/components/ChatStatus.d.ts.map +0 -1
- package/dist/gui/components/ChatStatus.js.map +0 -1
- package/dist/gui/components/ChatView.d.ts +0 -8
- package/dist/gui/components/ChatView.d.ts.map +0 -1
- package/dist/gui/components/ChatView.js +0 -42
- package/dist/gui/components/ChatView.js.map +0 -1
- package/dist/gui/components/ConfigPanel.d.ts +0 -20
- package/dist/gui/components/ConfigPanel.d.ts.map +0 -1
- package/dist/gui/components/ConfigPanel.js +0 -225
- package/dist/gui/components/ConfigPanel.js.map +0 -1
- package/dist/gui/components/Conversation.d.ts.map +0 -1
- package/dist/gui/components/Conversation.js.map +0 -1
- package/dist/gui/components/Dialog.d.ts.map +0 -1
- package/dist/gui/components/Dialog.js.map +0 -1
- package/dist/gui/components/DropdownMenu.d.ts +0 -108
- package/dist/gui/components/DropdownMenu.js +0 -215
- package/dist/gui/components/HeightTransition.d.ts.map +0 -1
- package/dist/gui/components/HeightTransition.js.map +0 -1
- package/dist/gui/components/Input.d.ts.map +0 -1
- package/dist/gui/components/Input.js.map +0 -1
- package/dist/gui/components/InputBox.d.ts +0 -21
- package/dist/gui/components/InputBox.d.ts.map +0 -1
- package/dist/gui/components/InputBox.js +0 -90
- package/dist/gui/components/InputBox.js.map +0 -1
- package/dist/gui/components/Label.d.ts.map +0 -1
- package/dist/gui/components/Label.js.map +0 -1
- package/dist/gui/components/MarkdownRenderer.d.ts.map +0 -1
- package/dist/gui/components/MarkdownRenderer.js.map +0 -1
- package/dist/gui/components/Message.d.ts.map +0 -1
- package/dist/gui/components/Message.js.map +0 -1
- package/dist/gui/components/MessageContent.d.ts.map +0 -1
- package/dist/gui/components/MessageContent.js.map +0 -1
- package/dist/gui/components/MessageList.d.ts.map +0 -1
- package/dist/gui/components/MessageList.js.map +0 -1
- package/dist/gui/components/PlaygroundLayout.d.ts +0 -14
- package/dist/gui/components/PlaygroundLayout.d.ts.map +0 -1
- package/dist/gui/components/PlaygroundLayout.js +0 -49
- package/dist/gui/components/PlaygroundLayout.js.map +0 -1
- package/dist/gui/components/Reasoning.d.ts.map +0 -1
- package/dist/gui/components/Reasoning.js.map +0 -1
- package/dist/gui/components/Response.d.ts.map +0 -1
- package/dist/gui/components/Response.js.map +0 -1
- package/dist/gui/components/Select.d.ts.map +0 -1
- package/dist/gui/components/Select.js.map +0 -1
- package/dist/gui/components/Sonner.d.ts +0 -7
- package/dist/gui/components/Sonner.js +0 -34
- package/dist/gui/components/StatusBar.d.ts +0 -12
- package/dist/gui/components/StatusBar.d.ts.map +0 -1
- package/dist/gui/components/StatusBar.js +0 -58
- package/dist/gui/components/StatusBar.js.map +0 -1
- package/dist/gui/components/Tabs.d.ts.map +0 -1
- package/dist/gui/components/Tabs.js.map +0 -1
- package/dist/gui/components/Task.d.ts.map +0 -1
- package/dist/gui/components/Task.js.map +0 -1
- package/dist/gui/components/Textarea.d.ts.map +0 -1
- package/dist/gui/components/Textarea.js.map +0 -1
- package/dist/gui/components/ThinkingBlock.d.ts.map +0 -1
- package/dist/gui/components/ThinkingBlock.js.map +0 -1
- package/dist/gui/components/TodoList.d.ts.map +0 -1
- package/dist/gui/components/TodoList.js.map +0 -1
- package/dist/gui/components/TodoListItem.d.ts.map +0 -1
- package/dist/gui/components/TodoListItem.js.map +0 -1
- package/dist/gui/components/index.d.ts.map +0 -1
- package/dist/gui/components/index.js.map +0 -1
- package/dist/gui/index.d.ts.map +0 -1
- package/dist/gui/index.js.map +0 -1
- package/dist/gui/lib/utils.d.ts.map +0 -1
- package/dist/gui/lib/utils.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/sdk/client/acp-client.d.ts.map +0 -1
- package/dist/sdk/client/acp-client.js.map +0 -1
- package/dist/sdk/client/index.d.ts.map +0 -1
- package/dist/sdk/client/index.js.map +0 -1
- package/dist/sdk/index.d.ts.map +0 -1
- package/dist/sdk/index.js.map +0 -1
- package/dist/sdk/schemas/agent.d.ts.map +0 -1
- package/dist/sdk/schemas/agent.js.map +0 -1
- package/dist/sdk/schemas/index.d.ts.map +0 -1
- package/dist/sdk/schemas/index.js.map +0 -1
- package/dist/sdk/schemas/message.d.ts.map +0 -1
- package/dist/sdk/schemas/message.js.map +0 -1
- package/dist/sdk/schemas/session.d.ts.map +0 -1
- package/dist/sdk/schemas/session.js.map +0 -1
- package/dist/sdk/transports/http.d.ts.map +0 -1
- package/dist/sdk/transports/http.js.map +0 -1
- package/dist/sdk/transports/index.d.ts.map +0 -1
- package/dist/sdk/transports/index.js.map +0 -1
- package/dist/sdk/transports/stdio.d.ts.map +0 -1
- package/dist/sdk/transports/stdio.js.map +0 -1
- package/dist/sdk/transports/types.d.ts.map +0 -1
- package/dist/sdk/transports/types.js.map +0 -1
- package/dist/sdk/transports/websocket.d.ts.map +0 -1
- package/dist/sdk/transports/websocket.js.map +0 -1
- package/dist/tui/components/ChatView.d.ts.map +0 -1
- package/dist/tui/components/ChatView.js.map +0 -1
- package/dist/tui/components/GameOfLife.d.ts.map +0 -1
- package/dist/tui/components/GameOfLife.js.map +0 -1
- package/dist/tui/components/InputBox.d.ts.map +0 -1
- package/dist/tui/components/InputBox.js.map +0 -1
- package/dist/tui/components/MessageList.d.ts.map +0 -1
- package/dist/tui/components/MessageList.js.map +0 -1
- package/dist/tui/components/ReadlineInput.d.ts.map +0 -1
- package/dist/tui/components/ReadlineInput.js.map +0 -1
- package/dist/tui/components/StatusBar.d.ts.map +0 -1
- package/dist/tui/components/StatusBar.js.map +0 -1
- package/dist/tui/components/index.d.ts.map +0 -1
- package/dist/tui/components/index.js.map +0 -1
- package/dist/tui/index.d.ts.map +0 -1
- package/dist/tui/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @townco/ui
|
|
2
2
|
|
|
3
3
|
Unified UI package with composable components for chat interfaces.
|
|
4
4
|
|
|
@@ -6,14 +6,14 @@ Unified UI package with composable components for chat interfaces.
|
|
|
6
6
|
|
|
7
7
|
Three layers:
|
|
8
8
|
|
|
9
|
-
1. **Core** (`@
|
|
10
|
-
1. **TUI** (`@
|
|
11
|
-
1. **GUI** (`@
|
|
9
|
+
1. **Core** (`@townco/ui/core`) - Headless business logic
|
|
10
|
+
1. **TUI** (`@townco/ui/tui`) - Terminal renderers (Ink)
|
|
11
|
+
1. **GUI** (`@townco/ui/gui`) - Web renderers (React + Tailwind)
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
bun add @
|
|
16
|
+
bun add @townco/ui @townco/ui
|
|
17
17
|
|
|
18
18
|
# For TUI
|
|
19
19
|
bun add ink react
|
|
@@ -27,7 +27,7 @@ bun add react react-dom
|
|
|
27
27
|
### Core (Headless Hooks)
|
|
28
28
|
|
|
29
29
|
```typescript
|
|
30
|
-
import { useChatSession, useChatMessages, useChatInput } from "@
|
|
30
|
+
import { useChatSession, useChatMessages, useChatInput } from "@townco/ui/core";
|
|
31
31
|
|
|
32
32
|
function MyComponent({ client }) {
|
|
33
33
|
const { connectionStatus, sessionId } = useChatSession(client);
|
|
@@ -42,8 +42,8 @@ function MyComponent({ client }) {
|
|
|
42
42
|
|
|
43
43
|
```typescript
|
|
44
44
|
import { render } from "ink";
|
|
45
|
-
import { ChatView } from "@
|
|
46
|
-
import { AcpClient } from "@
|
|
45
|
+
import { ChatView } from "@townco/ui/tui";
|
|
46
|
+
import { AcpClient } from "@townco/ui";
|
|
47
47
|
|
|
48
48
|
const client = new AcpClient({ stdio: { agentPath: "./agent" } });
|
|
49
49
|
render(<ChatView client={client} />);
|
|
@@ -53,8 +53,8 @@ render(<ChatView client={client} />);
|
|
|
53
53
|
|
|
54
54
|
```typescript
|
|
55
55
|
import ReactDOM from "react-dom/client";
|
|
56
|
-
import { ChatView } from "@
|
|
57
|
-
import { AcpClient } from "@
|
|
56
|
+
import { ChatView } from "@townco/ui/gui";
|
|
57
|
+
import { AcpClient } from "@townco/ui";
|
|
58
58
|
|
|
59
59
|
const client = new AcpClient({ http: { baseUrl: "http://localhost:8080" } });
|
|
60
60
|
ReactDOM.createRoot(root).render(<ChatView client={client} />);
|
|
@@ -152,7 +152,7 @@ bun test
|
|
|
152
152
|
## Example: Custom Component
|
|
153
153
|
|
|
154
154
|
```typescript
|
|
155
|
-
import { useChatMessages, useChatInput } from "@
|
|
155
|
+
import { useChatMessages, useChatInput } from "@townco/ui/core";
|
|
156
156
|
|
|
157
157
|
function CustomChat({ client }) {
|
|
158
158
|
const { messages, sendMessage } = useChatMessages(client);
|
|
@@ -3,21 +3,21 @@ import type { AcpClient } from "../../sdk/client/index.js";
|
|
|
3
3
|
* Hook for managing chat input
|
|
4
4
|
*/
|
|
5
5
|
export declare function useChatInput(client: AcpClient | null): {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
23
|
};
|
|
@@ -5,68 +5,59 @@ import { useChatMessages } from "./use-chat-messages.js";
|
|
|
5
5
|
* Hook for managing chat input
|
|
6
6
|
*/
|
|
7
7
|
export function useChatInput(client) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
value: input.value,
|
|
65
|
-
isSubmitting: input.isSubmitting,
|
|
66
|
-
attachedFiles: input.attachedFiles,
|
|
67
|
-
onChange: handleInputChange,
|
|
68
|
-
onSubmit: handleSubmit,
|
|
69
|
-
onAttachFile: handleAttachFile,
|
|
70
|
-
onRemoveFile: handleRemoveFile,
|
|
71
|
-
};
|
|
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
|
+
};
|
|
72
63
|
}
|
|
@@ -3,15 +3,15 @@ import type { AcpClient } from "../../sdk/client/index.js";
|
|
|
3
3
|
* Hook for managing chat messages
|
|
4
4
|
*/
|
|
5
5
|
export declare function useChatMessages(client: AcpClient | null): {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
17
|
};
|
|
@@ -4,125 +4,118 @@ import { useChatStore } from "../store/chat-store.js";
|
|
|
4
4
|
* Hook for managing chat messages
|
|
5
5
|
*/
|
|
6
6
|
export function useChatMessages(client) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
],
|
|
122
|
-
);
|
|
123
|
-
return {
|
|
124
|
-
messages,
|
|
125
|
-
isStreaming,
|
|
126
|
-
sendMessage,
|
|
127
|
-
};
|
|
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
|
+
};
|
|
128
121
|
}
|
|
@@ -3,9 +3,9 @@ import type { AcpClient } from "../../sdk/client/index.js";
|
|
|
3
3
|
* Hook for managing chat session lifecycle
|
|
4
4
|
*/
|
|
5
5
|
export declare function useChatSession(client: AcpClient | null): {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
connectionStatus: "error" | "connecting" | "connected" | "disconnected";
|
|
7
|
+
sessionId: string | null;
|
|
8
|
+
connect: () => Promise<void>;
|
|
9
|
+
startSession: () => Promise<void>;
|
|
10
|
+
disconnect: () => Promise<void>;
|
|
11
11
|
};
|