@deltakit/react 0.1.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/dist/index.cjs +195 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +67 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.js +166 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
fromOpenAiAgents: () => import_core2.fromOpenAiAgents,
|
|
24
|
+
parseSSEStream: () => import_core2.parseSSEStream,
|
|
25
|
+
useStreamChat: () => useStreamChat
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
|
|
29
|
+
// src/use-stream-chat.ts
|
|
30
|
+
var import_react = require("react");
|
|
31
|
+
var import_core = require("@deltakit/core");
|
|
32
|
+
var counter = 0;
|
|
33
|
+
function generateId() {
|
|
34
|
+
return `msg_${Date.now()}_${++counter}`;
|
|
35
|
+
}
|
|
36
|
+
function createMessage(role, parts) {
|
|
37
|
+
return { id: generateId(), role, parts };
|
|
38
|
+
}
|
|
39
|
+
function defaultOnEvent(event, helpers) {
|
|
40
|
+
if (event.type === "text_delta") {
|
|
41
|
+
helpers.appendText(event.delta);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function useStreamChat(options) {
|
|
45
|
+
const {
|
|
46
|
+
api,
|
|
47
|
+
headers,
|
|
48
|
+
body,
|
|
49
|
+
initialMessages,
|
|
50
|
+
onEvent,
|
|
51
|
+
onMessage,
|
|
52
|
+
onError,
|
|
53
|
+
onFinish
|
|
54
|
+
} = options;
|
|
55
|
+
const [messages, setMessages] = (0, import_react.useState)(
|
|
56
|
+
initialMessages ?? []
|
|
57
|
+
);
|
|
58
|
+
const [isLoading, setIsLoading] = (0, import_react.useState)(false);
|
|
59
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
60
|
+
const abortRef = (0, import_react.useRef)(null);
|
|
61
|
+
const messagesRef = (0, import_react.useRef)(messages);
|
|
62
|
+
messagesRef.current = messages;
|
|
63
|
+
const appendText = (0, import_react.useCallback)((delta) => {
|
|
64
|
+
setMessages((prev) => {
|
|
65
|
+
const last = prev[prev.length - 1];
|
|
66
|
+
if (!last || last.role !== "assistant") return prev;
|
|
67
|
+
const parts = [...last.parts];
|
|
68
|
+
const lastPart = parts[parts.length - 1];
|
|
69
|
+
if (lastPart && lastPart.type === "text" && "text" in lastPart) {
|
|
70
|
+
const textPart = lastPart;
|
|
71
|
+
parts[parts.length - 1] = {
|
|
72
|
+
...lastPart,
|
|
73
|
+
text: textPart.text + delta
|
|
74
|
+
};
|
|
75
|
+
} else {
|
|
76
|
+
parts.push({ type: "text", text: delta });
|
|
77
|
+
}
|
|
78
|
+
const updated = { ...last, parts };
|
|
79
|
+
return [...prev.slice(0, -1), updated];
|
|
80
|
+
});
|
|
81
|
+
}, []);
|
|
82
|
+
const appendPart = (0, import_react.useCallback)((part) => {
|
|
83
|
+
setMessages((prev) => {
|
|
84
|
+
const last = prev[prev.length - 1];
|
|
85
|
+
if (!last || last.role !== "assistant") return prev;
|
|
86
|
+
const updated = {
|
|
87
|
+
...last,
|
|
88
|
+
parts: [...last.parts, part]
|
|
89
|
+
};
|
|
90
|
+
return [...prev.slice(0, -1), updated];
|
|
91
|
+
});
|
|
92
|
+
}, []);
|
|
93
|
+
const stop = (0, import_react.useCallback)(() => {
|
|
94
|
+
abortRef.current?.abort();
|
|
95
|
+
abortRef.current = null;
|
|
96
|
+
setIsLoading(false);
|
|
97
|
+
}, []);
|
|
98
|
+
const sendMessage = (0, import_react.useCallback)(
|
|
99
|
+
(text) => {
|
|
100
|
+
if (abortRef.current) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const userMessage = createMessage("user", [
|
|
104
|
+
{ type: "text", text }
|
|
105
|
+
]);
|
|
106
|
+
const assistantMessage = createMessage("assistant", []);
|
|
107
|
+
setMessages((prev) => {
|
|
108
|
+
const next = [...prev, userMessage, assistantMessage];
|
|
109
|
+
messagesRef.current = next;
|
|
110
|
+
return next;
|
|
111
|
+
});
|
|
112
|
+
onMessage?.(userMessage);
|
|
113
|
+
setError(null);
|
|
114
|
+
setIsLoading(true);
|
|
115
|
+
const controller = new AbortController();
|
|
116
|
+
abortRef.current = controller;
|
|
117
|
+
const eventHandler = onEvent ?? defaultOnEvent;
|
|
118
|
+
const helpers = {
|
|
119
|
+
appendText,
|
|
120
|
+
appendPart,
|
|
121
|
+
setMessages
|
|
122
|
+
};
|
|
123
|
+
(async () => {
|
|
124
|
+
try {
|
|
125
|
+
const response = await fetch(api, {
|
|
126
|
+
method: "POST",
|
|
127
|
+
headers: {
|
|
128
|
+
"Content-Type": "application/json",
|
|
129
|
+
...headers
|
|
130
|
+
},
|
|
131
|
+
body: JSON.stringify({ message: text, ...body }),
|
|
132
|
+
signal: controller.signal
|
|
133
|
+
});
|
|
134
|
+
if (!response.ok) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`SSE request failed: ${response.status} ${response.statusText}`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
if (!response.body) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
"Response body is null \u2014 SSE streaming not supported"
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
for await (const event of (0, import_core.parseSSEStream)(
|
|
145
|
+
response.body,
|
|
146
|
+
controller.signal
|
|
147
|
+
)) {
|
|
148
|
+
eventHandler(event, helpers);
|
|
149
|
+
}
|
|
150
|
+
const finalMessages = messagesRef.current;
|
|
151
|
+
const lastMessage = finalMessages[finalMessages.length - 1];
|
|
152
|
+
if (lastMessage?.role === "assistant") {
|
|
153
|
+
onMessage?.(lastMessage);
|
|
154
|
+
}
|
|
155
|
+
onFinish?.(finalMessages);
|
|
156
|
+
} catch (err) {
|
|
157
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
161
|
+
setError(error2);
|
|
162
|
+
onError?.(error2);
|
|
163
|
+
} finally {
|
|
164
|
+
abortRef.current = null;
|
|
165
|
+
setIsLoading(false);
|
|
166
|
+
}
|
|
167
|
+
})();
|
|
168
|
+
},
|
|
169
|
+
[api, headers, body, onEvent, onMessage, onError, onFinish, appendText, appendPart]
|
|
170
|
+
);
|
|
171
|
+
(0, import_react.useEffect)(() => {
|
|
172
|
+
return () => {
|
|
173
|
+
abortRef.current?.abort();
|
|
174
|
+
abortRef.current = null;
|
|
175
|
+
};
|
|
176
|
+
}, []);
|
|
177
|
+
return {
|
|
178
|
+
messages,
|
|
179
|
+
isLoading,
|
|
180
|
+
error,
|
|
181
|
+
sendMessage,
|
|
182
|
+
stop,
|
|
183
|
+
setMessages
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/index.ts
|
|
188
|
+
var import_core2 = require("@deltakit/core");
|
|
189
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
190
|
+
0 && (module.exports = {
|
|
191
|
+
fromOpenAiAgents,
|
|
192
|
+
parseSSEStream,
|
|
193
|
+
useStreamChat
|
|
194
|
+
});
|
|
195
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/use-stream-chat.ts"],"sourcesContent":["export { useStreamChat } from \"./use-stream-chat\";\n\nexport type {\n EventHelpers,\n UseStreamChatOptions,\n UseStreamChatReturn,\n} from \"./types\";\n\n// Re-export core types so consumers only need to import from @deltakit/react\nexport type {\n TextPart,\n ToolCallPart,\n ReasoningPart,\n ContentPart,\n Message,\n TextDeltaEvent,\n ToolCallEvent,\n ToolResultEvent,\n SSEEvent,\n} from \"@deltakit/core\";\n\nexport { parseSSEStream, fromOpenAiAgents } from \"@deltakit/core\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { parseSSEStream } from \"@deltakit/core\";\nimport type {\n ContentPart,\n Message,\n SSEEvent,\n} from \"@deltakit/core\";\nimport type {\n EventHelpers,\n UseStreamChatOptions,\n UseStreamChatReturn,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nlet counter = 0;\n\nfunction generateId(): string {\n return `msg_${Date.now()}_${++counter}`;\n}\n\nfunction createMessage<TPart extends { type: string }>(\n role: Message[\"role\"],\n parts: TPart[],\n): Message<TPart> {\n return { id: generateId(), role, parts };\n}\n\n// ---------------------------------------------------------------------------\n// Default event handler — accumulates `text_delta` into the last\n// assistant message's parts.\n// ---------------------------------------------------------------------------\n\nfunction defaultOnEvent(\n event: SSEEvent,\n helpers: EventHelpers<ContentPart>,\n): void {\n if (event.type === \"text_delta\") {\n helpers.appendText(event.delta);\n }\n // Other event types (e.g. tool_call) are silently ignored by default.\n // Users can provide their own `onEvent` to handle them.\n}\n\n// ---------------------------------------------------------------------------\n// useStreamChat\n// ---------------------------------------------------------------------------\n\nexport function useStreamChat<\n TPart extends { type: string } = ContentPart,\n TEvent extends { type: string } = SSEEvent,\n>(options: UseStreamChatOptions<TPart, TEvent>): UseStreamChatReturn<TPart> {\n const {\n api,\n headers,\n body,\n initialMessages,\n onEvent,\n onMessage,\n onError,\n onFinish,\n } = options;\n\n const [messages, setMessages] = useState<Message<TPart>[]>(\n initialMessages ?? [],\n );\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const abortRef = useRef<AbortController | null>(null);\n\n // We use a ref for the latest messages so that callbacks created inside\n // `sendMessage` always see the current value without re-creating closures.\n const messagesRef = useRef<Message<TPart>[]>(messages);\n messagesRef.current = messages;\n\n // -----------------------------------------------------------------------\n // appendText — append a text delta to the last text part of the last\n // assistant message, or create a new text part if needed.\n // -----------------------------------------------------------------------\n\n const appendText = useCallback((delta: string) => {\n setMessages((prev) => {\n const last = prev[prev.length - 1];\n if (!last || last.role !== \"assistant\") return prev;\n\n const parts = [...last.parts];\n const lastPart = parts[parts.length - 1];\n\n if (lastPart && lastPart.type === \"text\" && \"text\" in lastPart) {\n // Append to existing text part\n const textPart = lastPart as { type: \"text\"; text: string };\n parts[parts.length - 1] = {\n ...lastPart,\n text: textPart.text + delta,\n } as unknown as TPart;\n } else {\n // Create a new text part\n parts.push({ type: \"text\", text: delta } as unknown as TPart);\n }\n\n const updated: Message<TPart> = { ...last, parts };\n return [...prev.slice(0, -1), updated];\n });\n }, []);\n\n // -----------------------------------------------------------------------\n // appendPart — push a new content part to the last assistant message.\n // -----------------------------------------------------------------------\n\n const appendPart = useCallback((part: TPart) => {\n setMessages((prev) => {\n const last = prev[prev.length - 1];\n if (!last || last.role !== \"assistant\") return prev;\n\n const updated: Message<TPart> = {\n ...last,\n parts: [...last.parts, part],\n };\n return [...prev.slice(0, -1), updated];\n });\n }, []);\n\n // -----------------------------------------------------------------------\n // stop\n // -----------------------------------------------------------------------\n\n const stop = useCallback(() => {\n abortRef.current?.abort();\n abortRef.current = null;\n setIsLoading(false);\n }, []);\n\n // -----------------------------------------------------------------------\n // sendMessage\n // -----------------------------------------------------------------------\n\n const sendMessage = useCallback(\n (text: string) => {\n // Prevent sending while already streaming.\n if (abortRef.current) {\n return;\n }\n\n const userMessage = createMessage<TPart>(\"user\", [\n { type: \"text\", text } as unknown as TPart,\n ]);\n const assistantMessage = createMessage<TPart>(\"assistant\", []);\n\n setMessages((prev) => {\n const next = [...prev, userMessage, assistantMessage];\n messagesRef.current = next;\n return next;\n });\n\n onMessage?.(userMessage);\n\n setError(null);\n setIsLoading(true);\n\n const controller = new AbortController();\n abortRef.current = controller;\n\n const eventHandler =\n onEvent ??\n (defaultOnEvent as unknown as (\n event: TEvent,\n helpers: EventHelpers<TPart>,\n ) => void);\n const helpers: EventHelpers<TPart> = {\n appendText,\n appendPart,\n setMessages,\n };\n\n // Fire-and-forget async IIFE — state is managed via React setState.\n (async () => {\n try {\n const response = await fetch(api, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...headers,\n },\n body: JSON.stringify({ message: text, ...body }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(\n `SSE request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n if (!response.body) {\n throw new Error(\n \"Response body is null — SSE streaming not supported\",\n );\n }\n\n for await (const event of parseSSEStream(\n response.body,\n controller.signal,\n )) {\n eventHandler(event as unknown as TEvent, helpers);\n }\n\n // Stream finished — notify via callbacks.\n const finalMessages = messagesRef.current;\n const lastMessage = finalMessages[finalMessages.length - 1];\n\n if (lastMessage?.role === \"assistant\") {\n onMessage?.(lastMessage);\n }\n\n onFinish?.(finalMessages);\n } catch (err) {\n // AbortError is expected when the user calls `stop()`.\n if (err instanceof DOMException && err.name === \"AbortError\") {\n return;\n }\n\n const error = err instanceof Error ? err : new Error(String(err));\n\n setError(error);\n onError?.(error);\n } finally {\n abortRef.current = null;\n setIsLoading(false);\n }\n })();\n },\n [api, headers, body, onEvent, onMessage, onError, onFinish, appendText, appendPart],\n );\n\n // -----------------------------------------------------------------------\n // Cleanup — abort any in-flight stream when the component unmounts.\n // -----------------------------------------------------------------------\n\n useEffect(() => {\n return () => {\n abortRef.current?.abort();\n abortRef.current = null;\n };\n }, []);\n\n return {\n messages,\n isLoading,\n error,\n sendMessage,\n stop,\n setMessages,\n };\n}\n"],"mappings":"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","names":["error","import_core"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ContentPart, Message, SSEEvent } from '@deltakit/core';
|
|
2
|
+
export { ContentPart, Message, ReasoningPart, SSEEvent, TextDeltaEvent, TextPart, ToolCallEvent, ToolCallPart, ToolResultEvent, fromOpenAiAgents, parseSSEStream } from '@deltakit/core';
|
|
3
|
+
import { Dispatch, SetStateAction } from 'react';
|
|
4
|
+
|
|
5
|
+
interface EventHelpers<TPart extends {
|
|
6
|
+
type: string;
|
|
7
|
+
} = ContentPart> {
|
|
8
|
+
/** Append a text delta to the last text part of the current assistant message, or create a new text part. */
|
|
9
|
+
appendText: (delta: string) => void;
|
|
10
|
+
/** Append a new content part to the current assistant message. */
|
|
11
|
+
appendPart: (part: TPart) => void;
|
|
12
|
+
/** Direct access to the messages state setter for advanced use-cases. */
|
|
13
|
+
setMessages: Dispatch<SetStateAction<Message<TPart>[]>>;
|
|
14
|
+
}
|
|
15
|
+
interface UseStreamChatOptions<TPart extends {
|
|
16
|
+
type: string;
|
|
17
|
+
} = ContentPart, TEvent extends {
|
|
18
|
+
type: string;
|
|
19
|
+
} = SSEEvent> {
|
|
20
|
+
/** SSE endpoint URL. */
|
|
21
|
+
api: string;
|
|
22
|
+
/** Initial messages to prepopulate the chat (e.g. from a database or previous session). */
|
|
23
|
+
initialMessages?: Message<TPart>[];
|
|
24
|
+
/** Extra headers merged into every fetch request. */
|
|
25
|
+
headers?: Record<string, string>;
|
|
26
|
+
/** Extra fields merged into the POST body alongside `message`. */
|
|
27
|
+
body?: Record<string, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* Custom handler for each SSE event. When provided, this **replaces** the
|
|
30
|
+
* default `text_delta` handling — giving you full control over how events
|
|
31
|
+
* are mapped to message state.
|
|
32
|
+
*
|
|
33
|
+
* The `event` parameter is typed as `TEvent`, which defaults to `SSEEvent`.
|
|
34
|
+
* Pass a custom event union as the second generic to handle additional event types.
|
|
35
|
+
*/
|
|
36
|
+
onEvent?: (event: TEvent, helpers: EventHelpers<TPart>) => void;
|
|
37
|
+
/** Called when the assistant message is complete (stream ended). */
|
|
38
|
+
onFinish?: (messages: Message<TPart>[]) => void;
|
|
39
|
+
/** Called whenever a new complete message (user or assistant) is added. */
|
|
40
|
+
onMessage?: (message: Message<TPart>) => void;
|
|
41
|
+
/** Called when a fetch or stream error occurs. */
|
|
42
|
+
onError?: (error: Error) => void;
|
|
43
|
+
}
|
|
44
|
+
interface UseStreamChatReturn<TPart extends {
|
|
45
|
+
type: string;
|
|
46
|
+
} = ContentPart> {
|
|
47
|
+
/** Chronological list of messages in the conversation. */
|
|
48
|
+
messages: Message<TPart>[];
|
|
49
|
+
/** `true` while the assistant is streaming a response. */
|
|
50
|
+
isLoading: boolean;
|
|
51
|
+
/** The most recent error, or `null`. */
|
|
52
|
+
error: Error | null;
|
|
53
|
+
/** Send a user message and begin streaming the assistant response. */
|
|
54
|
+
sendMessage: (text: string) => void;
|
|
55
|
+
/** Abort the current stream. */
|
|
56
|
+
stop: () => void;
|
|
57
|
+
/** Direct setter for programmatic message manipulation (clear, prepopulate, etc.). */
|
|
58
|
+
setMessages: Dispatch<SetStateAction<Message<TPart>[]>>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
declare function useStreamChat<TPart extends {
|
|
62
|
+
type: string;
|
|
63
|
+
} = ContentPart, TEvent extends {
|
|
64
|
+
type: string;
|
|
65
|
+
} = SSEEvent>(options: UseStreamChatOptions<TPart, TEvent>): UseStreamChatReturn<TPart>;
|
|
66
|
+
|
|
67
|
+
export { type EventHelpers, type UseStreamChatOptions, type UseStreamChatReturn, useStreamChat };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ContentPart, Message, SSEEvent } from '@deltakit/core';
|
|
2
|
+
export { ContentPart, Message, ReasoningPart, SSEEvent, TextDeltaEvent, TextPart, ToolCallEvent, ToolCallPart, ToolResultEvent, fromOpenAiAgents, parseSSEStream } from '@deltakit/core';
|
|
3
|
+
import { Dispatch, SetStateAction } from 'react';
|
|
4
|
+
|
|
5
|
+
interface EventHelpers<TPart extends {
|
|
6
|
+
type: string;
|
|
7
|
+
} = ContentPart> {
|
|
8
|
+
/** Append a text delta to the last text part of the current assistant message, or create a new text part. */
|
|
9
|
+
appendText: (delta: string) => void;
|
|
10
|
+
/** Append a new content part to the current assistant message. */
|
|
11
|
+
appendPart: (part: TPart) => void;
|
|
12
|
+
/** Direct access to the messages state setter for advanced use-cases. */
|
|
13
|
+
setMessages: Dispatch<SetStateAction<Message<TPart>[]>>;
|
|
14
|
+
}
|
|
15
|
+
interface UseStreamChatOptions<TPart extends {
|
|
16
|
+
type: string;
|
|
17
|
+
} = ContentPart, TEvent extends {
|
|
18
|
+
type: string;
|
|
19
|
+
} = SSEEvent> {
|
|
20
|
+
/** SSE endpoint URL. */
|
|
21
|
+
api: string;
|
|
22
|
+
/** Initial messages to prepopulate the chat (e.g. from a database or previous session). */
|
|
23
|
+
initialMessages?: Message<TPart>[];
|
|
24
|
+
/** Extra headers merged into every fetch request. */
|
|
25
|
+
headers?: Record<string, string>;
|
|
26
|
+
/** Extra fields merged into the POST body alongside `message`. */
|
|
27
|
+
body?: Record<string, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* Custom handler for each SSE event. When provided, this **replaces** the
|
|
30
|
+
* default `text_delta` handling — giving you full control over how events
|
|
31
|
+
* are mapped to message state.
|
|
32
|
+
*
|
|
33
|
+
* The `event` parameter is typed as `TEvent`, which defaults to `SSEEvent`.
|
|
34
|
+
* Pass a custom event union as the second generic to handle additional event types.
|
|
35
|
+
*/
|
|
36
|
+
onEvent?: (event: TEvent, helpers: EventHelpers<TPart>) => void;
|
|
37
|
+
/** Called when the assistant message is complete (stream ended). */
|
|
38
|
+
onFinish?: (messages: Message<TPart>[]) => void;
|
|
39
|
+
/** Called whenever a new complete message (user or assistant) is added. */
|
|
40
|
+
onMessage?: (message: Message<TPart>) => void;
|
|
41
|
+
/** Called when a fetch or stream error occurs. */
|
|
42
|
+
onError?: (error: Error) => void;
|
|
43
|
+
}
|
|
44
|
+
interface UseStreamChatReturn<TPart extends {
|
|
45
|
+
type: string;
|
|
46
|
+
} = ContentPart> {
|
|
47
|
+
/** Chronological list of messages in the conversation. */
|
|
48
|
+
messages: Message<TPart>[];
|
|
49
|
+
/** `true` while the assistant is streaming a response. */
|
|
50
|
+
isLoading: boolean;
|
|
51
|
+
/** The most recent error, or `null`. */
|
|
52
|
+
error: Error | null;
|
|
53
|
+
/** Send a user message and begin streaming the assistant response. */
|
|
54
|
+
sendMessage: (text: string) => void;
|
|
55
|
+
/** Abort the current stream. */
|
|
56
|
+
stop: () => void;
|
|
57
|
+
/** Direct setter for programmatic message manipulation (clear, prepopulate, etc.). */
|
|
58
|
+
setMessages: Dispatch<SetStateAction<Message<TPart>[]>>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
declare function useStreamChat<TPart extends {
|
|
62
|
+
type: string;
|
|
63
|
+
} = ContentPart, TEvent extends {
|
|
64
|
+
type: string;
|
|
65
|
+
} = SSEEvent>(options: UseStreamChatOptions<TPart, TEvent>): UseStreamChatReturn<TPart>;
|
|
66
|
+
|
|
67
|
+
export { type EventHelpers, type UseStreamChatOptions, type UseStreamChatReturn, useStreamChat };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// src/use-stream-chat.ts
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { parseSSEStream } from "@deltakit/core";
|
|
4
|
+
var counter = 0;
|
|
5
|
+
function generateId() {
|
|
6
|
+
return `msg_${Date.now()}_${++counter}`;
|
|
7
|
+
}
|
|
8
|
+
function createMessage(role, parts) {
|
|
9
|
+
return { id: generateId(), role, parts };
|
|
10
|
+
}
|
|
11
|
+
function defaultOnEvent(event, helpers) {
|
|
12
|
+
if (event.type === "text_delta") {
|
|
13
|
+
helpers.appendText(event.delta);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function useStreamChat(options) {
|
|
17
|
+
const {
|
|
18
|
+
api,
|
|
19
|
+
headers,
|
|
20
|
+
body,
|
|
21
|
+
initialMessages,
|
|
22
|
+
onEvent,
|
|
23
|
+
onMessage,
|
|
24
|
+
onError,
|
|
25
|
+
onFinish
|
|
26
|
+
} = options;
|
|
27
|
+
const [messages, setMessages] = useState(
|
|
28
|
+
initialMessages ?? []
|
|
29
|
+
);
|
|
30
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
31
|
+
const [error, setError] = useState(null);
|
|
32
|
+
const abortRef = useRef(null);
|
|
33
|
+
const messagesRef = useRef(messages);
|
|
34
|
+
messagesRef.current = messages;
|
|
35
|
+
const appendText = useCallback((delta) => {
|
|
36
|
+
setMessages((prev) => {
|
|
37
|
+
const last = prev[prev.length - 1];
|
|
38
|
+
if (!last || last.role !== "assistant") return prev;
|
|
39
|
+
const parts = [...last.parts];
|
|
40
|
+
const lastPart = parts[parts.length - 1];
|
|
41
|
+
if (lastPart && lastPart.type === "text" && "text" in lastPart) {
|
|
42
|
+
const textPart = lastPart;
|
|
43
|
+
parts[parts.length - 1] = {
|
|
44
|
+
...lastPart,
|
|
45
|
+
text: textPart.text + delta
|
|
46
|
+
};
|
|
47
|
+
} else {
|
|
48
|
+
parts.push({ type: "text", text: delta });
|
|
49
|
+
}
|
|
50
|
+
const updated = { ...last, parts };
|
|
51
|
+
return [...prev.slice(0, -1), updated];
|
|
52
|
+
});
|
|
53
|
+
}, []);
|
|
54
|
+
const appendPart = useCallback((part) => {
|
|
55
|
+
setMessages((prev) => {
|
|
56
|
+
const last = prev[prev.length - 1];
|
|
57
|
+
if (!last || last.role !== "assistant") return prev;
|
|
58
|
+
const updated = {
|
|
59
|
+
...last,
|
|
60
|
+
parts: [...last.parts, part]
|
|
61
|
+
};
|
|
62
|
+
return [...prev.slice(0, -1), updated];
|
|
63
|
+
});
|
|
64
|
+
}, []);
|
|
65
|
+
const stop = useCallback(() => {
|
|
66
|
+
abortRef.current?.abort();
|
|
67
|
+
abortRef.current = null;
|
|
68
|
+
setIsLoading(false);
|
|
69
|
+
}, []);
|
|
70
|
+
const sendMessage = useCallback(
|
|
71
|
+
(text) => {
|
|
72
|
+
if (abortRef.current) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const userMessage = createMessage("user", [
|
|
76
|
+
{ type: "text", text }
|
|
77
|
+
]);
|
|
78
|
+
const assistantMessage = createMessage("assistant", []);
|
|
79
|
+
setMessages((prev) => {
|
|
80
|
+
const next = [...prev, userMessage, assistantMessage];
|
|
81
|
+
messagesRef.current = next;
|
|
82
|
+
return next;
|
|
83
|
+
});
|
|
84
|
+
onMessage?.(userMessage);
|
|
85
|
+
setError(null);
|
|
86
|
+
setIsLoading(true);
|
|
87
|
+
const controller = new AbortController();
|
|
88
|
+
abortRef.current = controller;
|
|
89
|
+
const eventHandler = onEvent ?? defaultOnEvent;
|
|
90
|
+
const helpers = {
|
|
91
|
+
appendText,
|
|
92
|
+
appendPart,
|
|
93
|
+
setMessages
|
|
94
|
+
};
|
|
95
|
+
(async () => {
|
|
96
|
+
try {
|
|
97
|
+
const response = await fetch(api, {
|
|
98
|
+
method: "POST",
|
|
99
|
+
headers: {
|
|
100
|
+
"Content-Type": "application/json",
|
|
101
|
+
...headers
|
|
102
|
+
},
|
|
103
|
+
body: JSON.stringify({ message: text, ...body }),
|
|
104
|
+
signal: controller.signal
|
|
105
|
+
});
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
`SSE request failed: ${response.status} ${response.statusText}`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
if (!response.body) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
"Response body is null \u2014 SSE streaming not supported"
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
for await (const event of parseSSEStream(
|
|
117
|
+
response.body,
|
|
118
|
+
controller.signal
|
|
119
|
+
)) {
|
|
120
|
+
eventHandler(event, helpers);
|
|
121
|
+
}
|
|
122
|
+
const finalMessages = messagesRef.current;
|
|
123
|
+
const lastMessage = finalMessages[finalMessages.length - 1];
|
|
124
|
+
if (lastMessage?.role === "assistant") {
|
|
125
|
+
onMessage?.(lastMessage);
|
|
126
|
+
}
|
|
127
|
+
onFinish?.(finalMessages);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
133
|
+
setError(error2);
|
|
134
|
+
onError?.(error2);
|
|
135
|
+
} finally {
|
|
136
|
+
abortRef.current = null;
|
|
137
|
+
setIsLoading(false);
|
|
138
|
+
}
|
|
139
|
+
})();
|
|
140
|
+
},
|
|
141
|
+
[api, headers, body, onEvent, onMessage, onError, onFinish, appendText, appendPart]
|
|
142
|
+
);
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
return () => {
|
|
145
|
+
abortRef.current?.abort();
|
|
146
|
+
abortRef.current = null;
|
|
147
|
+
};
|
|
148
|
+
}, []);
|
|
149
|
+
return {
|
|
150
|
+
messages,
|
|
151
|
+
isLoading,
|
|
152
|
+
error,
|
|
153
|
+
sendMessage,
|
|
154
|
+
stop,
|
|
155
|
+
setMessages
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/index.ts
|
|
160
|
+
import { parseSSEStream as parseSSEStream2, fromOpenAiAgents } from "@deltakit/core";
|
|
161
|
+
export {
|
|
162
|
+
fromOpenAiAgents,
|
|
163
|
+
parseSSEStream2 as parseSSEStream,
|
|
164
|
+
useStreamChat
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/use-stream-chat.ts","../src/index.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { parseSSEStream } from \"@deltakit/core\";\nimport type {\n ContentPart,\n Message,\n SSEEvent,\n} from \"@deltakit/core\";\nimport type {\n EventHelpers,\n UseStreamChatOptions,\n UseStreamChatReturn,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nlet counter = 0;\n\nfunction generateId(): string {\n return `msg_${Date.now()}_${++counter}`;\n}\n\nfunction createMessage<TPart extends { type: string }>(\n role: Message[\"role\"],\n parts: TPart[],\n): Message<TPart> {\n return { id: generateId(), role, parts };\n}\n\n// ---------------------------------------------------------------------------\n// Default event handler — accumulates `text_delta` into the last\n// assistant message's parts.\n// ---------------------------------------------------------------------------\n\nfunction defaultOnEvent(\n event: SSEEvent,\n helpers: EventHelpers<ContentPart>,\n): void {\n if (event.type === \"text_delta\") {\n helpers.appendText(event.delta);\n }\n // Other event types (e.g. tool_call) are silently ignored by default.\n // Users can provide their own `onEvent` to handle them.\n}\n\n// ---------------------------------------------------------------------------\n// useStreamChat\n// ---------------------------------------------------------------------------\n\nexport function useStreamChat<\n TPart extends { type: string } = ContentPart,\n TEvent extends { type: string } = SSEEvent,\n>(options: UseStreamChatOptions<TPart, TEvent>): UseStreamChatReturn<TPart> {\n const {\n api,\n headers,\n body,\n initialMessages,\n onEvent,\n onMessage,\n onError,\n onFinish,\n } = options;\n\n const [messages, setMessages] = useState<Message<TPart>[]>(\n initialMessages ?? [],\n );\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const abortRef = useRef<AbortController | null>(null);\n\n // We use a ref for the latest messages so that callbacks created inside\n // `sendMessage` always see the current value without re-creating closures.\n const messagesRef = useRef<Message<TPart>[]>(messages);\n messagesRef.current = messages;\n\n // -----------------------------------------------------------------------\n // appendText — append a text delta to the last text part of the last\n // assistant message, or create a new text part if needed.\n // -----------------------------------------------------------------------\n\n const appendText = useCallback((delta: string) => {\n setMessages((prev) => {\n const last = prev[prev.length - 1];\n if (!last || last.role !== \"assistant\") return prev;\n\n const parts = [...last.parts];\n const lastPart = parts[parts.length - 1];\n\n if (lastPart && lastPart.type === \"text\" && \"text\" in lastPart) {\n // Append to existing text part\n const textPart = lastPart as { type: \"text\"; text: string };\n parts[parts.length - 1] = {\n ...lastPart,\n text: textPart.text + delta,\n } as unknown as TPart;\n } else {\n // Create a new text part\n parts.push({ type: \"text\", text: delta } as unknown as TPart);\n }\n\n const updated: Message<TPart> = { ...last, parts };\n return [...prev.slice(0, -1), updated];\n });\n }, []);\n\n // -----------------------------------------------------------------------\n // appendPart — push a new content part to the last assistant message.\n // -----------------------------------------------------------------------\n\n const appendPart = useCallback((part: TPart) => {\n setMessages((prev) => {\n const last = prev[prev.length - 1];\n if (!last || last.role !== \"assistant\") return prev;\n\n const updated: Message<TPart> = {\n ...last,\n parts: [...last.parts, part],\n };\n return [...prev.slice(0, -1), updated];\n });\n }, []);\n\n // -----------------------------------------------------------------------\n // stop\n // -----------------------------------------------------------------------\n\n const stop = useCallback(() => {\n abortRef.current?.abort();\n abortRef.current = null;\n setIsLoading(false);\n }, []);\n\n // -----------------------------------------------------------------------\n // sendMessage\n // -----------------------------------------------------------------------\n\n const sendMessage = useCallback(\n (text: string) => {\n // Prevent sending while already streaming.\n if (abortRef.current) {\n return;\n }\n\n const userMessage = createMessage<TPart>(\"user\", [\n { type: \"text\", text } as unknown as TPart,\n ]);\n const assistantMessage = createMessage<TPart>(\"assistant\", []);\n\n setMessages((prev) => {\n const next = [...prev, userMessage, assistantMessage];\n messagesRef.current = next;\n return next;\n });\n\n onMessage?.(userMessage);\n\n setError(null);\n setIsLoading(true);\n\n const controller = new AbortController();\n abortRef.current = controller;\n\n const eventHandler =\n onEvent ??\n (defaultOnEvent as unknown as (\n event: TEvent,\n helpers: EventHelpers<TPart>,\n ) => void);\n const helpers: EventHelpers<TPart> = {\n appendText,\n appendPart,\n setMessages,\n };\n\n // Fire-and-forget async IIFE — state is managed via React setState.\n (async () => {\n try {\n const response = await fetch(api, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...headers,\n },\n body: JSON.stringify({ message: text, ...body }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(\n `SSE request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n if (!response.body) {\n throw new Error(\n \"Response body is null — SSE streaming not supported\",\n );\n }\n\n for await (const event of parseSSEStream(\n response.body,\n controller.signal,\n )) {\n eventHandler(event as unknown as TEvent, helpers);\n }\n\n // Stream finished — notify via callbacks.\n const finalMessages = messagesRef.current;\n const lastMessage = finalMessages[finalMessages.length - 1];\n\n if (lastMessage?.role === \"assistant\") {\n onMessage?.(lastMessage);\n }\n\n onFinish?.(finalMessages);\n } catch (err) {\n // AbortError is expected when the user calls `stop()`.\n if (err instanceof DOMException && err.name === \"AbortError\") {\n return;\n }\n\n const error = err instanceof Error ? err : new Error(String(err));\n\n setError(error);\n onError?.(error);\n } finally {\n abortRef.current = null;\n setIsLoading(false);\n }\n })();\n },\n [api, headers, body, onEvent, onMessage, onError, onFinish, appendText, appendPart],\n );\n\n // -----------------------------------------------------------------------\n // Cleanup — abort any in-flight stream when the component unmounts.\n // -----------------------------------------------------------------------\n\n useEffect(() => {\n return () => {\n abortRef.current?.abort();\n abortRef.current = null;\n };\n }, []);\n\n return {\n messages,\n isLoading,\n error,\n sendMessage,\n stop,\n setMessages,\n };\n}\n","export { useStreamChat } from \"./use-stream-chat\";\n\nexport type {\n EventHelpers,\n UseStreamChatOptions,\n UseStreamChatReturn,\n} from \"./types\";\n\n// Re-export core types so consumers only need to import from @deltakit/react\nexport type {\n TextPart,\n ToolCallPart,\n ReasoningPart,\n ContentPart,\n Message,\n TextDeltaEvent,\n ToolCallEvent,\n ToolResultEvent,\n SSEEvent,\n} from \"@deltakit/core\";\n\nexport { parseSSEStream, fromOpenAiAgents } from \"@deltakit/core\";\n"],"mappings":"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","names":["error","parseSSEStream"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@deltakit/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "DeltaKit React bindings",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "DeltaKit HQ",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/deltakithq/deltakit-monorepo",
|
|
11
|
+
"directory": "packages/react"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"deltakit",
|
|
15
|
+
"react"
|
|
16
|
+
],
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"import": "./dist/index.js",
|
|
21
|
+
"require": "./dist/index.cjs"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"main": "./dist/index.cjs",
|
|
25
|
+
"module": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@deltakit/core": "0.1.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/react": "^18.3.18",
|
|
35
|
+
"react": "^18.3.1",
|
|
36
|
+
"tsup": "8.5.1",
|
|
37
|
+
"typescript": "^5.7.2"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"react": ">=18"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsup",
|
|
44
|
+
"dev": "tsup --watch",
|
|
45
|
+
"check": "biome check src/",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"clean": "rm -rf dist"
|
|
48
|
+
}
|
|
49
|
+
}
|