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.
@@ -0,0 +1,89 @@
1
+ /**
2
+ * StreamText Component
3
+ *
4
+ * React component for rendering streaming text with typing effect.
5
+ *
6
+ * @module
7
+ */
8
+ import { type ReactNode } from 'react';
9
+ /**
10
+ * StreamText props.
11
+ */
12
+ export interface StreamTextProps {
13
+ /** Text to display */
14
+ text: string;
15
+ /** Whether streaming is active */
16
+ isStreaming?: boolean;
17
+ /** Show cursor while streaming */
18
+ showCursor?: boolean;
19
+ /** Cursor character */
20
+ cursor?: string;
21
+ /** Cursor blink interval in ms */
22
+ cursorBlinkInterval?: number;
23
+ /** Custom className */
24
+ className?: string;
25
+ /** Custom render function */
26
+ renderText?: (text: string) => ReactNode;
27
+ /** Children to render after text */
28
+ children?: ReactNode;
29
+ }
30
+ /**
31
+ * StreamText - Display streaming text with optional cursor.
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * import { StreamText } from 'ai.matey.react.stream';
36
+ *
37
+ * function ChatMessage({ text, isStreaming }) {
38
+ * return (
39
+ * <StreamText
40
+ * text={text}
41
+ * isStreaming={isStreaming}
42
+ * showCursor={true}
43
+ * />
44
+ * );
45
+ * }
46
+ * ```
47
+ */
48
+ export declare function StreamText({ text, isStreaming, showCursor, cursor, cursorBlinkInterval, className, renderText, children, }: StreamTextProps): import("react/jsx-runtime").JSX.Element;
49
+ /**
50
+ * TypeWriter props.
51
+ */
52
+ export interface TypeWriterProps {
53
+ /** Text to type */
54
+ text: string;
55
+ /** Typing speed in ms per character */
56
+ speed?: number;
57
+ /** Delay before starting in ms */
58
+ delay?: number;
59
+ /** Called when typing completes */
60
+ onComplete?: () => void;
61
+ /** Custom className */
62
+ className?: string;
63
+ /** Show cursor */
64
+ showCursor?: boolean;
65
+ /** Cursor character */
66
+ cursor?: string;
67
+ }
68
+ /**
69
+ * TypeWriter - Display text with typewriter effect.
70
+ *
71
+ * Simulates typing effect for non-streaming text.
72
+ *
73
+ * @example
74
+ * ```tsx
75
+ * import { TypeWriter } from 'ai.matey.react.stream';
76
+ *
77
+ * function WelcomeMessage() {
78
+ * return (
79
+ * <TypeWriter
80
+ * text="Welcome to AI Matey!"
81
+ * speed={50}
82
+ * onComplete={() => console.log('Done typing')}
83
+ * />
84
+ * );
85
+ * }
86
+ * ```
87
+ */
88
+ export declare function TypeWriter({ text, speed, delay, onComplete, className, showCursor, cursor, }: TypeWriterProps): import("react/jsx-runtime").JSX.Element;
89
+ //# sourceMappingURL=stream-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-text.d.ts","sourceRoot":"","sources":["../../src/stream-text.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kCAAkC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,CAAC;IACzC,oCAAoC;IACpC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,WAAmB,EACnB,UAAiB,EACjB,MAAY,EACZ,mBAAyB,EACzB,SAAS,EACT,UAAU,EACV,QAAQ,GACT,EAAE,eAAe,2CAsCjB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,KAAU,EACV,KAAS,EACT,UAAU,EACV,SAAS,EACT,UAAiB,EACjB,MAAY,GACb,EAAE,eAAe,2CAyCjB"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Stream Utilities
3
+ *
4
+ * Helper functions for working with streams in React.
5
+ *
6
+ * @module
7
+ */
8
+ /**
9
+ * Options for creating a text stream.
10
+ */
11
+ export interface CreateTextStreamOptions {
12
+ /** Called for each chunk */
13
+ onChunk?: (chunk: string) => void;
14
+ /** Called when stream completes */
15
+ onComplete?: (fullText: string) => void;
16
+ /** Called on error */
17
+ onError?: (error: Error) => void;
18
+ /** Abort signal */
19
+ signal?: AbortSignal;
20
+ }
21
+ /**
22
+ * Create a controlled text stream from a fetch response.
23
+ *
24
+ * @param response - Fetch response with streaming body
25
+ * @param options - Stream options
26
+ * @returns Promise resolving to full text
27
+ */
28
+ export declare function createTextStream(response: Response, options?: CreateTextStreamOptions): Promise<string>;
29
+ /**
30
+ * Parse Server-Sent Events (SSE) stream.
31
+ *
32
+ * @param response - Fetch response with SSE body
33
+ * @param options - Stream options
34
+ * @returns Async generator yielding parsed events
35
+ */
36
+ export declare function parseSSEStream(response: Response, options?: {
37
+ signal?: AbortSignal;
38
+ }): AsyncGenerator<SSEEvent, void, unknown>;
39
+ /**
40
+ * SSE Event structure.
41
+ */
42
+ export interface SSEEvent {
43
+ /** Event type */
44
+ event?: string;
45
+ /** Event data */
46
+ data: string;
47
+ /** Event ID */
48
+ id?: string;
49
+ /** Retry interval */
50
+ retry?: number;
51
+ }
52
+ /**
53
+ * Transform a ReadableStream with a function.
54
+ *
55
+ * @param stream - Source stream
56
+ * @param transform - Transform function
57
+ * @returns Transformed stream
58
+ */
59
+ export declare function transformStream<T, U>(stream: ReadableStream<T>, transform: (chunk: T) => U | Promise<U>): ReadableStream<U>;
60
+ /**
61
+ * Merge multiple streams into one.
62
+ *
63
+ * @param streams - Streams to merge
64
+ * @returns Merged stream
65
+ */
66
+ export declare function mergeStreams<T>(...streams: ReadableStream<T>[]): ReadableStream<T>;
67
+ /**
68
+ * Create a stream from an async iterable.
69
+ *
70
+ * @param iterable - Async iterable source
71
+ * @returns ReadableStream
72
+ */
73
+ export declare function fromAsyncIterable<T>(iterable: AsyncIterable<T>): ReadableStream<T>;
74
+ /**
75
+ * Convert a ReadableStream to an async iterable.
76
+ *
77
+ * @param stream - ReadableStream source
78
+ * @returns Async iterable
79
+ */
80
+ export declare function toAsyncIterable<T>(stream: ReadableStream<T>): AsyncGenerator<T, void, unknown>;
81
+ //# sourceMappingURL=stream-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-utils.d.ts","sourceRoot":"","sources":["../../src/stream-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,4BAA4B;IAC5B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,mCAAmC;IACnC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,sBAAsB;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,mBAAmB;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,MAAM,CAAC,CAoCjB;AAED;;;;;;GAMG;AACH,wBAAuB,cAAc,CACnC,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAO,GACrC,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAgDzC;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAiCD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAClC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,EACzB,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACtC,cAAc,CAAC,CAAC,CAAC,CAmBnB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,CAiClF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAkBlF;AAED;;;;;GAKG;AACH,wBAAuB,eAAe,CAAC,CAAC,EACtC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GACxB,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAgBlC"}
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "ai.matey.react.stream",
3
+ "version": "0.2.0",
4
+ "description": "React streaming utilities for AI Matey - StreamProvider, StreamContext",
5
+ "type": "module",
6
+ "main": "./dist/cjs/index.js",
7
+ "module": "./dist/esm/index.js",
8
+ "types": "./dist/types/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/types/index.d.ts",
13
+ "default": "./dist/esm/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/types/index.d.ts",
17
+ "default": "./dist/cjs/index.js"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "readme.md",
24
+ "CHANGELOG.md",
25
+ "LICENSE"
26
+ ],
27
+ "scripts": {
28
+ "build": "npm run build:esm && npm run build:cjs && npm run build:types",
29
+ "build:esm": "tsc -p tsconfig.esm.json",
30
+ "build:cjs": "tsc -p tsconfig.cjs.json",
31
+ "build:types": "tsc -p tsconfig.types.json",
32
+ "clean": "rm -rf dist",
33
+ "typecheck": "tsc --noEmit",
34
+ "test": "vitest run"
35
+ },
36
+ "dependencies": {
37
+ "ai.matey.types": "*",
38
+ "ai.matey.react.core": "*"
39
+ },
40
+ "peerDependencies": {
41
+ "react": ">=18.0.0"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "react": {
45
+ "optional": false
46
+ }
47
+ },
48
+ "devDependencies": {
49
+ "@types/react": "^18.2.0",
50
+ "react": "^18.2.0",
51
+ "typescript": "^5.9.3",
52
+ "vitest": "^3.2.4"
53
+ },
54
+ "keywords": [
55
+ "ai",
56
+ "llm",
57
+ "react",
58
+ "streaming",
59
+ "context",
60
+ "provider",
61
+ "ai-matey"
62
+ ],
63
+ "author": "AI Matey",
64
+ "license": "MIT",
65
+ "homepage": "https://github.com/johnhenry/ai.matey#readme",
66
+ "bugs": {
67
+ "url": "https://github.com/johnhenry/ai.matey/issues"
68
+ },
69
+ "repository": {
70
+ "type": "git",
71
+ "url": "git+https://github.com/johnhenry/ai.matey.git",
72
+ "directory": "packages/react-stream"
73
+ },
74
+ "engines": {
75
+ "node": ">=18.0.0"
76
+ }
77
+ }
package/readme.md ADDED
@@ -0,0 +1,192 @@
1
+ # ai.matey.react.stream
2
+
3
+ React components and utilities for streaming AI responses.
4
+
5
+ Part of the [ai.matey](https://github.com/johnhenry/ai.matey) monorepo.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install ai.matey.react.stream
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```tsx
16
+ import { StreamProvider, useStreamContext, StreamText } from 'ai.matey.react.stream';
17
+
18
+ // Wrap your app with StreamProvider
19
+ function App() {
20
+ return (
21
+ <StreamProvider maxStreams={10}>
22
+ <ChatComponent />
23
+ </StreamProvider>
24
+ );
25
+ }
26
+
27
+ // Use streaming in components
28
+ function ChatComponent() {
29
+ const { startStream, appendToStream, completeStream, getStream } = useStreamContext();
30
+ const [streamId, setStreamId] = useState<string | null>(null);
31
+
32
+ const handleSend = async () => {
33
+ const id = `msg-${Date.now()}`;
34
+ setStreamId(id);
35
+ startStream(id);
36
+
37
+ const response = await fetch('/api/chat', { method: 'POST' });
38
+ const reader = response.body?.getReader();
39
+ const decoder = new TextDecoder();
40
+
41
+ while (reader) {
42
+ const { done, value } = await reader.read();
43
+ if (done) break;
44
+ appendToStream(id, decoder.decode(value));
45
+ }
46
+
47
+ completeStream(id);
48
+ };
49
+
50
+ const stream = streamId ? getStream(streamId) : null;
51
+
52
+ return (
53
+ <div>
54
+ {stream && (
55
+ <StreamText
56
+ text={stream.text}
57
+ isStreaming={stream.isStreaming}
58
+ showCursor={true}
59
+ />
60
+ )}
61
+ <button onClick={handleSend}>Send</button>
62
+ </div>
63
+ );
64
+ }
65
+ ```
66
+
67
+ ## Exports
68
+
69
+ ### Components
70
+
71
+ - `StreamProvider` - Context provider for stream state management
72
+ - `StreamText` - Display streaming text with cursor
73
+ - `TypeWriter` - Typewriter effect for static text
74
+
75
+ ### Hooks
76
+
77
+ - `useStreamContext` - Access stream management functions
78
+ - `useStreamState` - Get state for a specific stream
79
+
80
+ ### Utilities
81
+
82
+ - `createTextStream` - Create controlled text stream from fetch response
83
+ - `parseSSEStream` - Parse Server-Sent Events
84
+ - `transformStream` - Transform stream data
85
+ - `mergeStreams` - Merge multiple streams
86
+ - `fromAsyncIterable` - Convert async iterable to stream
87
+ - `toAsyncIterable` - Convert stream to async iterable
88
+
89
+ ### Types
90
+
91
+ - `StreamState`, `StreamContextValue`, `StreamProviderProps`
92
+ - `StreamTextProps`, `TypeWriterProps`
93
+ - `CreateTextStreamOptions`, `SSEEvent`
94
+
95
+ ## API Reference
96
+
97
+ ### StreamProvider
98
+
99
+ Context provider for managing multiple concurrent streams.
100
+
101
+ ```tsx
102
+ <StreamProvider maxStreams={100}>
103
+ {children}
104
+ </StreamProvider>
105
+ ```
106
+
107
+ **Props:**
108
+ - `maxStreams` - Maximum streams to keep (default: 100, oldest completed removed when exceeded)
109
+
110
+ ### useStreamContext
111
+
112
+ Access stream management functions.
113
+
114
+ ```tsx
115
+ const {
116
+ streams, // Map<string, StreamState> - All streams
117
+ getStream, // (id: string) => StreamState | undefined
118
+ startStream, // (id: string, metadata?: object) => void
119
+ updateStream, // (id: string, text: string) => void - Replace text
120
+ appendToStream, // (id: string, chunk: string) => void - Append text
121
+ completeStream, // (id: string) => void - Mark complete
122
+ setStreamError, // (id: string, error: Error) => void
123
+ removeStream, // (id: string) => void
124
+ clearAllStreams, // () => void
125
+ } = useStreamContext();
126
+ ```
127
+
128
+ ### useStreamState
129
+
130
+ Get state for a specific stream by ID.
131
+
132
+ ```tsx
133
+ const stream = useStreamState('message-1');
134
+ // stream: { id, text, isStreaming, error, metadata } | undefined
135
+ ```
136
+
137
+ ### StreamText
138
+
139
+ Display streaming text with optional blinking cursor.
140
+
141
+ ```tsx
142
+ <StreamText
143
+ text="Hello world"
144
+ isStreaming={true}
145
+ showCursor={true} // Show cursor while streaming
146
+ cursor="▋" // Cursor character
147
+ cursorBlinkInterval={500} // Blink speed in ms
148
+ className="my-class"
149
+ renderText={(text) => <Markdown>{text}</Markdown>}
150
+ />
151
+ ```
152
+
153
+ ### TypeWriter
154
+
155
+ Simulate typing effect for non-streaming text.
156
+
157
+ ```tsx
158
+ <TypeWriter
159
+ text="Welcome to AI Matey!"
160
+ speed={30} // ms per character
161
+ delay={500} // ms before starting
162
+ showCursor={true}
163
+ cursor="▋"
164
+ onComplete={() => console.log('Done!')}
165
+ />
166
+ ```
167
+
168
+ ### Stream Utilities
169
+
170
+ ```tsx
171
+ import {
172
+ createTextStream,
173
+ parseSSEStream,
174
+ fromAsyncIterable,
175
+ } from 'ai.matey.react.stream';
176
+
177
+ // Create text stream from fetch response
178
+ const text = await createTextStream(response, {
179
+ onChunk: (chunk) => console.log(chunk),
180
+ onComplete: (fullText) => console.log('Done:', fullText),
181
+ signal: abortController.signal,
182
+ });
183
+
184
+ // Parse SSE events
185
+ for await (const event of parseSSEStream(response)) {
186
+ console.log(event.data); // { type: 'data' | 'event', data: string }
187
+ }
188
+ ```
189
+
190
+ ## License
191
+
192
+ MIT - see [LICENSE](./LICENSE) for details.