ai.matey.react.core 0.2.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.
@@ -0,0 +1,415 @@
1
+ /**
2
+ * useChat Hook
3
+ *
4
+ * React hook for building chat interfaces with streaming support.
5
+ * Supports both HTTP API mode and direct backend mode.
6
+ *
7
+ * @module
8
+ */
9
+ import { useState, useCallback, useRef, useId, useEffect } from 'react';
10
+ import { createChat } from 'ai.matey.wrapper';
11
+ /**
12
+ * Generate a unique ID.
13
+ */
14
+ function generateUniqueId() {
15
+ return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
16
+ }
17
+ /**
18
+ * Convert React Message to IR message format.
19
+ */
20
+ function messageToIR(message) {
21
+ return {
22
+ role: message.role,
23
+ content: message.content,
24
+ };
25
+ }
26
+ /**
27
+ * useChat - React hook for chat interfaces.
28
+ *
29
+ * Provides state management, streaming, and utilities for building
30
+ * chat applications with AI backends.
31
+ *
32
+ * Supports two modes:
33
+ * 1. HTTP Mode (default): Uses `api` endpoint with fetch
34
+ * 2. Direct Mode: Uses `direct.backend` for direct backend access
35
+ *
36
+ * @example HTTP Mode
37
+ * ```tsx
38
+ * import { useChat } from 'ai.matey.react.core';
39
+ *
40
+ * function ChatComponent() {
41
+ * const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
42
+ * api: '/api/chat',
43
+ * });
44
+ *
45
+ * return (
46
+ * <div>
47
+ * {messages.map((m) => (
48
+ * <div key={m.id}>{m.role}: {m.content}</div>
49
+ * ))}
50
+ * <form onSubmit={handleSubmit}>
51
+ * <input value={input} onChange={handleInputChange} />
52
+ * <button type="submit" disabled={isLoading}>Send</button>
53
+ * </form>
54
+ * </div>
55
+ * );
56
+ * }
57
+ * ```
58
+ *
59
+ * @example Direct Mode
60
+ * ```tsx
61
+ * import { useChat } from 'ai.matey.react.core';
62
+ * import { AnthropicBackend } from 'ai.matey.backend/anthropic';
63
+ *
64
+ * const backend = new AnthropicBackend({ apiKey: process.env.ANTHROPIC_API_KEY });
65
+ *
66
+ * function ChatComponent() {
67
+ * const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
68
+ * direct: {
69
+ * backend,
70
+ * systemPrompt: 'You are a helpful assistant.',
71
+ * },
72
+ * });
73
+ *
74
+ * return (
75
+ * <div>
76
+ * {messages.map((m) => (
77
+ * <div key={m.id}>{m.role}: {m.content}</div>
78
+ * ))}
79
+ * <form onSubmit={handleSubmit}>
80
+ * <input value={input} onChange={handleInputChange} />
81
+ * <button type="submit" disabled={isLoading}>Send</button>
82
+ * </form>
83
+ * </div>
84
+ * );
85
+ * }
86
+ * ```
87
+ */
88
+ export function useChat(options = {}) {
89
+ const { initialMessages = [], initialInput = '', id,
90
+ // HTTP mode options
91
+ api = '/api/chat', headers = {}, body = {}, streamProtocol = 'data', onResponse,
92
+ // Direct mode options
93
+ direct,
94
+ // Common options
95
+ generateId = generateUniqueId, onFinish, onError, keepLastMessageOnError = true, maxToolRoundtrips = 0, sendExtraMessageFields = false, } = options;
96
+ // Determine mode
97
+ const isDirectMode = !!direct;
98
+ // Generate a stable ID for this chat instance
99
+ const hookId = useId();
100
+ const chatId = id ?? hookId;
101
+ // State
102
+ const [messages, setMessages] = useState(initialMessages);
103
+ const [input, setInput] = useState(initialInput);
104
+ const [isLoading, setIsLoading] = useState(false);
105
+ const [error, setError] = useState(undefined);
106
+ const [data, _setData] = useState(undefined);
107
+ // Refs
108
+ const abortControllerRef = useRef(null);
109
+ const chatRef = useRef(null);
110
+ // Create Chat instance for direct mode
111
+ useEffect(() => {
112
+ if (isDirectMode && direct) {
113
+ chatRef.current = createChat({
114
+ backend: direct.backend,
115
+ systemPrompt: direct.systemPrompt,
116
+ defaultParameters: direct.defaultParameters,
117
+ tools: direct.tools,
118
+ onToolCall: direct.onToolCall,
119
+ autoExecuteTools: direct.autoExecuteTools,
120
+ maxToolRounds: direct.maxToolRounds ?? maxToolRoundtrips,
121
+ });
122
+ }
123
+ return () => {
124
+ chatRef.current = null;
125
+ };
126
+ }, [isDirectMode, direct, maxToolRoundtrips]);
127
+ /**
128
+ * Handle input change from form elements.
129
+ */
130
+ const handleInputChange = useCallback((e) => {
131
+ setInput(e.target.value);
132
+ }, []);
133
+ /**
134
+ * Stop current streaming request.
135
+ */
136
+ const stop = useCallback(() => {
137
+ if (abortControllerRef.current) {
138
+ abortControllerRef.current.abort();
139
+ abortControllerRef.current = null;
140
+ }
141
+ }, []);
142
+ /**
143
+ * Send request in direct mode using wrapper-ir Chat.
144
+ */
145
+ const sendDirectRequest = useCallback(async (messagesToSend, _requestOptions) => {
146
+ const chat = chatRef.current;
147
+ if (!chat) {
148
+ throw new Error('Chat instance not initialized');
149
+ }
150
+ try {
151
+ setIsLoading(true);
152
+ setError(undefined);
153
+ // Create abort controller
154
+ abortControllerRef.current = new AbortController();
155
+ const { signal } = abortControllerRef.current;
156
+ // Clear chat and restore messages
157
+ chat.clear();
158
+ for (const msg of messagesToSend.slice(0, -1)) {
159
+ chat.addMessage(messageToIR(msg));
160
+ }
161
+ // Get the last user message content
162
+ const lastMessage = messagesToSend[messagesToSend.length - 1];
163
+ if (!lastMessage || lastMessage.role !== 'user') {
164
+ throw new Error('Last message must be a user message');
165
+ }
166
+ // Add placeholder assistant message
167
+ const assistantId = generateId();
168
+ const assistantMessage = {
169
+ id: assistantId,
170
+ role: 'assistant',
171
+ content: '',
172
+ createdAt: new Date(),
173
+ };
174
+ setMessages((prev) => [...prev, assistantMessage]);
175
+ // Stream the response
176
+ const response = await chat.stream(lastMessage.content, {
177
+ signal,
178
+ onChunk: ({ accumulated }) => {
179
+ setMessages((prev) => prev.map((msg) => (msg.id === assistantId ? { ...msg, content: accumulated } : msg)));
180
+ },
181
+ });
182
+ // Finalize message
183
+ const finalMessage = {
184
+ id: assistantId,
185
+ role: 'assistant',
186
+ content: response.content,
187
+ createdAt: new Date(),
188
+ };
189
+ setMessages((prev) => prev.map((msg) => (msg.id === assistantId ? finalMessage : msg)));
190
+ onFinish?.(finalMessage);
191
+ return response.content;
192
+ }
193
+ catch (err) {
194
+ if (err instanceof Error && err.name === 'AbortError') {
195
+ return null;
196
+ }
197
+ const error = err instanceof Error ? err : new Error(String(err));
198
+ setError(error);
199
+ onError?.(error);
200
+ if (!keepLastMessageOnError) {
201
+ setMessages((prev) => prev.slice(0, -1));
202
+ }
203
+ return undefined;
204
+ }
205
+ finally {
206
+ setIsLoading(false);
207
+ abortControllerRef.current = null;
208
+ }
209
+ }, [generateId, onFinish, onError, keepLastMessageOnError]);
210
+ /**
211
+ * Send request in HTTP mode using fetch.
212
+ */
213
+ const sendHttpRequest = useCallback(async (messagesToSend, requestOptions) => {
214
+ try {
215
+ setIsLoading(true);
216
+ setError(undefined);
217
+ // Create abort controller
218
+ abortControllerRef.current = new AbortController();
219
+ const { signal } = abortControllerRef.current;
220
+ // Prepare request body
221
+ const requestBody = {
222
+ messages: sendExtraMessageFields
223
+ ? messagesToSend
224
+ : messagesToSend.map(({ role, content }) => ({ role, content })),
225
+ id: chatId,
226
+ ...body,
227
+ ...requestOptions?.body,
228
+ };
229
+ // Make request
230
+ const response = await fetch(api, {
231
+ method: 'POST',
232
+ headers: {
233
+ 'Content-Type': 'application/json',
234
+ ...headers,
235
+ ...requestOptions?.headers,
236
+ },
237
+ body: JSON.stringify(requestBody),
238
+ signal,
239
+ });
240
+ // Call onResponse callback
241
+ onResponse?.(response);
242
+ if (!response.ok) {
243
+ throw new Error(`HTTP error! status: ${response.status}`);
244
+ }
245
+ if (!response.body) {
246
+ throw new Error('Response body is null');
247
+ }
248
+ // Handle streaming response
249
+ const reader = response.body.getReader();
250
+ const decoder = new TextDecoder();
251
+ let assistantContent = '';
252
+ const assistantId = generateId();
253
+ // Add placeholder message
254
+ const assistantMessage = {
255
+ id: assistantId,
256
+ role: 'assistant',
257
+ content: '',
258
+ createdAt: new Date(),
259
+ };
260
+ setMessages((prev) => [...prev, assistantMessage]);
261
+ // Read stream
262
+ while (true) {
263
+ const { done, value } = await reader.read();
264
+ if (done) {
265
+ break;
266
+ }
267
+ const chunk = decoder.decode(value, { stream: true });
268
+ if (streamProtocol === 'data') {
269
+ // Parse SSE data format
270
+ const lines = chunk.split('\n');
271
+ for (const line of lines) {
272
+ if (line.startsWith('data: ')) {
273
+ const data = line.slice(6);
274
+ if (data === '[DONE]') {
275
+ break;
276
+ }
277
+ try {
278
+ const parsed = JSON.parse(data);
279
+ if (parsed.content) {
280
+ assistantContent += parsed.content;
281
+ }
282
+ else if (parsed.choices?.[0]?.delta?.content) {
283
+ assistantContent += parsed.choices[0].delta.content;
284
+ }
285
+ }
286
+ catch {
287
+ // Ignore parse errors for incomplete JSON
288
+ }
289
+ }
290
+ }
291
+ }
292
+ else {
293
+ // Raw text protocol
294
+ assistantContent += chunk;
295
+ }
296
+ // Update message content
297
+ setMessages((prev) => prev.map((msg) => msg.id === assistantId ? { ...msg, content: assistantContent } : msg));
298
+ }
299
+ // Finalize message
300
+ const finalMessage = {
301
+ id: assistantId,
302
+ role: 'assistant',
303
+ content: assistantContent,
304
+ createdAt: new Date(),
305
+ };
306
+ setMessages((prev) => prev.map((msg) => (msg.id === assistantId ? finalMessage : msg)));
307
+ onFinish?.(finalMessage);
308
+ return assistantContent;
309
+ }
310
+ catch (err) {
311
+ if (err instanceof Error && err.name === 'AbortError') {
312
+ // Request was aborted, not an error
313
+ return null;
314
+ }
315
+ const error = err instanceof Error ? err : new Error(String(err));
316
+ setError(error);
317
+ onError?.(error);
318
+ if (!keepLastMessageOnError) {
319
+ // Remove the last user message on error
320
+ setMessages((prev) => prev.slice(0, -1));
321
+ }
322
+ return undefined;
323
+ }
324
+ finally {
325
+ setIsLoading(false);
326
+ abortControllerRef.current = null;
327
+ }
328
+ }, [
329
+ api,
330
+ body,
331
+ chatId,
332
+ generateId,
333
+ headers,
334
+ keepLastMessageOnError,
335
+ onError,
336
+ onFinish,
337
+ onResponse,
338
+ sendExtraMessageFields,
339
+ streamProtocol,
340
+ ]);
341
+ /**
342
+ * Send request using the appropriate mode.
343
+ */
344
+ const sendRequest = useCallback(async (messagesToSend, requestOptions) => {
345
+ return isDirectMode
346
+ ? sendDirectRequest(messagesToSend, requestOptions)
347
+ : sendHttpRequest(messagesToSend, requestOptions);
348
+ }, [isDirectMode, sendDirectRequest, sendHttpRequest]);
349
+ /**
350
+ * Append a message and send.
351
+ */
352
+ const append = useCallback(async (message, options) => {
353
+ const newMessage = typeof message === 'string'
354
+ ? {
355
+ id: generateId(),
356
+ role: 'user',
357
+ content: message,
358
+ createdAt: new Date(),
359
+ }
360
+ : message;
361
+ const newMessages = [...messages, newMessage];
362
+ setMessages(newMessages);
363
+ return sendRequest(newMessages, options);
364
+ }, [generateId, messages, sendRequest]);
365
+ /**
366
+ * Handle form submission.
367
+ */
368
+ const handleSubmit = useCallback((e, options) => {
369
+ e?.preventDefault();
370
+ if (!input.trim()) {
371
+ return;
372
+ }
373
+ const userMessage = {
374
+ id: generateId(),
375
+ role: 'user',
376
+ content: input,
377
+ createdAt: new Date(),
378
+ };
379
+ const newMessages = [...messages, userMessage];
380
+ setMessages(newMessages);
381
+ setInput('');
382
+ sendRequest(newMessages, options);
383
+ }, [generateId, input, messages, sendRequest]);
384
+ /**
385
+ * Reload the last assistant message.
386
+ */
387
+ const reload = useCallback(async (options) => {
388
+ if (messages.length === 0) {
389
+ return null;
390
+ }
391
+ // Find messages up to the last user message
392
+ const lastUserIndex = messages.findLastIndex((m) => m.role === 'user');
393
+ if (lastUserIndex === -1) {
394
+ return null;
395
+ }
396
+ const messagesToReload = messages.slice(0, lastUserIndex + 1);
397
+ setMessages(messagesToReload);
398
+ return sendRequest(messagesToReload, options);
399
+ }, [messages, sendRequest]);
400
+ return {
401
+ messages,
402
+ input,
403
+ setInput,
404
+ handleInputChange,
405
+ handleSubmit,
406
+ append,
407
+ reload,
408
+ stop,
409
+ setMessages,
410
+ isLoading,
411
+ error,
412
+ data,
413
+ };
414
+ }
415
+ //# sourceMappingURL=use-chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-chat.js","sourceRoot":"","sources":["../../src/use-chat.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAQ,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAIpD;;GAEG;AACH,SAAS,gBAAgB;IACvB,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,OAAgB;IACnC,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,MAAM,UAAU,OAAO,CAAC,UAA0B,EAAE;IAClD,MAAM,EACJ,eAAe,GAAG,EAAE,EACpB,YAAY,GAAG,EAAE,EACjB,EAAE;IACF,oBAAoB;IACpB,GAAG,GAAG,WAAW,EACjB,OAAO,GAAG,EAAE,EACZ,IAAI,GAAG,EAAE,EACT,cAAc,GAAG,MAAM,EACvB,UAAU;IACV,sBAAsB;IACtB,MAAM;IACN,iBAAiB;IACjB,UAAU,GAAG,gBAAgB,EAC7B,QAAQ,EACR,OAAO,EACP,sBAAsB,GAAG,IAAI,EAC7B,iBAAiB,GAAG,CAAC,EACrB,sBAAsB,GAAG,KAAK,GAC/B,GAAG,OAAO,CAAC;IAEZ,iBAAiB;IACjB,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAE9B,8CAA8C;IAC9C,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,EAAE,IAAI,MAAM,CAAC;IAE5B,QAAQ;IACR,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAY,eAAe,CAAC,CAAC;IACrE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAS,YAAY,CAAC,CAAC;IACzD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC3D,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAoB,SAAS,CAAC,CAAC;IACjE,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAwB,SAAS,CAAC,CAAC;IAEpE,OAAO;IACP,MAAM,kBAAkB,GAAG,MAAM,CAAyB,IAAI,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;IAE1C,uCAAuC;IACvC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,YAAY,IAAI,MAAM,EAAE,CAAC;YAC3B,OAAO,CAAC,OAAO,GAAG,UAAU,CAAC;gBAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;gBAC3C,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;gBACzC,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,iBAAiB;aACzD,CAAC,CAAC;QACL,CAAC;QAED,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;QACzB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAE9C;;OAEG;IACH,MAAM,iBAAiB,GAAG,WAAW,CACnC,CAAC,CAA4D,EAAE,EAAE;QAC/D,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC,EACD,EAAE,CACH,CAAC;IAEF;;OAEG;IACH,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,IAAI,kBAAkB,CAAC,OAAO,EAAE,CAAC;YAC/B,kBAAkB,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACnC,kBAAkB,CAAC,OAAO,GAAG,IAAI,CAAC;QACpC,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP;;OAEG;IACH,MAAM,iBAAiB,GAAG,WAAW,CACnC,KAAK,EACH,cAAyB,EACzB,eAAoC,EACA,EAAE;QACtC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,CAAC;YACH,YAAY,CAAC,IAAI,CAAC,CAAC;YACnB,QAAQ,CAAC,SAAS,CAAC,CAAC;YAEpB,0BAA0B;YAC1B,kBAAkB,CAAC,OAAO,GAAG,IAAI,eAAe,EAAE,CAAC;YACnD,MAAM,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC,OAAO,CAAC;YAE9C,kCAAkC;YAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,KAAK,MAAM,GAAG,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9C,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;YACpC,CAAC;YAED,oCAAoC;YACpC,MAAM,WAAW,GAAG,cAAc,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC9D,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAChD,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;YACzD,CAAC;YAED,oCAAoC;YACpC,MAAM,WAAW,GAAG,UAAU,EAAE,CAAC;YACjC,MAAM,gBAAgB,GAAY;gBAChC,EAAE,EAAE,WAAW;gBACf,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,EAAE;gBACX,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB,CAAC;YACF,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC;YAEnD,sBAAsB;YACtB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE;gBACtD,MAAM;gBACN,OAAO,EAAE,CAAC,EAAE,WAAW,EAA4D,EAAE,EAAE;oBACrF,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CACnB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CACrF,CAAC;gBACJ,CAAC;aACF,CAAC,CAAC;YAEH,mBAAmB;YACnB,MAAM,YAAY,GAAY;gBAC5B,EAAE,EAAE,WAAW;gBACf,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB,CAAC;YAEF,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAExF,QAAQ,EAAE,CAAC,YAAY,CAAC,CAAC;YACzB,OAAO,QAAQ,CAAC,OAAO,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACtD,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAClE,QAAQ,CAAC,KAAK,CAAC,CAAC;YAChB,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YAEjB,IAAI,CAAC,sBAAsB,EAAE,CAAC;gBAC5B,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,CAAC;YAED,OAAO,SAAS,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,kBAAkB,CAAC,OAAO,GAAG,IAAI,CAAC;QACpC,CAAC;IACH,CAAC,EACD,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,sBAAsB,CAAC,CACxD,CAAC;IAEF;;OAEG;IACH,MAAM,eAAe,GAAG,WAAW,CACjC,KAAK,EACH,cAAyB,EACzB,cAAmC,EACC,EAAE;QACtC,IAAI,CAAC;YACH,YAAY,CAAC,IAAI,CAAC,CAAC;YACnB,QAAQ,CAAC,SAAS,CAAC,CAAC;YAEpB,0BAA0B;YAC1B,kBAAkB,CAAC,OAAO,GAAG,IAAI,eAAe,EAAE,CAAC;YACnD,MAAM,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC,OAAO,CAAC;YAE9C,uBAAuB;YACvB,MAAM,WAAW,GAAG;gBAClB,QAAQ,EAAE,sBAAsB;oBAC9B,CAAC,CAAC,cAAc;oBAChB,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;gBAClE,EAAE,EAAE,MAAM;gBACV,GAAG,IAAI;gBACP,GAAG,cAAc,EAAE,IAAI;aACxB,CAAC;YAEF,eAAe;YACf,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,GAAG,OAAO;oBACV,GAAG,cAAc,EAAE,OAAO;iBAC3B;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;gBACjC,MAAM;aACP,CAAC,CAAC;YAEH,2BAA2B;YAC3B,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC;YAEvB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAC5D,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAC3C,CAAC;YAED,4BAA4B;YAC5B,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;YAClC,IAAI,gBAAgB,GAAG,EAAE,CAAC;YAC1B,MAAM,WAAW,GAAG,UAAU,EAAE,CAAC;YAEjC,0BAA0B;YAC1B,MAAM,gBAAgB,GAAY;gBAChC,EAAE,EAAE,WAAW;gBACf,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,EAAE;gBACX,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB,CAAC;YAEF,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC;YAEnD,cAAc;YACd,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAE5C,IAAI,IAAI,EAAE,CAAC;oBACT,MAAM;gBACR,CAAC;gBAED,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBAEtD,IAAI,cAAc,KAAK,MAAM,EAAE,CAAC;oBAC9B,wBAAwB;oBACxB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;wBACzB,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;4BAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;4BAC3B,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gCACtB,MAAM;4BACR,CAAC;4BACD,IAAI,CAAC;gCACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gCAChC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oCACnB,gBAAgB,IAAI,MAAM,CAAC,OAAO,CAAC;gCACrC,CAAC;qCAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;oCAC/C,gBAAgB,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;gCACtD,CAAC;4BACH,CAAC;4BAAC,MAAM,CAAC;gCACP,0CAA0C;4BAC5C,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,oBAAoB;oBACpB,gBAAgB,IAAI,KAAK,CAAC;gBAC5B,CAAC;gBAED,yBAAyB;gBACzB,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CACnB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACf,GAAG,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,GAAG,CACrE,CACF,CAAC;YACJ,CAAC;YAED,mBAAmB;YACnB,MAAM,YAAY,GAAY;gBAC5B,EAAE,EAAE,WAAW;gBACf,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,gBAAgB;gBACzB,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB,CAAC;YAEF,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAExF,QAAQ,EAAE,CAAC,YAAY,CAAC,CAAC;YAEzB,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACtD,oCAAoC;gBACpC,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAClE,QAAQ,CAAC,KAAK,CAAC,CAAC;YAChB,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YAEjB,IAAI,CAAC,sBAAsB,EAAE,CAAC;gBAC5B,wCAAwC;gBACxC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,CAAC;YAED,OAAO,SAAS,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,kBAAkB,CAAC,OAAO,GAAG,IAAI,CAAC;QACpC,CAAC;IACH,CAAC,EACD;QACE,GAAG;QACH,IAAI;QACJ,MAAM;QACN,UAAU;QACV,OAAO;QACP,sBAAsB;QACtB,OAAO;QACP,QAAQ;QACR,UAAU;QACV,sBAAsB;QACtB,cAAc;KACf,CACF,CAAC;IAEF;;OAEG;IACH,MAAM,WAAW,GAAG,WAAW,CAC7B,KAAK,EACH,cAAyB,EACzB,cAAmC,EACC,EAAE;QACtC,OAAO,YAAY;YACjB,CAAC,CAAC,iBAAiB,CAAC,cAAc,EAAE,cAAc,CAAC;YACnD,CAAC,CAAC,eAAe,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;IACtD,CAAC,EACD,CAAC,YAAY,EAAE,iBAAiB,EAAE,eAAe,CAAC,CACnD,CAAC;IAEF;;OAEG;IACH,MAAM,MAAM,GAAG,WAAW,CACxB,KAAK,EACH,OAAyB,EACzB,OAA4B,EACQ,EAAE;QACtC,MAAM,UAAU,GACd,OAAO,OAAO,KAAK,QAAQ;YACzB,CAAC,CAAC;gBACE,EAAE,EAAE,UAAU,EAAE;gBAChB,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,OAAO;gBAChB,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB;YACH,CAAC,CAAC,OAAO,CAAC;QAEd,MAAM,WAAW,GAAG,CAAC,GAAG,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC9C,WAAW,CAAC,WAAW,CAAC,CAAC;QAEzB,OAAO,WAAW,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC,EACD,CAAC,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC,CACpC,CAAC;IAEF;;OAEG;IACH,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,CAAoC,EAAE,OAA4B,EAAE,EAAE;QACrE,CAAC,EAAE,cAAc,EAAE,CAAC;QAEpB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAY;YAC3B,EAAE,EAAE,UAAU,EAAE;YAChB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC;QAEF,MAAM,WAAW,GAAG,CAAC,GAAG,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC/C,WAAW,CAAC,WAAW,CAAC,CAAC;QACzB,QAAQ,CAAC,EAAE,CAAC,CAAC;QAEb,WAAW,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC,EACD,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,CAC3C,CAAC;IAEF;;OAEG;IACH,MAAM,MAAM,GAAG,WAAW,CACxB,KAAK,EAAE,OAA4B,EAAsC,EAAE;QACzE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,4CAA4C;QAC5C,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAChF,IAAI,aAAa,KAAK,CAAC,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,gBAAgB,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,GAAG,CAAC,CAAC,CAAC;QAC9D,WAAW,CAAC,gBAAgB,CAAC,CAAC;QAE9B,OAAO,WAAW,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC,EACD,CAAC,QAAQ,EAAE,WAAW,CAAC,CACxB,CAAC;IAEF,OAAO;QACL,QAAQ;QACR,KAAK;QACL,QAAQ;QACR,iBAAiB;QACjB,YAAY;QACZ,MAAM;QACN,MAAM;QACN,IAAI;QACJ,WAAW;QACX,SAAS;QACT,KAAK;QACL,IAAI;KACL,CAAC;AACJ,CAAC"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * useCompletion Hook
3
+ *
4
+ * React hook for text completion interfaces with streaming support.
5
+ *
6
+ * @module
7
+ */
8
+ import { useState, useCallback, useRef, useId } from 'react';
9
+ /**
10
+ * useCompletion - React hook for text completion.
11
+ *
12
+ * Provides state management and streaming for single-turn
13
+ * text completion tasks.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * import { useCompletion } from 'ai.matey.react.core';
18
+ *
19
+ * function CompletionComponent() {
20
+ * const { completion, input, handleInputChange, handleSubmit, isLoading } = useCompletion({
21
+ * api: '/api/completion',
22
+ * });
23
+ *
24
+ * return (
25
+ * <div>
26
+ * <p>{completion}</p>
27
+ * <form onSubmit={handleSubmit}>
28
+ * <input value={input} onChange={handleInputChange} placeholder="Enter a prompt..." />
29
+ * <button type="submit" disabled={isLoading}>Complete</button>
30
+ * </form>
31
+ * </div>
32
+ * );
33
+ * }
34
+ * ```
35
+ */
36
+ export function useCompletion(options = {}) {
37
+ const { initialInput = '', initialCompletion = '', id, api = '/api/completion', headers = {}, body = {}, onFinish, onError, onResponse, streamProtocol = 'data', } = options;
38
+ // Generate a stable ID for this completion instance
39
+ const hookId = useId();
40
+ const completionId = id ?? hookId;
41
+ // State
42
+ const [completion, setCompletion] = useState(initialCompletion);
43
+ const [input, setInput] = useState(initialInput);
44
+ const [isLoading, setIsLoading] = useState(false);
45
+ const [error, setError] = useState(undefined);
46
+ const [data, _setData] = useState(undefined);
47
+ // Refs for abort control
48
+ const abortControllerRef = useRef(null);
49
+ /**
50
+ * Handle input change from form elements.
51
+ */
52
+ const handleInputChange = useCallback((e) => {
53
+ setInput(e.target.value);
54
+ }, []);
55
+ /**
56
+ * Stop current streaming request.
57
+ */
58
+ const stop = useCallback(() => {
59
+ if (abortControllerRef.current) {
60
+ abortControllerRef.current.abort();
61
+ abortControllerRef.current = null;
62
+ }
63
+ }, []);
64
+ /**
65
+ * Send a completion request and handle streaming response.
66
+ */
67
+ const complete = useCallback(async (prompt, requestOptions) => {
68
+ try {
69
+ setIsLoading(true);
70
+ setError(undefined);
71
+ setCompletion('');
72
+ // Create abort controller
73
+ abortControllerRef.current = new AbortController();
74
+ const { signal } = abortControllerRef.current;
75
+ // Prepare request body
76
+ const requestBody = {
77
+ prompt,
78
+ id: completionId,
79
+ ...body,
80
+ ...requestOptions?.body,
81
+ };
82
+ // Make request
83
+ const response = await fetch(api, {
84
+ method: 'POST',
85
+ headers: {
86
+ 'Content-Type': 'application/json',
87
+ ...headers,
88
+ ...requestOptions?.headers,
89
+ },
90
+ body: JSON.stringify(requestBody),
91
+ signal,
92
+ });
93
+ // Call onResponse callback
94
+ onResponse?.(response);
95
+ if (!response.ok) {
96
+ throw new Error(`HTTP error! status: ${response.status}`);
97
+ }
98
+ if (!response.body) {
99
+ throw new Error('Response body is null');
100
+ }
101
+ // Handle streaming response
102
+ const reader = response.body.getReader();
103
+ const decoder = new TextDecoder();
104
+ let completionText = '';
105
+ // Read stream
106
+ while (true) {
107
+ const { done, value } = await reader.read();
108
+ if (done) {
109
+ break;
110
+ }
111
+ const chunk = decoder.decode(value, { stream: true });
112
+ if (streamProtocol === 'data') {
113
+ // Parse SSE data format
114
+ const lines = chunk.split('\n');
115
+ for (const line of lines) {
116
+ if (line.startsWith('data: ')) {
117
+ const data = line.slice(6);
118
+ if (data === '[DONE]') {
119
+ break;
120
+ }
121
+ try {
122
+ const parsed = JSON.parse(data);
123
+ if (parsed.text) {
124
+ completionText += parsed.text;
125
+ }
126
+ else if (parsed.choices?.[0]?.text) {
127
+ completionText += parsed.choices[0].text;
128
+ }
129
+ else if (parsed.choices?.[0]?.delta?.content) {
130
+ completionText += parsed.choices[0].delta.content;
131
+ }
132
+ }
133
+ catch {
134
+ // Ignore parse errors for incomplete JSON
135
+ }
136
+ }
137
+ }
138
+ }
139
+ else {
140
+ // Raw text protocol
141
+ completionText += chunk;
142
+ }
143
+ // Update completion
144
+ setCompletion(completionText);
145
+ }
146
+ onFinish?.(prompt, completionText);
147
+ return completionText;
148
+ }
149
+ catch (err) {
150
+ if (err instanceof Error && err.name === 'AbortError') {
151
+ // Request was aborted, not an error
152
+ return null;
153
+ }
154
+ const error = err instanceof Error ? err : new Error(String(err));
155
+ setError(error);
156
+ onError?.(error);
157
+ return undefined;
158
+ }
159
+ finally {
160
+ setIsLoading(false);
161
+ abortControllerRef.current = null;
162
+ }
163
+ }, [api, body, completionId, headers, onError, onFinish, onResponse, streamProtocol]);
164
+ /**
165
+ * Handle form submission.
166
+ */
167
+ const handleSubmit = useCallback((e) => {
168
+ e?.preventDefault();
169
+ if (!input.trim()) {
170
+ return;
171
+ }
172
+ const prompt = input;
173
+ setInput('');
174
+ complete(prompt);
175
+ }, [complete, input]);
176
+ return {
177
+ completion,
178
+ input,
179
+ setInput,
180
+ handleInputChange,
181
+ handleSubmit,
182
+ complete,
183
+ stop,
184
+ setCompletion,
185
+ isLoading,
186
+ error,
187
+ data,
188
+ };
189
+ }
190
+ //# sourceMappingURL=use-completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-completion.js","sourceRoot":"","sources":["../../src/use-completion.ts"],"names":[],"mappings":"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"}