ai.matey.react.hooks 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 +20 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/use-assistant.js +180 -0
- package/dist/cjs/use-assistant.js.map +1 -0
- package/dist/cjs/use-stream.js +173 -0
- package/dist/cjs/use-stream.js.map +1 -0
- package/dist/cjs/use-token-count.js +135 -0
- package/dist/cjs/use-token-count.js.map +1 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/use-assistant.js +177 -0
- package/dist/esm/use-assistant.js.map +1 -0
- package/dist/esm/use-stream.js +170 -0
- package/dist/esm/use-stream.js.map +1 -0
- package/dist/esm/use-token-count.js +130 -0
- package/dist/esm/use-token-count.js.map +1 -0
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/use-assistant.d.ts +123 -0
- package/dist/types/use-assistant.d.ts.map +1 -0
- package/dist/types/use-stream.d.ts +75 -0
- package/dist/types/use-stream.d.ts.map +1 -0
- package/dist/types/use-token-count.d.ts +68 -0
- package/dist/types/use-token-count.d.ts.map +1 -0
- package/package.json +77 -0
- package/readme.md +143 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useStream Hook
|
|
3
|
+
*
|
|
4
|
+
* React hook for generic text streaming with state management.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Stream hook options.
|
|
10
|
+
*/
|
|
11
|
+
export interface UseStreamOptions {
|
|
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
|
+
/** Initial text value */
|
|
19
|
+
initialText?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Stream hook return value.
|
|
23
|
+
*/
|
|
24
|
+
export interface UseStreamReturn {
|
|
25
|
+
/** Current streamed text */
|
|
26
|
+
text: string;
|
|
27
|
+
/** Whether streaming is active */
|
|
28
|
+
isStreaming: boolean;
|
|
29
|
+
/** Error if any */
|
|
30
|
+
error: Error | undefined;
|
|
31
|
+
/** Start streaming from a response */
|
|
32
|
+
startStream: (response: Response) => Promise<string>;
|
|
33
|
+
/** Start streaming from a ReadableStream */
|
|
34
|
+
startReadableStream: (stream: ReadableStream<Uint8Array>) => Promise<string>;
|
|
35
|
+
/** Start streaming from an async iterable */
|
|
36
|
+
startAsyncIterable: (iterable: AsyncIterable<string>) => Promise<string>;
|
|
37
|
+
/** Stop streaming */
|
|
38
|
+
stop: () => void;
|
|
39
|
+
/** Reset state */
|
|
40
|
+
reset: () => void;
|
|
41
|
+
/** Manually set text */
|
|
42
|
+
setText: (text: string) => void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* useStream - React hook for generic text streaming.
|
|
46
|
+
*
|
|
47
|
+
* Provides state management for streaming text from various sources
|
|
48
|
+
* including fetch responses, ReadableStreams, and async iterables.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* import { useStream } from 'ai.matey.react.hooks';
|
|
53
|
+
*
|
|
54
|
+
* function StreamingComponent() {
|
|
55
|
+
* const { text, isStreaming, startStream, stop } = useStream({
|
|
56
|
+
* onComplete: (fullText) => console.log('Completed:', fullText),
|
|
57
|
+
* });
|
|
58
|
+
*
|
|
59
|
+
* const handleClick = async () => {
|
|
60
|
+
* const response = await fetch('/api/stream');
|
|
61
|
+
* await startStream(response);
|
|
62
|
+
* };
|
|
63
|
+
*
|
|
64
|
+
* return (
|
|
65
|
+
* <div>
|
|
66
|
+
* <button onClick={handleClick} disabled={isStreaming}>Start</button>
|
|
67
|
+
* <button onClick={stop} disabled={!isStreaming}>Stop</button>
|
|
68
|
+
* <pre>{text}</pre>
|
|
69
|
+
* </div>
|
|
70
|
+
* );
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare function useStream(options?: UseStreamOptions): UseStreamReturn;
|
|
75
|
+
//# sourceMappingURL=use-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-stream.d.ts","sourceRoot":"","sources":["../../src/use-stream.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,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,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,mBAAmB;IACnB,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IACzB,sCAAsC;IACtC,WAAW,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,4CAA4C;IAC5C,mBAAmB,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7E,6CAA6C;IAC7C,kBAAkB,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACzE,qBAAqB;IACrB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,kBAAkB;IAClB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,wBAAwB;IACxB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,eAAe,CA0JzE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useTokenCount Hook
|
|
3
|
+
*
|
|
4
|
+
* React hook for estimating token counts.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Token count options.
|
|
10
|
+
*/
|
|
11
|
+
export interface UseTokenCountOptions {
|
|
12
|
+
/** Text to count tokens for */
|
|
13
|
+
text?: string;
|
|
14
|
+
/** Model to use for estimation */
|
|
15
|
+
model?: string;
|
|
16
|
+
/** Custom tokenizer function */
|
|
17
|
+
tokenizer?: (text: string) => number;
|
|
18
|
+
/** Debounce delay in ms */
|
|
19
|
+
debounceMs?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Token count return value.
|
|
23
|
+
*/
|
|
24
|
+
export interface UseTokenCountReturn {
|
|
25
|
+
/** Estimated token count */
|
|
26
|
+
tokenCount: number;
|
|
27
|
+
/** Characters count */
|
|
28
|
+
characterCount: number;
|
|
29
|
+
/** Word count */
|
|
30
|
+
wordCount: number;
|
|
31
|
+
/** Whether estimation is in progress */
|
|
32
|
+
isEstimating: boolean;
|
|
33
|
+
/** Count tokens for text */
|
|
34
|
+
countTokens: (text: string) => number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* useTokenCount - React hook for estimating token counts.
|
|
38
|
+
*
|
|
39
|
+
* Provides real-time token estimation for text input,
|
|
40
|
+
* useful for staying within model context limits.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* import { useTokenCount } from 'ai.matey.react.hooks';
|
|
45
|
+
*
|
|
46
|
+
* function TokenCounter() {
|
|
47
|
+
* const [text, setText] = useState('');
|
|
48
|
+
* const { tokenCount, characterCount, wordCount } = useTokenCount({ text });
|
|
49
|
+
*
|
|
50
|
+
* return (
|
|
51
|
+
* <div>
|
|
52
|
+
* <textarea value={text} onChange={(e) => setText(e.target.value)} />
|
|
53
|
+
* <p>Tokens: ~{tokenCount} | Words: {wordCount} | Characters: {characterCount}</p>
|
|
54
|
+
* </div>
|
|
55
|
+
* );
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function useTokenCount(options?: UseTokenCountOptions): UseTokenCountReturn;
|
|
60
|
+
/**
|
|
61
|
+
* Model-specific token limits.
|
|
62
|
+
*/
|
|
63
|
+
export declare const MODEL_TOKEN_LIMITS: Record<string, number>;
|
|
64
|
+
/**
|
|
65
|
+
* Get token limit for a model.
|
|
66
|
+
*/
|
|
67
|
+
export declare function getModelTokenLimit(model: string): number | undefined;
|
|
68
|
+
//# sourceMappingURL=use-token-count.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-token-count.d.ts","sourceRoot":"","sources":["../../src/use-token-count.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,YAAY,EAAE,OAAO,CAAC;IACtB,4BAA4B;IAC5B,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC;AA4BD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,CAuDrF;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAgBrD,CAAC;AAEF;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAcpE"}
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ai.matey.react.hooks",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Additional React hooks for AI Matey - useAssistant, useStream, useTokenCount",
|
|
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
|
+
"hooks",
|
|
59
|
+
"useAssistant",
|
|
60
|
+
"useStream",
|
|
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-hooks"
|
|
73
|
+
},
|
|
74
|
+
"engines": {
|
|
75
|
+
"node": ">=18.0.0"
|
|
76
|
+
}
|
|
77
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# ai.matey.react.hooks
|
|
2
|
+
|
|
3
|
+
Additional specialized React hooks for AI applications.
|
|
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.hooks
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { useAssistant } from 'ai.matey.react.hooks';
|
|
17
|
+
|
|
18
|
+
function AssistantChat() {
|
|
19
|
+
const { messages, input, handleInputChange, handleSubmit, status } = useAssistant({
|
|
20
|
+
api: '/api/assistant',
|
|
21
|
+
assistantId: 'asst_xxx',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div>
|
|
26
|
+
{messages.map((m) => (
|
|
27
|
+
<div key={m.id}>
|
|
28
|
+
<strong>{m.role}:</strong> {m.content}
|
|
29
|
+
</div>
|
|
30
|
+
))}
|
|
31
|
+
<form onSubmit={handleSubmit}>
|
|
32
|
+
<input value={input} onChange={handleInputChange} />
|
|
33
|
+
<button type="submit" disabled={status === 'in_progress'}>
|
|
34
|
+
Send
|
|
35
|
+
</button>
|
|
36
|
+
</form>
|
|
37
|
+
<p>Status: {status}</p>
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Exports
|
|
44
|
+
|
|
45
|
+
### Hooks
|
|
46
|
+
|
|
47
|
+
- `useAssistant` - OpenAI Assistants API integration with thread management
|
|
48
|
+
- `useTokenCount` - Token counting and context window tracking
|
|
49
|
+
- `useStream` - Low-level stream consumption hook
|
|
50
|
+
|
|
51
|
+
### Types
|
|
52
|
+
|
|
53
|
+
- `AssistantMessage`, `Annotation`, `AssistantStatus` - Assistant types
|
|
54
|
+
- `UseAssistantOptions`, `UseAssistantReturn` - useAssistant types
|
|
55
|
+
- `UseTokenCountOptions`, `UseTokenCountReturn` - useTokenCount types
|
|
56
|
+
- `UseStreamOptions`, `UseStreamReturn` - useStream types
|
|
57
|
+
|
|
58
|
+
## API Reference
|
|
59
|
+
|
|
60
|
+
### useAssistant
|
|
61
|
+
|
|
62
|
+
React hook for OpenAI Assistants API with thread and run management.
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
const {
|
|
66
|
+
messages, // AssistantMessage[] - Chat history with annotations
|
|
67
|
+
input, // string - Current input
|
|
68
|
+
setInput, // (value: string) => void
|
|
69
|
+
handleInputChange, // (e: ChangeEvent) => void
|
|
70
|
+
handleSubmit, // (e?: FormEvent) => void
|
|
71
|
+
append, // (message: string | Message) => Promise<void>
|
|
72
|
+
threadId, // string | undefined - Current thread ID
|
|
73
|
+
status, // AssistantStatus - Run status
|
|
74
|
+
stop, // () => void - Cancel current run
|
|
75
|
+
setMessages, // (messages: AssistantMessage[]) => void
|
|
76
|
+
error, // Error | undefined
|
|
77
|
+
} = useAssistant({
|
|
78
|
+
api: '/api/assistant', // API endpoint
|
|
79
|
+
assistantId: 'asst_xxx', // OpenAI Assistant ID
|
|
80
|
+
threadId: 'thread_xxx', // Existing thread to continue
|
|
81
|
+
headers: {}, // Request headers
|
|
82
|
+
body: {}, // Extra request body
|
|
83
|
+
onStatus: (status) => {}, // Called on status change
|
|
84
|
+
onError: (error) => {}, // Called on error
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**AssistantStatus values:**
|
|
89
|
+
- `awaiting_message` - Ready for input
|
|
90
|
+
- `in_progress` - Processing request
|
|
91
|
+
- `requires_action` - Tool call pending
|
|
92
|
+
- `completed` - Run finished
|
|
93
|
+
- `failed` - Run failed
|
|
94
|
+
- `cancelled` - Run cancelled
|
|
95
|
+
- `expired` - Run expired
|
|
96
|
+
|
|
97
|
+
### useTokenCount
|
|
98
|
+
|
|
99
|
+
Track token usage and context window limits.
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
const {
|
|
103
|
+
tokenCount, // number - Current token count
|
|
104
|
+
maxTokens, // number - Model's max context
|
|
105
|
+
remainingTokens, // number - Tokens remaining
|
|
106
|
+
isNearLimit, // boolean - Within 10% of limit
|
|
107
|
+
isOverLimit, // boolean - Exceeded limit
|
|
108
|
+
updateText, // (text: string) => void - Update counted text
|
|
109
|
+
} = useTokenCount({
|
|
110
|
+
model: 'gpt-4', // Model name for limits
|
|
111
|
+
text: '', // Initial text to count
|
|
112
|
+
warningThreshold: 0.9, // Threshold for isNearLimit
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Supported models:**
|
|
117
|
+
- `gpt-4`, `gpt-4-turbo`: 128,000 tokens
|
|
118
|
+
- `gpt-3.5-turbo`: 16,385 tokens
|
|
119
|
+
- `claude-3-opus`, `claude-3-sonnet`: 200,000 tokens
|
|
120
|
+
- And more...
|
|
121
|
+
|
|
122
|
+
### useStream
|
|
123
|
+
|
|
124
|
+
Low-level hook for consuming async iterables/streams.
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
const {
|
|
128
|
+
data, // T[] - Accumulated data
|
|
129
|
+
isStreaming, // boolean
|
|
130
|
+
error, // Error | undefined
|
|
131
|
+
start, // (stream: AsyncIterable<T>) => void
|
|
132
|
+
stop, // () => void
|
|
133
|
+
reset, // () => void
|
|
134
|
+
} = useStream<ChunkType>({
|
|
135
|
+
onChunk: (chunk) => {}, // Called for each chunk
|
|
136
|
+
onComplete: (data) => {}, // Called when done
|
|
137
|
+
onError: (error) => {}, // Called on error
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
MIT - see [LICENSE](./LICENSE) for details.
|