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.
- package/LICENSE +21 -0
- package/dist/cjs/index.js +18 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/types.js +10 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/use-chat.js +418 -0
- package/dist/cjs/use-chat.js.map +1 -0
- package/dist/cjs/use-completion.js +193 -0
- package/dist/cjs/use-completion.js.map +1 -0
- package/dist/cjs/use-object.js +250 -0
- package/dist/cjs/use-object.js.map +1 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/types.js +9 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/use-chat.js +415 -0
- package/dist/esm/use-chat.js.map +1 -0
- package/dist/esm/use-completion.js +190 -0
- package/dist/esm/use-completion.js.map +1 -0
- package/dist/esm/use-object.js +247 -0
- package/dist/esm/use-object.js.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/types.d.ts +295 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/use-chat.d.ts +73 -0
- package/dist/types/use-chat.d.ts.map +1 -0
- package/dist/types/use-completion.d.ts +37 -0
- package/dist/types/use-completion.d.ts.map +1 -0
- package/dist/types/use-object.d.ts +47 -0
- package/dist/types/use-object.d.ts.map +1 -0
- package/package.json +78 -0
- package/readme.md +232 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* useCompletion Hook
|
|
4
|
+
*
|
|
5
|
+
* React hook for text completion interfaces with streaming support.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.useCompletion = useCompletion;
|
|
11
|
+
const react_1 = require("react");
|
|
12
|
+
/**
|
|
13
|
+
* useCompletion - React hook for text completion.
|
|
14
|
+
*
|
|
15
|
+
* Provides state management and streaming for single-turn
|
|
16
|
+
* text completion tasks.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* import { useCompletion } from 'ai.matey.react.core';
|
|
21
|
+
*
|
|
22
|
+
* function CompletionComponent() {
|
|
23
|
+
* const { completion, input, handleInputChange, handleSubmit, isLoading } = useCompletion({
|
|
24
|
+
* api: '/api/completion',
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* return (
|
|
28
|
+
* <div>
|
|
29
|
+
* <p>{completion}</p>
|
|
30
|
+
* <form onSubmit={handleSubmit}>
|
|
31
|
+
* <input value={input} onChange={handleInputChange} placeholder="Enter a prompt..." />
|
|
32
|
+
* <button type="submit" disabled={isLoading}>Complete</button>
|
|
33
|
+
* </form>
|
|
34
|
+
* </div>
|
|
35
|
+
* );
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
function useCompletion(options = {}) {
|
|
40
|
+
const { initialInput = '', initialCompletion = '', id, api = '/api/completion', headers = {}, body = {}, onFinish, onError, onResponse, streamProtocol = 'data', } = options;
|
|
41
|
+
// Generate a stable ID for this completion instance
|
|
42
|
+
const hookId = (0, react_1.useId)();
|
|
43
|
+
const completionId = id ?? hookId;
|
|
44
|
+
// State
|
|
45
|
+
const [completion, setCompletion] = (0, react_1.useState)(initialCompletion);
|
|
46
|
+
const [input, setInput] = (0, react_1.useState)(initialInput);
|
|
47
|
+
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
48
|
+
const [error, setError] = (0, react_1.useState)(undefined);
|
|
49
|
+
const [data, _setData] = (0, react_1.useState)(undefined);
|
|
50
|
+
// Refs for abort control
|
|
51
|
+
const abortControllerRef = (0, react_1.useRef)(null);
|
|
52
|
+
/**
|
|
53
|
+
* Handle input change from form elements.
|
|
54
|
+
*/
|
|
55
|
+
const handleInputChange = (0, react_1.useCallback)((e) => {
|
|
56
|
+
setInput(e.target.value);
|
|
57
|
+
}, []);
|
|
58
|
+
/**
|
|
59
|
+
* Stop current streaming request.
|
|
60
|
+
*/
|
|
61
|
+
const stop = (0, react_1.useCallback)(() => {
|
|
62
|
+
if (abortControllerRef.current) {
|
|
63
|
+
abortControllerRef.current.abort();
|
|
64
|
+
abortControllerRef.current = null;
|
|
65
|
+
}
|
|
66
|
+
}, []);
|
|
67
|
+
/**
|
|
68
|
+
* Send a completion request and handle streaming response.
|
|
69
|
+
*/
|
|
70
|
+
const complete = (0, react_1.useCallback)(async (prompt, requestOptions) => {
|
|
71
|
+
try {
|
|
72
|
+
setIsLoading(true);
|
|
73
|
+
setError(undefined);
|
|
74
|
+
setCompletion('');
|
|
75
|
+
// Create abort controller
|
|
76
|
+
abortControllerRef.current = new AbortController();
|
|
77
|
+
const { signal } = abortControllerRef.current;
|
|
78
|
+
// Prepare request body
|
|
79
|
+
const requestBody = {
|
|
80
|
+
prompt,
|
|
81
|
+
id: completionId,
|
|
82
|
+
...body,
|
|
83
|
+
...requestOptions?.body,
|
|
84
|
+
};
|
|
85
|
+
// Make request
|
|
86
|
+
const response = await fetch(api, {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
headers: {
|
|
89
|
+
'Content-Type': 'application/json',
|
|
90
|
+
...headers,
|
|
91
|
+
...requestOptions?.headers,
|
|
92
|
+
},
|
|
93
|
+
body: JSON.stringify(requestBody),
|
|
94
|
+
signal,
|
|
95
|
+
});
|
|
96
|
+
// Call onResponse callback
|
|
97
|
+
onResponse?.(response);
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
100
|
+
}
|
|
101
|
+
if (!response.body) {
|
|
102
|
+
throw new Error('Response body is null');
|
|
103
|
+
}
|
|
104
|
+
// Handle streaming response
|
|
105
|
+
const reader = response.body.getReader();
|
|
106
|
+
const decoder = new TextDecoder();
|
|
107
|
+
let completionText = '';
|
|
108
|
+
// Read stream
|
|
109
|
+
while (true) {
|
|
110
|
+
const { done, value } = await reader.read();
|
|
111
|
+
if (done) {
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
115
|
+
if (streamProtocol === 'data') {
|
|
116
|
+
// Parse SSE data format
|
|
117
|
+
const lines = chunk.split('\n');
|
|
118
|
+
for (const line of lines) {
|
|
119
|
+
if (line.startsWith('data: ')) {
|
|
120
|
+
const data = line.slice(6);
|
|
121
|
+
if (data === '[DONE]') {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const parsed = JSON.parse(data);
|
|
126
|
+
if (parsed.text) {
|
|
127
|
+
completionText += parsed.text;
|
|
128
|
+
}
|
|
129
|
+
else if (parsed.choices?.[0]?.text) {
|
|
130
|
+
completionText += parsed.choices[0].text;
|
|
131
|
+
}
|
|
132
|
+
else if (parsed.choices?.[0]?.delta?.content) {
|
|
133
|
+
completionText += parsed.choices[0].delta.content;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// Ignore parse errors for incomplete JSON
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
// Raw text protocol
|
|
144
|
+
completionText += chunk;
|
|
145
|
+
}
|
|
146
|
+
// Update completion
|
|
147
|
+
setCompletion(completionText);
|
|
148
|
+
}
|
|
149
|
+
onFinish?.(prompt, completionText);
|
|
150
|
+
return completionText;
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
154
|
+
// Request was aborted, not an error
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
158
|
+
setError(error);
|
|
159
|
+
onError?.(error);
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
setIsLoading(false);
|
|
164
|
+
abortControllerRef.current = null;
|
|
165
|
+
}
|
|
166
|
+
}, [api, body, completionId, headers, onError, onFinish, onResponse, streamProtocol]);
|
|
167
|
+
/**
|
|
168
|
+
* Handle form submission.
|
|
169
|
+
*/
|
|
170
|
+
const handleSubmit = (0, react_1.useCallback)((e) => {
|
|
171
|
+
e?.preventDefault();
|
|
172
|
+
if (!input.trim()) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const prompt = input;
|
|
176
|
+
setInput('');
|
|
177
|
+
complete(prompt);
|
|
178
|
+
}, [complete, input]);
|
|
179
|
+
return {
|
|
180
|
+
completion,
|
|
181
|
+
input,
|
|
182
|
+
setInput,
|
|
183
|
+
handleInputChange,
|
|
184
|
+
handleSubmit,
|
|
185
|
+
complete,
|
|
186
|
+
stop,
|
|
187
|
+
setCompletion,
|
|
188
|
+
isLoading,
|
|
189
|
+
error,
|
|
190
|
+
data,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
//# 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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"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* useObject Hook
|
|
4
|
+
*
|
|
5
|
+
* React hook for streaming structured objects with streaming support.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.useObject = useObject;
|
|
11
|
+
const react_1 = require("react");
|
|
12
|
+
/**
|
|
13
|
+
* useObject - React hook for streaming structured objects.
|
|
14
|
+
*
|
|
15
|
+
* Provides state management for streaming JSON objects with
|
|
16
|
+
* partial updates as data arrives.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* import { useObject } from 'ai.matey.react.core';
|
|
21
|
+
*
|
|
22
|
+
* interface Recipe {
|
|
23
|
+
* name: string;
|
|
24
|
+
* ingredients: string[];
|
|
25
|
+
* instructions: string[];
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* function RecipeGenerator() {
|
|
29
|
+
* const { object, submit, isLoading } = useObject<Recipe>({
|
|
30
|
+
* api: '/api/generate-recipe',
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* return (
|
|
34
|
+
* <div>
|
|
35
|
+
* <button onClick={() => submit('Generate a pasta recipe')} disabled={isLoading}>
|
|
36
|
+
* Generate Recipe
|
|
37
|
+
* </button>
|
|
38
|
+
* {object && (
|
|
39
|
+
* <div>
|
|
40
|
+
* <h2>{object.name}</h2>
|
|
41
|
+
* <ul>{object.ingredients?.map((i, idx) => <li key={idx}>{i}</li>)}</ul>
|
|
42
|
+
* </div>
|
|
43
|
+
* )}
|
|
44
|
+
* </div>
|
|
45
|
+
* );
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
function useObject(options = {}) {
|
|
50
|
+
const { api = '/api/object', schema, initialValue, headers = {}, body = {}, onFinish, onError, } = options;
|
|
51
|
+
// State
|
|
52
|
+
const [object, setObject] = (0, react_1.useState)(initialValue);
|
|
53
|
+
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
54
|
+
const [error, setError] = (0, react_1.useState)(undefined);
|
|
55
|
+
// Refs for abort control
|
|
56
|
+
const abortControllerRef = (0, react_1.useRef)(null);
|
|
57
|
+
/**
|
|
58
|
+
* Stop current streaming request.
|
|
59
|
+
*/
|
|
60
|
+
const stop = (0, react_1.useCallback)(() => {
|
|
61
|
+
if (abortControllerRef.current) {
|
|
62
|
+
abortControllerRef.current.abort();
|
|
63
|
+
abortControllerRef.current = null;
|
|
64
|
+
}
|
|
65
|
+
}, []);
|
|
66
|
+
/**
|
|
67
|
+
* Submit a prompt to generate an object.
|
|
68
|
+
*/
|
|
69
|
+
const submit = (0, react_1.useCallback)(async (prompt) => {
|
|
70
|
+
try {
|
|
71
|
+
setIsLoading(true);
|
|
72
|
+
setError(undefined);
|
|
73
|
+
setObject(undefined);
|
|
74
|
+
// Create abort controller
|
|
75
|
+
abortControllerRef.current = new AbortController();
|
|
76
|
+
const { signal } = abortControllerRef.current;
|
|
77
|
+
// Prepare request body
|
|
78
|
+
const requestBody = {
|
|
79
|
+
prompt,
|
|
80
|
+
schema,
|
|
81
|
+
...body,
|
|
82
|
+
};
|
|
83
|
+
// Make request
|
|
84
|
+
const response = await fetch(api, {
|
|
85
|
+
method: 'POST',
|
|
86
|
+
headers: {
|
|
87
|
+
'Content-Type': 'application/json',
|
|
88
|
+
...headers,
|
|
89
|
+
},
|
|
90
|
+
body: JSON.stringify(requestBody),
|
|
91
|
+
signal,
|
|
92
|
+
});
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
95
|
+
}
|
|
96
|
+
if (!response.body) {
|
|
97
|
+
throw new Error('Response body is null');
|
|
98
|
+
}
|
|
99
|
+
// Handle streaming response
|
|
100
|
+
const reader = response.body.getReader();
|
|
101
|
+
const decoder = new TextDecoder();
|
|
102
|
+
let jsonBuffer = '';
|
|
103
|
+
// Read stream
|
|
104
|
+
while (true) {
|
|
105
|
+
const { done, value } = await reader.read();
|
|
106
|
+
if (done) {
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
110
|
+
// Parse SSE data format
|
|
111
|
+
const lines = chunk.split('\n');
|
|
112
|
+
for (const line of lines) {
|
|
113
|
+
if (line.startsWith('data: ')) {
|
|
114
|
+
const data = line.slice(6);
|
|
115
|
+
if (data === '[DONE]') {
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
const parsed = JSON.parse(data);
|
|
120
|
+
if (parsed.object) {
|
|
121
|
+
// Direct object update
|
|
122
|
+
setObject(parsed.object);
|
|
123
|
+
}
|
|
124
|
+
else if (parsed.partial) {
|
|
125
|
+
// Partial JSON string
|
|
126
|
+
jsonBuffer = parsed.partial;
|
|
127
|
+
try {
|
|
128
|
+
const partialObject = JSON.parse(jsonBuffer);
|
|
129
|
+
setObject(partialObject);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// Incomplete JSON, try to parse what we can
|
|
133
|
+
const repaired = tryRepairJson(jsonBuffer);
|
|
134
|
+
if (repaired) {
|
|
135
|
+
setObject(repaired);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else if (parsed.delta) {
|
|
140
|
+
// Delta update - append to buffer
|
|
141
|
+
jsonBuffer += parsed.delta;
|
|
142
|
+
try {
|
|
143
|
+
const partialObject = JSON.parse(jsonBuffer);
|
|
144
|
+
setObject(partialObject);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// Incomplete JSON
|
|
148
|
+
const repaired = tryRepairJson(jsonBuffer);
|
|
149
|
+
if (repaired) {
|
|
150
|
+
setObject(repaired);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// Ignore parse errors
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Try to parse final object
|
|
162
|
+
let finalObject;
|
|
163
|
+
if (jsonBuffer) {
|
|
164
|
+
try {
|
|
165
|
+
finalObject = JSON.parse(jsonBuffer);
|
|
166
|
+
setObject(finalObject);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// Keep partial object
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
onFinish?.({ object: finalObject, error: undefined });
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
176
|
+
// Request was aborted
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
180
|
+
setError(error);
|
|
181
|
+
onError?.(error);
|
|
182
|
+
onFinish?.({ object: undefined, error });
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
setIsLoading(false);
|
|
186
|
+
abortControllerRef.current = null;
|
|
187
|
+
}
|
|
188
|
+
}, [api, body, headers, onError, onFinish, schema]);
|
|
189
|
+
return {
|
|
190
|
+
object,
|
|
191
|
+
submit,
|
|
192
|
+
stop,
|
|
193
|
+
isLoading,
|
|
194
|
+
error,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Try to repair incomplete JSON by closing open brackets.
|
|
199
|
+
*/
|
|
200
|
+
function tryRepairJson(json) {
|
|
201
|
+
if (!json.trim()) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
// Count open brackets
|
|
205
|
+
let openBraces = 0;
|
|
206
|
+
let openBrackets = 0;
|
|
207
|
+
let inString = false;
|
|
208
|
+
let escape = false;
|
|
209
|
+
for (const char of json) {
|
|
210
|
+
if (escape) {
|
|
211
|
+
escape = false;
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (char === '\\') {
|
|
215
|
+
escape = true;
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (char === '"') {
|
|
219
|
+
inString = !inString;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (inString) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (char === '{')
|
|
226
|
+
openBraces++;
|
|
227
|
+
if (char === '}')
|
|
228
|
+
openBraces--;
|
|
229
|
+
if (char === '[')
|
|
230
|
+
openBrackets++;
|
|
231
|
+
if (char === ']')
|
|
232
|
+
openBrackets--;
|
|
233
|
+
}
|
|
234
|
+
// Try to close the JSON
|
|
235
|
+
let repaired = json;
|
|
236
|
+
// If we're in a string, close it
|
|
237
|
+
if (inString) {
|
|
238
|
+
repaired += '"';
|
|
239
|
+
}
|
|
240
|
+
// Close brackets and braces
|
|
241
|
+
repaired += ']'.repeat(Math.max(0, openBrackets));
|
|
242
|
+
repaired += '}'.repeat(Math.max(0, openBraces));
|
|
243
|
+
try {
|
|
244
|
+
return JSON.parse(repaired);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=use-object.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-object.js","sourceRoot":"","sources":["../../src/use-object.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Matey React Core
|
|
3
|
+
*
|
|
4
|
+
* Core React hooks for building AI-powered applications.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
// Hooks
|
|
9
|
+
export { useChat } from './use-chat.js';
|
|
10
|
+
export { useCompletion } from './use-completion.js';
|
|
11
|
+
export { useObject } from './use-object.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,QAAQ;AACR,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|