@curaious/uno-converse 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 +282 -0
- package/dist/index.cjs +870 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +473 -0
- package/dist/index.d.ts +473 -0
- package/dist/index.js +860 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# @curaious/uno-converse
|
|
2
|
+
|
|
3
|
+
React hooks and utilities for building conversation UIs with [Uno Agent Server](https://github.com/curaious/uno).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎣 **React Hook** - `useConversation` hook for complete conversation state management
|
|
8
|
+
- 🌊 **Streaming Support** - Built-in SSE streaming with real-time message updates
|
|
9
|
+
- 📦 **Type Safe** - Full TypeScript support with comprehensive type definitions
|
|
10
|
+
- 🔌 **Flexible API Client** - Bring your own API client or use the built-in one
|
|
11
|
+
- 🎯 **Zero Dependencies** - Only React as a peer dependency
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# npm
|
|
17
|
+
npm install @curaious/uno-converse
|
|
18
|
+
|
|
19
|
+
# yarn
|
|
20
|
+
yarn add @curaious/uno-converse
|
|
21
|
+
|
|
22
|
+
# pnpm
|
|
23
|
+
pnpm add @curaious/uno-converse
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### GitHub Packages Registry
|
|
27
|
+
|
|
28
|
+
This package is published to GitHub Packages. You'll need to configure npm to use the GitHub registry for `@curaious` scoped packages:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Create or edit ~/.npmrc
|
|
32
|
+
echo "@curaious:registry=https://npm.pkg.github.com" >> ~/.npmrc
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
You may also need to authenticate with a GitHub personal access token:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
echo "//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN" >> ~/.npmrc
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { useConversation, createApiClient, MessageType, ContentType } from '@curaious/uno-converse';
|
|
45
|
+
|
|
46
|
+
// Create an API client
|
|
47
|
+
const client = createApiClient({
|
|
48
|
+
baseUrl: 'https://your-uno-server.com/api/agent-server',
|
|
49
|
+
headers: {
|
|
50
|
+
'Authorization': 'Bearer your-api-key',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
function ChatApp() {
|
|
55
|
+
const {
|
|
56
|
+
allMessages,
|
|
57
|
+
isStreaming,
|
|
58
|
+
sendMessage,
|
|
59
|
+
startNewChat,
|
|
60
|
+
conversations,
|
|
61
|
+
selectConversation,
|
|
62
|
+
} = useConversation({
|
|
63
|
+
namespace: 'my-app',
|
|
64
|
+
client,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const handleSend = async (text: string) => {
|
|
68
|
+
await sendMessage(
|
|
69
|
+
[{
|
|
70
|
+
type: MessageType.Message,
|
|
71
|
+
id: Date.now().toString(),
|
|
72
|
+
content: [{ type: ContentType.InputText, text }],
|
|
73
|
+
}],
|
|
74
|
+
{
|
|
75
|
+
baseUrl: client.baseUrl,
|
|
76
|
+
namespace: 'my-app',
|
|
77
|
+
agentName: 'my-agent',
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<div>
|
|
84
|
+
<button onClick={startNewChat}>New Chat</button>
|
|
85
|
+
|
|
86
|
+
<div className="messages">
|
|
87
|
+
{allMessages.map((msg) => (
|
|
88
|
+
<Message key={msg.message_id} message={msg} />
|
|
89
|
+
))}
|
|
90
|
+
{isStreaming && <LoadingIndicator />}
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<ChatInput onSend={handleSend} disabled={isStreaming} />
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## API Reference
|
|
100
|
+
|
|
101
|
+
### `useConversation(options)`
|
|
102
|
+
|
|
103
|
+
The main hook for managing conversation state.
|
|
104
|
+
|
|
105
|
+
#### Options
|
|
106
|
+
|
|
107
|
+
| Option | Type | Default | Description |
|
|
108
|
+
|--------|------|---------|-------------|
|
|
109
|
+
| `namespace` | `string` | required | Namespace for organizing conversations |
|
|
110
|
+
| `client` | `UnoApiClient` | required | API client for communicating with Uno server |
|
|
111
|
+
| `autoLoad` | `boolean` | `true` | Auto-load conversations on mount |
|
|
112
|
+
|
|
113
|
+
#### Return Value
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
interface UseConversationReturn {
|
|
117
|
+
// State
|
|
118
|
+
conversations: Conversation[];
|
|
119
|
+
conversationsLoading: boolean;
|
|
120
|
+
threads: Thread[];
|
|
121
|
+
threadsLoading: boolean;
|
|
122
|
+
currentThread: Thread | null;
|
|
123
|
+
messages: ConversationMessage[];
|
|
124
|
+
streamingMessage: ConversationMessage | null;
|
|
125
|
+
messagesLoading: boolean;
|
|
126
|
+
isStreaming: boolean;
|
|
127
|
+
currentConversationId: string | null;
|
|
128
|
+
currentThreadId: string | null;
|
|
129
|
+
allMessages: ConversationMessage[];
|
|
130
|
+
|
|
131
|
+
// Actions
|
|
132
|
+
loadConversations: () => Promise<void>;
|
|
133
|
+
selectConversation: (conversationId: string) => void;
|
|
134
|
+
loadThreads: (conversationId: string) => Promise<void>;
|
|
135
|
+
selectThread: (threadId: string) => void;
|
|
136
|
+
sendMessage: (messages: MessageUnion[], config: ConverseConfig) => Promise<void>;
|
|
137
|
+
startNewChat: () => void;
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### `createApiClient(options)`
|
|
142
|
+
|
|
143
|
+
Creates a default API client using fetch.
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
const client = createApiClient({
|
|
147
|
+
baseUrl: 'https://your-server.com/api/agent-server',
|
|
148
|
+
headers: { 'Authorization': 'Bearer token' },
|
|
149
|
+
projectId: 'optional-project-id',
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Custom API Client
|
|
154
|
+
|
|
155
|
+
You can implement your own API client:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import type { UnoApiClient } from '@curaious/uno-converse';
|
|
159
|
+
|
|
160
|
+
const customClient: UnoApiClient = {
|
|
161
|
+
baseUrl: 'https://your-server.com',
|
|
162
|
+
headers: { 'Authorization': 'Bearer token' },
|
|
163
|
+
|
|
164
|
+
async getConversations(namespace) {
|
|
165
|
+
// Your implementation
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
async getThreads(conversationId, namespace) {
|
|
169
|
+
// Your implementation
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
async getMessages(threadId, namespace) {
|
|
173
|
+
// Your implementation
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
async getMessage(messageId, namespace) {
|
|
177
|
+
// Your implementation
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Streaming Utilities
|
|
183
|
+
|
|
184
|
+
For advanced use cases, you can use the streaming utilities directly:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import { streamSSE, ChunkProcessor } from '@curaious/uno-converse';
|
|
188
|
+
|
|
189
|
+
// Stream SSE events
|
|
190
|
+
await streamSSE(
|
|
191
|
+
'https://your-server.com/converse',
|
|
192
|
+
{ method: 'POST', body: JSON.stringify(payload) },
|
|
193
|
+
{
|
|
194
|
+
onChunk: (data) => console.log('Chunk:', data),
|
|
195
|
+
onComplete: () => console.log('Done'),
|
|
196
|
+
onError: (err) => console.error('Error:', err),
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
// Process chunks into conversation messages
|
|
201
|
+
const processor = new ChunkProcessor(
|
|
202
|
+
'conversation-id',
|
|
203
|
+
'thread-id',
|
|
204
|
+
(conversation) => updateUI(conversation)
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
processor.processChunk(jsonString);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Message Types
|
|
211
|
+
|
|
212
|
+
The library exports comprehensive types for all message formats:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import {
|
|
216
|
+
MessageType,
|
|
217
|
+
ContentType,
|
|
218
|
+
Role,
|
|
219
|
+
type MessageUnion,
|
|
220
|
+
type InputMessage,
|
|
221
|
+
type FunctionCallMessage,
|
|
222
|
+
type ReasoningMessage,
|
|
223
|
+
} from '@curaious/uno-converse';
|
|
224
|
+
|
|
225
|
+
// Create a user message
|
|
226
|
+
const userMessage: InputMessage = {
|
|
227
|
+
type: MessageType.Message,
|
|
228
|
+
role: Role.User,
|
|
229
|
+
content: [
|
|
230
|
+
{ type: ContentType.InputText, text: 'Hello!' },
|
|
231
|
+
],
|
|
232
|
+
};
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Tool Call Approvals
|
|
236
|
+
|
|
237
|
+
Handle human-in-the-loop scenarios with function call approvals:
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
const { sendMessage } = useConversation({ ... });
|
|
241
|
+
|
|
242
|
+
// Approve or reject pending tool calls
|
|
243
|
+
const handleApproval = async (approvedIds: string[], rejectedIds: string[]) => {
|
|
244
|
+
await sendMessage(
|
|
245
|
+
[{
|
|
246
|
+
type: MessageType.FunctionCallApprovalResponse,
|
|
247
|
+
id: Date.now().toString(),
|
|
248
|
+
approved_call_ids: approvedIds,
|
|
249
|
+
rejected_call_ids: rejectedIds,
|
|
250
|
+
}],
|
|
251
|
+
converseConfig
|
|
252
|
+
);
|
|
253
|
+
};
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Type Guards
|
|
257
|
+
|
|
258
|
+
The library exports type guard functions for runtime type checking:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import {
|
|
262
|
+
isEasyMessage,
|
|
263
|
+
isInputMessage,
|
|
264
|
+
isFunctionCallMessage,
|
|
265
|
+
isReasoningMessage,
|
|
266
|
+
} from '@curaious/uno-converse';
|
|
267
|
+
|
|
268
|
+
allMessages.forEach((msg) => {
|
|
269
|
+
msg.messages.forEach((m) => {
|
|
270
|
+
if (isFunctionCallMessage(m)) {
|
|
271
|
+
console.log('Function call:', m.name, m.arguments);
|
|
272
|
+
} else if (isReasoningMessage(m)) {
|
|
273
|
+
console.log('Reasoning:', m.summary);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## License
|
|
280
|
+
|
|
281
|
+
MIT
|
|
282
|
+
|