ai.matey.react.stream 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 +28 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/stream-context.js +193 -0
- package/dist/cjs/stream-context.js.map +1 -0
- package/dist/cjs/stream-text.js +104 -0
- package/dist/cjs/stream-text.js.map +1 -0
- package/dist/cjs/stream-utils.js +236 -0
- package/dist/cjs/stream-utils.js.map +1 -0
- package/dist/esm/index.js +14 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/stream-context.js +188 -0
- package/dist/esm/stream-context.js.map +1 -0
- package/dist/esm/stream-text.js +100 -0
- package/dist/esm/stream-text.js.map +1 -0
- package/dist/esm/stream-utils.js +228 -0
- package/dist/esm/stream-utils.js.map +1 -0
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/stream-context.d.ts +104 -0
- package/dist/types/stream-context.d.ts.map +1 -0
- package/dist/types/stream-text.d.ts +89 -0
- package/dist/types/stream-text.d.ts.map +1 -0
- package/dist/types/stream-utils.d.ts +81 -0
- package/dist/types/stream-utils.d.ts.map +1 -0
- package/package.json +77 -0
- package/readme.md +192 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Stream Context and Provider
|
|
4
|
+
*
|
|
5
|
+
* React context for sharing streaming state across components.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { createContext, useContext, useCallback, useState, useRef } from 'react';
|
|
10
|
+
/**
|
|
11
|
+
* Stream context.
|
|
12
|
+
*/
|
|
13
|
+
const StreamContext = createContext(null);
|
|
14
|
+
/**
|
|
15
|
+
* StreamProvider - Context provider for managing multiple streams.
|
|
16
|
+
*
|
|
17
|
+
* Provides centralized stream state management across components.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* import { StreamProvider, useStreamContext } from 'ai.matey.react.stream';
|
|
22
|
+
*
|
|
23
|
+
* function App() {
|
|
24
|
+
* return (
|
|
25
|
+
* <StreamProvider maxStreams={10}>
|
|
26
|
+
* <ChatComponent />
|
|
27
|
+
* </StreamProvider>
|
|
28
|
+
* );
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* function ChatComponent() {
|
|
32
|
+
* const { startStream, appendToStream, completeStream } = useStreamContext();
|
|
33
|
+
*
|
|
34
|
+
* const handleNewMessage = async () => {
|
|
35
|
+
* const streamId = 'message-1';
|
|
36
|
+
* startStream(streamId);
|
|
37
|
+
* // ... fetch and stream
|
|
38
|
+
* for await (const chunk of response) {
|
|
39
|
+
* appendToStream(streamId, chunk);
|
|
40
|
+
* }
|
|
41
|
+
* completeStream(streamId);
|
|
42
|
+
* };
|
|
43
|
+
*
|
|
44
|
+
* return <button onClick={handleNewMessage}>Send</button>;
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export function StreamProvider({ children, maxStreams = 100 }) {
|
|
49
|
+
const [streams, setStreams] = useState(new Map());
|
|
50
|
+
const streamsRef = useRef(streams);
|
|
51
|
+
// Keep ref in sync
|
|
52
|
+
streamsRef.current = streams;
|
|
53
|
+
/**
|
|
54
|
+
* Get a specific stream.
|
|
55
|
+
*/
|
|
56
|
+
const getStream = useCallback((id) => {
|
|
57
|
+
return streamsRef.current.get(id);
|
|
58
|
+
}, []);
|
|
59
|
+
/**
|
|
60
|
+
* Start a new stream.
|
|
61
|
+
*/
|
|
62
|
+
const startStream = useCallback((id, metadata) => {
|
|
63
|
+
setStreams((prev) => {
|
|
64
|
+
const newMap = new Map(prev);
|
|
65
|
+
// Enforce max streams limit
|
|
66
|
+
if (newMap.size >= maxStreams && !newMap.has(id)) {
|
|
67
|
+
// Remove oldest completed stream
|
|
68
|
+
for (const [streamId, state] of newMap) {
|
|
69
|
+
if (!state.isStreaming) {
|
|
70
|
+
newMap.delete(streamId);
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
newMap.set(id, {
|
|
76
|
+
id,
|
|
77
|
+
text: '',
|
|
78
|
+
isStreaming: true,
|
|
79
|
+
error: undefined,
|
|
80
|
+
metadata,
|
|
81
|
+
});
|
|
82
|
+
return newMap;
|
|
83
|
+
});
|
|
84
|
+
}, [maxStreams]);
|
|
85
|
+
/**
|
|
86
|
+
* Update stream text (replace).
|
|
87
|
+
*/
|
|
88
|
+
const updateStream = useCallback((id, text) => {
|
|
89
|
+
setStreams((prev) => {
|
|
90
|
+
const state = prev.get(id);
|
|
91
|
+
if (!state)
|
|
92
|
+
return prev;
|
|
93
|
+
const newMap = new Map(prev);
|
|
94
|
+
newMap.set(id, { ...state, text });
|
|
95
|
+
return newMap;
|
|
96
|
+
});
|
|
97
|
+
}, []);
|
|
98
|
+
/**
|
|
99
|
+
* Append to stream text.
|
|
100
|
+
*/
|
|
101
|
+
const appendToStream = useCallback((id, chunk) => {
|
|
102
|
+
setStreams((prev) => {
|
|
103
|
+
const state = prev.get(id);
|
|
104
|
+
if (!state)
|
|
105
|
+
return prev;
|
|
106
|
+
const newMap = new Map(prev);
|
|
107
|
+
newMap.set(id, { ...state, text: state.text + chunk });
|
|
108
|
+
return newMap;
|
|
109
|
+
});
|
|
110
|
+
}, []);
|
|
111
|
+
/**
|
|
112
|
+
* Complete a stream.
|
|
113
|
+
*/
|
|
114
|
+
const completeStream = useCallback((id) => {
|
|
115
|
+
setStreams((prev) => {
|
|
116
|
+
const state = prev.get(id);
|
|
117
|
+
if (!state)
|
|
118
|
+
return prev;
|
|
119
|
+
const newMap = new Map(prev);
|
|
120
|
+
newMap.set(id, { ...state, isStreaming: false });
|
|
121
|
+
return newMap;
|
|
122
|
+
});
|
|
123
|
+
}, []);
|
|
124
|
+
/**
|
|
125
|
+
* Set stream error.
|
|
126
|
+
*/
|
|
127
|
+
const setStreamError = useCallback((id, error) => {
|
|
128
|
+
setStreams((prev) => {
|
|
129
|
+
const state = prev.get(id);
|
|
130
|
+
if (!state)
|
|
131
|
+
return prev;
|
|
132
|
+
const newMap = new Map(prev);
|
|
133
|
+
newMap.set(id, { ...state, isStreaming: false, error });
|
|
134
|
+
return newMap;
|
|
135
|
+
});
|
|
136
|
+
}, []);
|
|
137
|
+
/**
|
|
138
|
+
* Remove a stream.
|
|
139
|
+
*/
|
|
140
|
+
const removeStream = useCallback((id) => {
|
|
141
|
+
setStreams((prev) => {
|
|
142
|
+
const newMap = new Map(prev);
|
|
143
|
+
newMap.delete(id);
|
|
144
|
+
return newMap;
|
|
145
|
+
});
|
|
146
|
+
}, []);
|
|
147
|
+
/**
|
|
148
|
+
* Clear all streams.
|
|
149
|
+
*/
|
|
150
|
+
const clearAllStreams = useCallback(() => {
|
|
151
|
+
setStreams(new Map());
|
|
152
|
+
}, []);
|
|
153
|
+
const value = {
|
|
154
|
+
streams,
|
|
155
|
+
getStream,
|
|
156
|
+
startStream,
|
|
157
|
+
updateStream,
|
|
158
|
+
appendToStream,
|
|
159
|
+
completeStream,
|
|
160
|
+
setStreamError,
|
|
161
|
+
removeStream,
|
|
162
|
+
clearAllStreams,
|
|
163
|
+
};
|
|
164
|
+
return _jsx(StreamContext.Provider, { value: value, children: children });
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* useStreamContext - Access the stream context.
|
|
168
|
+
*
|
|
169
|
+
* @throws {Error} If used outside of StreamProvider
|
|
170
|
+
*/
|
|
171
|
+
export function useStreamContext() {
|
|
172
|
+
const context = useContext(StreamContext);
|
|
173
|
+
if (!context) {
|
|
174
|
+
throw new Error('useStreamContext must be used within a StreamProvider');
|
|
175
|
+
}
|
|
176
|
+
return context;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* useStreamState - Get state for a specific stream.
|
|
180
|
+
*
|
|
181
|
+
* @param id - Stream ID
|
|
182
|
+
* @returns Stream state or undefined
|
|
183
|
+
*/
|
|
184
|
+
export function useStreamState(id) {
|
|
185
|
+
const { streams } = useStreamContext();
|
|
186
|
+
return streams.get(id);
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=stream-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-context.js","sourceRoot":"","sources":["../../src/stream-context.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* StreamText Component
|
|
4
|
+
*
|
|
5
|
+
* React component for rendering streaming text with typing effect.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { useEffect, useState, useMemo } from 'react';
|
|
10
|
+
/**
|
|
11
|
+
* StreamText - Display streaming text with optional cursor.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* import { StreamText } from 'ai.matey.react.stream';
|
|
16
|
+
*
|
|
17
|
+
* function ChatMessage({ text, isStreaming }) {
|
|
18
|
+
* return (
|
|
19
|
+
* <StreamText
|
|
20
|
+
* text={text}
|
|
21
|
+
* isStreaming={isStreaming}
|
|
22
|
+
* showCursor={true}
|
|
23
|
+
* />
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function StreamText({ text, isStreaming = false, showCursor = true, cursor = '▋', cursorBlinkInterval = 500, className, renderText, children, }) {
|
|
29
|
+
const [cursorVisible, setCursorVisible] = useState(true);
|
|
30
|
+
// Blink cursor while streaming
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!isStreaming || !showCursor) {
|
|
33
|
+
setCursorVisible(false);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
setCursorVisible(true);
|
|
37
|
+
const interval = setInterval(() => {
|
|
38
|
+
setCursorVisible((prev) => !prev);
|
|
39
|
+
}, cursorBlinkInterval);
|
|
40
|
+
return () => clearInterval(interval);
|
|
41
|
+
}, [isStreaming, showCursor, cursorBlinkInterval]);
|
|
42
|
+
// Render text content
|
|
43
|
+
const textContent = useMemo(() => {
|
|
44
|
+
if (renderText) {
|
|
45
|
+
return renderText(text);
|
|
46
|
+
}
|
|
47
|
+
return text;
|
|
48
|
+
}, [text, renderText]);
|
|
49
|
+
return (_jsxs("span", { className: className, children: [textContent, isStreaming && showCursor && cursorVisible && (_jsx("span", { className: "streaming-cursor", "aria-hidden": "true", children: cursor })), children] }));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* TypeWriter - Display text with typewriter effect.
|
|
53
|
+
*
|
|
54
|
+
* Simulates typing effect for non-streaming text.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```tsx
|
|
58
|
+
* import { TypeWriter } from 'ai.matey.react.stream';
|
|
59
|
+
*
|
|
60
|
+
* function WelcomeMessage() {
|
|
61
|
+
* return (
|
|
62
|
+
* <TypeWriter
|
|
63
|
+
* text="Welcome to AI Matey!"
|
|
64
|
+
* speed={50}
|
|
65
|
+
* onComplete={() => console.log('Done typing')}
|
|
66
|
+
* />
|
|
67
|
+
* );
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export function TypeWriter({ text, speed = 30, delay = 0, onComplete, className, showCursor = true, cursor = '▋', }) {
|
|
72
|
+
const [displayedText, setDisplayedText] = useState('');
|
|
73
|
+
const [isTyping, setIsTyping] = useState(false);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
setDisplayedText('');
|
|
76
|
+
setIsTyping(false);
|
|
77
|
+
if (!text)
|
|
78
|
+
return;
|
|
79
|
+
// Start delay
|
|
80
|
+
const delayTimeout = setTimeout(() => {
|
|
81
|
+
setIsTyping(true);
|
|
82
|
+
let currentIndex = 0;
|
|
83
|
+
const typeInterval = setInterval(() => {
|
|
84
|
+
if (currentIndex < text.length) {
|
|
85
|
+
setDisplayedText(text.slice(0, currentIndex + 1));
|
|
86
|
+
currentIndex++;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
clearInterval(typeInterval);
|
|
90
|
+
setIsTyping(false);
|
|
91
|
+
onComplete?.();
|
|
92
|
+
}
|
|
93
|
+
}, speed);
|
|
94
|
+
return () => clearInterval(typeInterval);
|
|
95
|
+
}, delay);
|
|
96
|
+
return () => clearTimeout(delayTimeout);
|
|
97
|
+
}, [text, speed, delay, onComplete]);
|
|
98
|
+
return (_jsx(StreamText, { text: displayedText, isStreaming: isTyping, showCursor: showCursor, cursor: cursor, className: className }));
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=stream-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-text.js","sourceRoot":"","sources":["../../src/stream-text.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream Utilities
|
|
3
|
+
*
|
|
4
|
+
* Helper functions for working with streams in React.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Create a controlled text stream from a fetch response.
|
|
10
|
+
*
|
|
11
|
+
* @param response - Fetch response with streaming body
|
|
12
|
+
* @param options - Stream options
|
|
13
|
+
* @returns Promise resolving to full text
|
|
14
|
+
*/
|
|
15
|
+
export async function createTextStream(response, options = {}) {
|
|
16
|
+
const { onChunk, onComplete, onError, signal } = options;
|
|
17
|
+
if (!response.body) {
|
|
18
|
+
throw new Error('Response body is null');
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const reader = response.body.getReader();
|
|
22
|
+
const decoder = new TextDecoder();
|
|
23
|
+
let fullText = '';
|
|
24
|
+
while (true) {
|
|
25
|
+
if (signal?.aborted) {
|
|
26
|
+
reader.cancel();
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
const { done, value } = await reader.read();
|
|
30
|
+
if (done) {
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
34
|
+
fullText += chunk;
|
|
35
|
+
onChunk?.(chunk);
|
|
36
|
+
}
|
|
37
|
+
onComplete?.(fullText);
|
|
38
|
+
return fullText;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
42
|
+
onError?.(err);
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Parse Server-Sent Events (SSE) stream.
|
|
48
|
+
*
|
|
49
|
+
* @param response - Fetch response with SSE body
|
|
50
|
+
* @param options - Stream options
|
|
51
|
+
* @returns Async generator yielding parsed events
|
|
52
|
+
*/
|
|
53
|
+
export async function* parseSSEStream(response, options = {}) {
|
|
54
|
+
const { signal } = options;
|
|
55
|
+
if (!response.body) {
|
|
56
|
+
throw new Error('Response body is null');
|
|
57
|
+
}
|
|
58
|
+
const reader = response.body.getReader();
|
|
59
|
+
const decoder = new TextDecoder();
|
|
60
|
+
let buffer = '';
|
|
61
|
+
try {
|
|
62
|
+
while (true) {
|
|
63
|
+
if (signal?.aborted) {
|
|
64
|
+
reader.cancel();
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
const { done, value } = await reader.read();
|
|
68
|
+
if (done) {
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
buffer += decoder.decode(value, { stream: true });
|
|
72
|
+
// Split by double newlines (SSE event delimiter)
|
|
73
|
+
const events = buffer.split('\n\n');
|
|
74
|
+
buffer = events.pop() || '';
|
|
75
|
+
for (const eventText of events) {
|
|
76
|
+
const event = parseSSEEvent(eventText);
|
|
77
|
+
if (event) {
|
|
78
|
+
yield event;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Process any remaining buffer
|
|
83
|
+
if (buffer.trim()) {
|
|
84
|
+
const event = parseSSEEvent(buffer);
|
|
85
|
+
if (event) {
|
|
86
|
+
yield event;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
reader.releaseLock();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Parse a single SSE event.
|
|
96
|
+
*/
|
|
97
|
+
function parseSSEEvent(text) {
|
|
98
|
+
const lines = text.split('\n');
|
|
99
|
+
const event = { data: '' };
|
|
100
|
+
const dataLines = [];
|
|
101
|
+
for (const line of lines) {
|
|
102
|
+
if (line.startsWith('event:')) {
|
|
103
|
+
event.event = line.slice(6).trim();
|
|
104
|
+
}
|
|
105
|
+
else if (line.startsWith('data:')) {
|
|
106
|
+
dataLines.push(line.slice(5).trim());
|
|
107
|
+
}
|
|
108
|
+
else if (line.startsWith('id:')) {
|
|
109
|
+
event.id = line.slice(3).trim();
|
|
110
|
+
}
|
|
111
|
+
else if (line.startsWith('retry:')) {
|
|
112
|
+
const retry = parseInt(line.slice(6).trim(), 10);
|
|
113
|
+
if (!isNaN(retry)) {
|
|
114
|
+
event.retry = retry;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (dataLines.length === 0) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
event.data = dataLines.join('\n');
|
|
122
|
+
return event;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Transform a ReadableStream with a function.
|
|
126
|
+
*
|
|
127
|
+
* @param stream - Source stream
|
|
128
|
+
* @param transform - Transform function
|
|
129
|
+
* @returns Transformed stream
|
|
130
|
+
*/
|
|
131
|
+
export function transformStream(stream, transform) {
|
|
132
|
+
const reader = stream.getReader();
|
|
133
|
+
return new ReadableStream({
|
|
134
|
+
async pull(controller) {
|
|
135
|
+
const { done, value } = await reader.read();
|
|
136
|
+
if (done) {
|
|
137
|
+
controller.close();
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const transformed = await transform(value);
|
|
141
|
+
controller.enqueue(transformed);
|
|
142
|
+
},
|
|
143
|
+
cancel() {
|
|
144
|
+
reader.cancel();
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Merge multiple streams into one.
|
|
150
|
+
*
|
|
151
|
+
* @param streams - Streams to merge
|
|
152
|
+
* @returns Merged stream
|
|
153
|
+
*/
|
|
154
|
+
export function mergeStreams(...streams) {
|
|
155
|
+
const readers = streams.map((s) => s.getReader());
|
|
156
|
+
let activeReaders = readers.length;
|
|
157
|
+
return new ReadableStream({
|
|
158
|
+
async pull(controller) {
|
|
159
|
+
const results = await Promise.all(readers.map(async (reader, index) => {
|
|
160
|
+
try {
|
|
161
|
+
const { done, value } = await reader.read();
|
|
162
|
+
return { index, done, value };
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
return { index, done: true, value: undefined, error };
|
|
166
|
+
}
|
|
167
|
+
}));
|
|
168
|
+
for (const result of results) {
|
|
169
|
+
if (result.done) {
|
|
170
|
+
activeReaders--;
|
|
171
|
+
}
|
|
172
|
+
else if (result.value !== undefined) {
|
|
173
|
+
controller.enqueue(result.value);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (activeReaders === 0) {
|
|
177
|
+
controller.close();
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
cancel() {
|
|
181
|
+
readers.forEach((reader) => reader.cancel());
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Create a stream from an async iterable.
|
|
187
|
+
*
|
|
188
|
+
* @param iterable - Async iterable source
|
|
189
|
+
* @returns ReadableStream
|
|
190
|
+
*/
|
|
191
|
+
export function fromAsyncIterable(iterable) {
|
|
192
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
193
|
+
return new ReadableStream({
|
|
194
|
+
async pull(controller) {
|
|
195
|
+
const { done, value } = await iterator.next();
|
|
196
|
+
if (done) {
|
|
197
|
+
controller.close();
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
controller.enqueue(value);
|
|
201
|
+
},
|
|
202
|
+
cancel() {
|
|
203
|
+
iterator.return?.();
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Convert a ReadableStream to an async iterable.
|
|
209
|
+
*
|
|
210
|
+
* @param stream - ReadableStream source
|
|
211
|
+
* @returns Async iterable
|
|
212
|
+
*/
|
|
213
|
+
export async function* toAsyncIterable(stream) {
|
|
214
|
+
const reader = stream.getReader();
|
|
215
|
+
try {
|
|
216
|
+
while (true) {
|
|
217
|
+
const { done, value } = await reader.read();
|
|
218
|
+
if (done) {
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
yield value;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
reader.releaseLock();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=stream-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-utils.js","sourceRoot":"","sources":["../../src/stream-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Matey React Stream
|
|
3
|
+
*
|
|
4
|
+
* React streaming utilities and components.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
export { StreamProvider, useStreamContext, useStreamState } from './stream-context.js';
|
|
9
|
+
export { StreamText, TypeWriter } from './stream-text.js';
|
|
10
|
+
export { createTextStream, parseSSEStream, transformStream, mergeStreams, fromAsyncIterable, toAsyncIterable, } from './stream-utils.js';
|
|
11
|
+
export type { StreamState, StreamContextValue, StreamProviderProps } from './stream-context.js';
|
|
12
|
+
export type { StreamTextProps, TypeWriterProps } from './stream-text.js';
|
|
13
|
+
export type { CreateTextStreamOptions, SSEEvent } from './stream-utils.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGvF,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG1D,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAEhG,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEzE,YAAY,EAAE,uBAAuB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream Context and Provider
|
|
3
|
+
*
|
|
4
|
+
* React context for sharing streaming state across components.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { type ReactNode } from 'react';
|
|
9
|
+
/**
|
|
10
|
+
* Stream state for a single stream.
|
|
11
|
+
*/
|
|
12
|
+
export interface StreamState {
|
|
13
|
+
/** Stream ID */
|
|
14
|
+
id: string;
|
|
15
|
+
/** Current text content */
|
|
16
|
+
text: string;
|
|
17
|
+
/** Whether streaming is active */
|
|
18
|
+
isStreaming: boolean;
|
|
19
|
+
/** Error if any */
|
|
20
|
+
error: Error | undefined;
|
|
21
|
+
/** Metadata */
|
|
22
|
+
metadata?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Stream context value.
|
|
26
|
+
*/
|
|
27
|
+
export interface StreamContextValue {
|
|
28
|
+
/** All active streams */
|
|
29
|
+
streams: Map<string, StreamState>;
|
|
30
|
+
/** Get a specific stream */
|
|
31
|
+
getStream: (id: string) => StreamState | undefined;
|
|
32
|
+
/** Start a new stream */
|
|
33
|
+
startStream: (id: string, metadata?: Record<string, unknown>) => void;
|
|
34
|
+
/** Update stream text */
|
|
35
|
+
updateStream: (id: string, text: string) => void;
|
|
36
|
+
/** Append to stream text */
|
|
37
|
+
appendToStream: (id: string, chunk: string) => void;
|
|
38
|
+
/** Complete a stream */
|
|
39
|
+
completeStream: (id: string) => void;
|
|
40
|
+
/** Set stream error */
|
|
41
|
+
setStreamError: (id: string, error: Error) => void;
|
|
42
|
+
/** Remove a stream */
|
|
43
|
+
removeStream: (id: string) => void;
|
|
44
|
+
/** Clear all streams */
|
|
45
|
+
clearAllStreams: () => void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Stream provider props.
|
|
49
|
+
*/
|
|
50
|
+
export interface StreamProviderProps {
|
|
51
|
+
/** Children to render */
|
|
52
|
+
children: ReactNode;
|
|
53
|
+
/** Maximum number of streams to keep */
|
|
54
|
+
maxStreams?: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* StreamProvider - Context provider for managing multiple streams.
|
|
58
|
+
*
|
|
59
|
+
* Provides centralized stream state management across components.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* import { StreamProvider, useStreamContext } from 'ai.matey.react.stream';
|
|
64
|
+
*
|
|
65
|
+
* function App() {
|
|
66
|
+
* return (
|
|
67
|
+
* <StreamProvider maxStreams={10}>
|
|
68
|
+
* <ChatComponent />
|
|
69
|
+
* </StreamProvider>
|
|
70
|
+
* );
|
|
71
|
+
* }
|
|
72
|
+
*
|
|
73
|
+
* function ChatComponent() {
|
|
74
|
+
* const { startStream, appendToStream, completeStream } = useStreamContext();
|
|
75
|
+
*
|
|
76
|
+
* const handleNewMessage = async () => {
|
|
77
|
+
* const streamId = 'message-1';
|
|
78
|
+
* startStream(streamId);
|
|
79
|
+
* // ... fetch and stream
|
|
80
|
+
* for await (const chunk of response) {
|
|
81
|
+
* appendToStream(streamId, chunk);
|
|
82
|
+
* }
|
|
83
|
+
* completeStream(streamId);
|
|
84
|
+
* };
|
|
85
|
+
*
|
|
86
|
+
* return <button onClick={handleNewMessage}>Send</button>;
|
|
87
|
+
* }
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export declare function StreamProvider({ children, maxStreams }: StreamProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
91
|
+
/**
|
|
92
|
+
* useStreamContext - Access the stream context.
|
|
93
|
+
*
|
|
94
|
+
* @throws {Error} If used outside of StreamProvider
|
|
95
|
+
*/
|
|
96
|
+
export declare function useStreamContext(): StreamContextValue;
|
|
97
|
+
/**
|
|
98
|
+
* useStreamState - Get state for a specific stream.
|
|
99
|
+
*
|
|
100
|
+
* @param id - Stream ID
|
|
101
|
+
* @returns Stream state or undefined
|
|
102
|
+
*/
|
|
103
|
+
export declare function useStreamState(id: string): StreamState | undefined;
|
|
104
|
+
//# sourceMappingURL=stream-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-context.d.ts","sourceRoot":"","sources":["../../src/stream-context.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAA4D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjG;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gBAAgB;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,mBAAmB;IACnB,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IACzB,eAAe;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,yBAAyB;IACzB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,4BAA4B;IAC5B,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;IACnD,yBAAyB;IACzB,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,yBAAyB;IACzB,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,4BAA4B;IAC5B,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,wBAAwB;IACxB,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,uBAAuB;IACvB,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACnD,sBAAsB;IACtB,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,wBAAwB;IACxB,eAAe,EAAE,MAAM,IAAI,CAAC;CAC7B;AAOD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,yBAAyB;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,UAAgB,EAAE,EAAE,mBAAmB,2CAsIjF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,kBAAkB,CAQrD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAGlE"}
|