@starcite/react 0.0.7

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,171 @@
1
+ // src/chat-protocol.ts
2
+ import { readUIMessageStream } from "ai";
3
+ var chatUserMessageEventType = "chat.user.message";
4
+ var chatAssistantChunkEventType = "chat.assistant.chunk";
5
+ function isChatEventType(type) {
6
+ return type === chatUserMessageEventType || type === chatAssistantChunkEventType;
7
+ }
8
+ function isRecord(value) {
9
+ return typeof value === "object" && value !== null;
10
+ }
11
+ function parseUserEnvelope(payload) {
12
+ const message = payload.message;
13
+ if (!isRecord(message)) {
14
+ throw new Error("Invalid chat payload envelope: missing message");
15
+ }
16
+ const role = message.role;
17
+ const parts = message.parts;
18
+ if (role !== "system" && role !== "user" && role !== "assistant") {
19
+ throw new Error("Invalid chat payload envelope: invalid message role");
20
+ }
21
+ if (!Array.isArray(parts)) {
22
+ throw new Error("Invalid chat payload envelope: invalid message parts");
23
+ }
24
+ return {
25
+ ...payload,
26
+ kind: chatUserMessageEventType,
27
+ message: {
28
+ ...message,
29
+ role,
30
+ parts
31
+ }
32
+ };
33
+ }
34
+ function parseAssistantEnvelope(payload) {
35
+ const chunk = payload.chunk;
36
+ if (!isRecord(chunk)) {
37
+ throw new Error("Invalid chat payload envelope: missing chunk");
38
+ }
39
+ const type = chunk.type;
40
+ if (typeof type !== "string" || type.length === 0) {
41
+ throw new Error("Invalid chat payload envelope: invalid chunk type");
42
+ }
43
+ return {
44
+ ...payload,
45
+ kind: chatAssistantChunkEventType,
46
+ chunk: {
47
+ ...chunk,
48
+ type
49
+ }
50
+ };
51
+ }
52
+ function createUserMessageEnvelope(message) {
53
+ return {
54
+ kind: chatUserMessageEventType,
55
+ message
56
+ };
57
+ }
58
+ function createAssistantChunkEnvelope(chunk) {
59
+ return {
60
+ kind: chatAssistantChunkEventType,
61
+ chunk
62
+ };
63
+ }
64
+ function parseChatPayloadEnvelope(payload) {
65
+ if (!isRecord(payload)) {
66
+ throw new Error("Invalid chat payload envelope: payload must be an object");
67
+ }
68
+ const kind = payload.kind;
69
+ if (kind === chatUserMessageEventType) {
70
+ return parseUserEnvelope(payload);
71
+ }
72
+ if (kind === chatAssistantChunkEventType) {
73
+ return parseAssistantEnvelope(payload);
74
+ }
75
+ throw new Error("Invalid chat payload envelope: unknown kind");
76
+ }
77
+ function appendUserMessageEvent(session, message, options = {}) {
78
+ return session.append({
79
+ type: chatUserMessageEventType,
80
+ source: options.source ?? "use-chat",
81
+ payload: createUserMessageEnvelope(message)
82
+ });
83
+ }
84
+ function appendAssistantChunkEvent(session, chunk, options = {}) {
85
+ return session.append({
86
+ type: chatAssistantChunkEventType,
87
+ source: options.source ?? "openai",
88
+ payload: createAssistantChunkEnvelope(chunk)
89
+ });
90
+ }
91
+ async function buildChunkMessages(chunks) {
92
+ if (chunks.length === 0) {
93
+ return [];
94
+ }
95
+ const messageIds = [];
96
+ const latestById = /* @__PURE__ */ new Map();
97
+ let index = 0;
98
+ const stream = new ReadableStream({
99
+ pull(controller) {
100
+ const chunk = chunks[index];
101
+ if (!chunk) {
102
+ controller.close();
103
+ return;
104
+ }
105
+ controller.enqueue(chunk);
106
+ index += 1;
107
+ }
108
+ });
109
+ try {
110
+ for await (const message of readUIMessageStream({
111
+ stream,
112
+ terminateOnError: false
113
+ })) {
114
+ if (!latestById.has(message.id)) {
115
+ messageIds.push(message.id);
116
+ }
117
+ latestById.set(message.id, message);
118
+ }
119
+ } catch {
120
+ }
121
+ const messages = [];
122
+ for (const messageId of messageIds) {
123
+ const message = latestById.get(messageId);
124
+ if (message) {
125
+ messages.push(message);
126
+ }
127
+ }
128
+ return messages;
129
+ }
130
+ async function toUIMessagesFromEvents(events) {
131
+ const messages = [];
132
+ const bufferedChunks = [];
133
+ const flushBufferedChunks = async () => {
134
+ if (bufferedChunks.length === 0) {
135
+ return;
136
+ }
137
+ messages.push(...await buildChunkMessages(bufferedChunks));
138
+ bufferedChunks.length = 0;
139
+ };
140
+ for (const event of events) {
141
+ if (!isChatEventType(event.type)) {
142
+ continue;
143
+ }
144
+ let envelope;
145
+ try {
146
+ envelope = parseChatPayloadEnvelope(event.payload);
147
+ } catch {
148
+ continue;
149
+ }
150
+ if (envelope.kind === chatUserMessageEventType) {
151
+ await flushBufferedChunks();
152
+ messages.push(envelope.message);
153
+ continue;
154
+ }
155
+ bufferedChunks.push(envelope.chunk);
156
+ }
157
+ await flushBufferedChunks();
158
+ return messages;
159
+ }
160
+
161
+ export {
162
+ chatUserMessageEventType,
163
+ chatAssistantChunkEventType,
164
+ createUserMessageEnvelope,
165
+ createAssistantChunkEnvelope,
166
+ parseChatPayloadEnvelope,
167
+ appendUserMessageEvent,
168
+ appendAssistantChunkEvent,
169
+ toUIMessagesFromEvents
170
+ };
171
+ //# sourceMappingURL=chunk-QG237Z3K.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/chat-protocol.ts"],"sourcesContent":["import type { AppendResult, SessionAppendInput } from \"@starcite/sdk\";\nimport { readUIMessageStream, type UIMessage, type UIMessageChunk } from \"ai\";\n\nexport const chatUserMessageEventType = \"chat.user.message\";\nexport const chatAssistantChunkEventType = \"chat.assistant.chunk\";\n\ntype ChatRole = \"system\" | \"user\" | \"assistant\";\n\ninterface ChatUserMessagePayload {\n role: ChatRole;\n parts: unknown[];\n [key: string]: unknown;\n}\n\ninterface ChatAssistantChunkPayload {\n type: string;\n [key: string]: unknown;\n}\n\nexport type ChatPayloadEnvelope =\n | {\n kind: typeof chatUserMessageEventType;\n message: ChatUserMessagePayload;\n [key: string]: unknown;\n }\n | {\n kind: typeof chatAssistantChunkEventType;\n chunk: ChatAssistantChunkPayload;\n [key: string]: unknown;\n };\n\ninterface SessionAppender {\n append: (input: SessionAppendInput) => Promise<AppendResult>;\n}\n\nfunction isChatEventType(type: string): boolean {\n return (\n type === chatUserMessageEventType || type === chatAssistantChunkEventType\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction parseUserEnvelope(\n payload: Record<string, unknown>\n): ChatPayloadEnvelope {\n const message = payload.message;\n if (!isRecord(message)) {\n throw new Error(\"Invalid chat payload envelope: missing message\");\n }\n\n const role = message.role;\n const parts = message.parts;\n\n if (role !== \"system\" && role !== \"user\" && role !== \"assistant\") {\n throw new Error(\"Invalid chat payload envelope: invalid message role\");\n }\n\n if (!Array.isArray(parts)) {\n throw new Error(\"Invalid chat payload envelope: invalid message parts\");\n }\n\n return {\n ...payload,\n kind: chatUserMessageEventType,\n message: {\n ...message,\n role,\n parts,\n },\n };\n}\n\nfunction parseAssistantEnvelope(\n payload: Record<string, unknown>\n): ChatPayloadEnvelope {\n const chunk = payload.chunk;\n if (!isRecord(chunk)) {\n throw new Error(\"Invalid chat payload envelope: missing chunk\");\n }\n\n const type = chunk.type;\n if (typeof type !== \"string\" || type.length === 0) {\n throw new Error(\"Invalid chat payload envelope: invalid chunk type\");\n }\n\n return {\n ...payload,\n kind: chatAssistantChunkEventType,\n chunk: {\n ...chunk,\n type,\n },\n };\n}\n\nexport function createUserMessageEnvelope<\n TMessage extends Record<string, unknown>,\n>(\n message: TMessage\n): {\n kind: typeof chatUserMessageEventType;\n message: TMessage;\n} {\n return {\n kind: chatUserMessageEventType,\n message,\n };\n}\n\nexport function createAssistantChunkEnvelope<\n TChunk extends Record<string, unknown>,\n>(\n chunk: TChunk\n): {\n kind: typeof chatAssistantChunkEventType;\n chunk: TChunk;\n} {\n return {\n kind: chatAssistantChunkEventType,\n chunk,\n };\n}\n\nexport function parseChatPayloadEnvelope(\n payload: unknown\n): ChatPayloadEnvelope {\n if (!isRecord(payload)) {\n throw new Error(\"Invalid chat payload envelope: payload must be an object\");\n }\n\n const kind = payload.kind;\n if (kind === chatUserMessageEventType) {\n return parseUserEnvelope(payload);\n }\n\n if (kind === chatAssistantChunkEventType) {\n return parseAssistantEnvelope(payload);\n }\n\n throw new Error(\"Invalid chat payload envelope: unknown kind\");\n}\n\nexport function appendUserMessageEvent(\n session: SessionAppender,\n message: Record<string, unknown>,\n options: { source?: string } = {}\n): Promise<AppendResult> {\n return session.append({\n type: chatUserMessageEventType,\n source: options.source ?? \"use-chat\",\n payload: createUserMessageEnvelope(message),\n });\n}\n\nexport function appendAssistantChunkEvent(\n session: SessionAppender,\n chunk: Record<string, unknown>,\n options: { source?: string } = {}\n): Promise<AppendResult> {\n return session.append({\n type: chatAssistantChunkEventType,\n source: options.source ?? \"openai\",\n payload: createAssistantChunkEnvelope(chunk),\n });\n}\n\nasync function buildChunkMessages(\n chunks: readonly UIMessageChunk[]\n): Promise<UIMessage[]> {\n if (chunks.length === 0) {\n return [];\n }\n\n const messageIds: string[] = [];\n const latestById = new Map<string, UIMessage>();\n let index = 0;\n\n const stream = new ReadableStream<UIMessageChunk>({\n pull(controller) {\n const chunk = chunks[index];\n if (!chunk) {\n controller.close();\n return;\n }\n\n controller.enqueue(chunk);\n index += 1;\n },\n });\n\n try {\n for await (const message of readUIMessageStream({\n stream,\n terminateOnError: false,\n })) {\n if (!latestById.has(message.id)) {\n messageIds.push(message.id);\n }\n\n latestById.set(message.id, message);\n }\n } catch {\n // Best effort: keep messages emitted before malformed chunk sequences.\n }\n\n const messages: UIMessage[] = [];\n for (const messageId of messageIds) {\n const message = latestById.get(messageId);\n if (message) {\n messages.push(message);\n }\n }\n\n return messages;\n}\n\nexport async function toUIMessagesFromEvents(\n events: readonly { type: string; payload: unknown }[]\n): Promise<UIMessage[]> {\n const messages: UIMessage[] = [];\n const bufferedChunks: UIMessageChunk[] = [];\n\n const flushBufferedChunks = async (): Promise<void> => {\n if (bufferedChunks.length === 0) {\n return;\n }\n\n messages.push(...(await buildChunkMessages(bufferedChunks)));\n bufferedChunks.length = 0;\n };\n\n for (const event of events) {\n if (!isChatEventType(event.type)) {\n continue;\n }\n\n let envelope: ChatPayloadEnvelope;\n try {\n envelope = parseChatPayloadEnvelope(event.payload);\n } catch {\n // Skip malformed chat payloads and continue projecting the rest.\n continue;\n }\n\n if (envelope.kind === chatUserMessageEventType) {\n await flushBufferedChunks();\n messages.push(envelope.message as unknown as UIMessage);\n continue;\n }\n\n bufferedChunks.push(envelope.chunk as unknown as UIMessageChunk);\n }\n\n await flushBufferedChunks();\n return messages;\n}\n"],"mappings":"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","names":[]}
package/dist/index.cjs ADDED
@@ -0,0 +1,383 @@
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
+ useStarciteChat: () => useStarciteChat
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/use-starcite-chat.ts
28
+ var import_react = require("react");
29
+
30
+ // src/chat-protocol.ts
31
+ var import_ai = require("ai");
32
+ var chatUserMessageEventType = "chat.user.message";
33
+ var chatAssistantChunkEventType = "chat.assistant.chunk";
34
+ function isChatEventType(type) {
35
+ return type === chatUserMessageEventType || type === chatAssistantChunkEventType;
36
+ }
37
+ function isRecord(value) {
38
+ return typeof value === "object" && value !== null;
39
+ }
40
+ function parseUserEnvelope(payload) {
41
+ const message = payload.message;
42
+ if (!isRecord(message)) {
43
+ throw new Error("Invalid chat payload envelope: missing message");
44
+ }
45
+ const role = message.role;
46
+ const parts = message.parts;
47
+ if (role !== "system" && role !== "user" && role !== "assistant") {
48
+ throw new Error("Invalid chat payload envelope: invalid message role");
49
+ }
50
+ if (!Array.isArray(parts)) {
51
+ throw new Error("Invalid chat payload envelope: invalid message parts");
52
+ }
53
+ return {
54
+ ...payload,
55
+ kind: chatUserMessageEventType,
56
+ message: {
57
+ ...message,
58
+ role,
59
+ parts
60
+ }
61
+ };
62
+ }
63
+ function parseAssistantEnvelope(payload) {
64
+ const chunk = payload.chunk;
65
+ if (!isRecord(chunk)) {
66
+ throw new Error("Invalid chat payload envelope: missing chunk");
67
+ }
68
+ const type = chunk.type;
69
+ if (typeof type !== "string" || type.length === 0) {
70
+ throw new Error("Invalid chat payload envelope: invalid chunk type");
71
+ }
72
+ return {
73
+ ...payload,
74
+ kind: chatAssistantChunkEventType,
75
+ chunk: {
76
+ ...chunk,
77
+ type
78
+ }
79
+ };
80
+ }
81
+ function createUserMessageEnvelope(message) {
82
+ return {
83
+ kind: chatUserMessageEventType,
84
+ message
85
+ };
86
+ }
87
+ function parseChatPayloadEnvelope(payload) {
88
+ if (!isRecord(payload)) {
89
+ throw new Error("Invalid chat payload envelope: payload must be an object");
90
+ }
91
+ const kind = payload.kind;
92
+ if (kind === chatUserMessageEventType) {
93
+ return parseUserEnvelope(payload);
94
+ }
95
+ if (kind === chatAssistantChunkEventType) {
96
+ return parseAssistantEnvelope(payload);
97
+ }
98
+ throw new Error("Invalid chat payload envelope: unknown kind");
99
+ }
100
+ function appendUserMessageEvent(session, message, options = {}) {
101
+ return session.append({
102
+ type: chatUserMessageEventType,
103
+ source: options.source ?? "use-chat",
104
+ payload: createUserMessageEnvelope(message)
105
+ });
106
+ }
107
+ async function buildChunkMessages(chunks) {
108
+ if (chunks.length === 0) {
109
+ return [];
110
+ }
111
+ const messageIds = [];
112
+ const latestById = /* @__PURE__ */ new Map();
113
+ let index = 0;
114
+ const stream = new ReadableStream({
115
+ pull(controller) {
116
+ const chunk = chunks[index];
117
+ if (!chunk) {
118
+ controller.close();
119
+ return;
120
+ }
121
+ controller.enqueue(chunk);
122
+ index += 1;
123
+ }
124
+ });
125
+ try {
126
+ for await (const message of (0, import_ai.readUIMessageStream)({
127
+ stream,
128
+ terminateOnError: false
129
+ })) {
130
+ if (!latestById.has(message.id)) {
131
+ messageIds.push(message.id);
132
+ }
133
+ latestById.set(message.id, message);
134
+ }
135
+ } catch {
136
+ }
137
+ const messages = [];
138
+ for (const messageId of messageIds) {
139
+ const message = latestById.get(messageId);
140
+ if (message) {
141
+ messages.push(message);
142
+ }
143
+ }
144
+ return messages;
145
+ }
146
+ async function toUIMessagesFromEvents(events) {
147
+ const messages = [];
148
+ const bufferedChunks = [];
149
+ const flushBufferedChunks = async () => {
150
+ if (bufferedChunks.length === 0) {
151
+ return;
152
+ }
153
+ messages.push(...await buildChunkMessages(bufferedChunks));
154
+ bufferedChunks.length = 0;
155
+ };
156
+ for (const event of events) {
157
+ if (!isChatEventType(event.type)) {
158
+ continue;
159
+ }
160
+ let envelope;
161
+ try {
162
+ envelope = parseChatPayloadEnvelope(event.payload);
163
+ } catch {
164
+ continue;
165
+ }
166
+ if (envelope.kind === chatUserMessageEventType) {
167
+ await flushBufferedChunks();
168
+ messages.push(envelope.message);
169
+ continue;
170
+ }
171
+ bufferedChunks.push(envelope.chunk);
172
+ }
173
+ await flushBufferedChunks();
174
+ return messages;
175
+ }
176
+
177
+ // src/use-starcite-chat.ts
178
+ function createMessageId() {
179
+ if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
180
+ return crypto.randomUUID();
181
+ }
182
+ return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
183
+ }
184
+ function isChatEventType2(type) {
185
+ return type === chatUserMessageEventType || type === chatAssistantChunkEventType;
186
+ }
187
+ function isTerminalAssistantChunkType(type) {
188
+ return type === "finish" || type === "abort";
189
+ }
190
+ function isRecord2(value) {
191
+ return typeof value === "object" && value !== null;
192
+ }
193
+ function readAssistantChunkType(payload) {
194
+ if (!isRecord2(payload) || payload.kind !== chatAssistantChunkEventType) {
195
+ return void 0;
196
+ }
197
+ const chunk = payload.chunk;
198
+ if (!isRecord2(chunk)) {
199
+ return void 0;
200
+ }
201
+ return typeof chunk.type === "string" ? chunk.type : void 0;
202
+ }
203
+ function hasTextInput(message) {
204
+ return "text" in message && !("parts" in message);
205
+ }
206
+ function normalizeOutgoingMessage(input) {
207
+ if (hasTextInput(input)) {
208
+ return {
209
+ id: createMessageId(),
210
+ role: "user",
211
+ parts: [{ type: "text", text: input.text }]
212
+ };
213
+ }
214
+ return {
215
+ ...input,
216
+ id: input.id ?? createMessageId()
217
+ };
218
+ }
219
+ function normalizeError(error) {
220
+ if (error instanceof Error) {
221
+ return error;
222
+ }
223
+ return new Error(String(error));
224
+ }
225
+ async function readChatState(events) {
226
+ const messages = await toUIMessagesFromEvents(events);
227
+ let assistantOpen = false;
228
+ for (let index = events.length - 1; index >= 0; index -= 1) {
229
+ const event = events[index];
230
+ if (!event || event.type !== chatAssistantChunkEventType) {
231
+ continue;
232
+ }
233
+ const chunkType = readAssistantChunkType(event.payload);
234
+ if (!chunkType) {
235
+ break;
236
+ }
237
+ assistantOpen = !isTerminalAssistantChunkType(chunkType);
238
+ break;
239
+ }
240
+ return {
241
+ messages,
242
+ assistantOpen
243
+ };
244
+ }
245
+ function useStarciteChat(options) {
246
+ const { session, id, userMessageSource = "use-chat", onError } = options;
247
+ const sessionResetKey = id ?? session.id;
248
+ const [messages, setMessages] = (0, import_react.useState)([]);
249
+ const [status, setStatus] = (0, import_react.useState)("ready");
250
+ const refreshVersionRef = (0, import_react.useRef)(0);
251
+ const sessionKeyRef = (0, import_react.useRef)(sessionResetKey);
252
+ const onErrorRef = (0, import_react.useRef)(onError);
253
+ const liveRefreshScheduledRef = (0, import_react.useRef)(false);
254
+ const replayRefreshTimeoutRef = (0, import_react.useRef)(
255
+ null
256
+ );
257
+ (0, import_react.useEffect)(() => {
258
+ onErrorRef.current = onError;
259
+ }, [onError]);
260
+ const reportError = (0, import_react.useCallback)((error) => {
261
+ const normalized = normalizeError(error);
262
+ setStatus("error");
263
+ onErrorRef.current?.(normalized);
264
+ return normalized;
265
+ }, []);
266
+ const refreshFromSession = (0, import_react.useCallback)(() => {
267
+ const version = refreshVersionRef.current + 1;
268
+ refreshVersionRef.current = version;
269
+ const snapshot = [...session.events()];
270
+ readChatState(snapshot).then((chatState) => {
271
+ if (refreshVersionRef.current !== version) {
272
+ return;
273
+ }
274
+ setMessages(chatState.messages);
275
+ setStatus((current) => {
276
+ if (chatState.assistantOpen) {
277
+ return "streaming";
278
+ }
279
+ return current === "submitted" ? "submitted" : "ready";
280
+ });
281
+ }).catch((error) => {
282
+ reportError(error);
283
+ });
284
+ }, [reportError, session]);
285
+ const scheduleLiveRefreshFromSession = (0, import_react.useCallback)(() => {
286
+ if (liveRefreshScheduledRef.current) {
287
+ return;
288
+ }
289
+ liveRefreshScheduledRef.current = true;
290
+ setTimeout(() => {
291
+ liveRefreshScheduledRef.current = false;
292
+ refreshFromSession();
293
+ }, 16);
294
+ }, [refreshFromSession]);
295
+ const scheduleReplayRefreshFromSession = (0, import_react.useCallback)(() => {
296
+ if (replayRefreshTimeoutRef.current !== null) {
297
+ clearTimeout(replayRefreshTimeoutRef.current);
298
+ }
299
+ replayRefreshTimeoutRef.current = setTimeout(() => {
300
+ replayRefreshTimeoutRef.current = null;
301
+ refreshFromSession();
302
+ }, 120);
303
+ }, [refreshFromSession]);
304
+ const sendMessage = (0, import_react.useCallback)(
305
+ async (message) => {
306
+ const requestSessionKey = sessionKeyRef.current;
307
+ const outgoingMessage = normalizeOutgoingMessage(message);
308
+ setStatus("submitted");
309
+ try {
310
+ await appendUserMessageEvent(
311
+ session,
312
+ outgoingMessage,
313
+ {
314
+ source: userMessageSource
315
+ }
316
+ );
317
+ if (sessionKeyRef.current !== requestSessionKey) {
318
+ return;
319
+ }
320
+ refreshFromSession();
321
+ } catch (error) {
322
+ refreshVersionRef.current += 1;
323
+ throw reportError(error);
324
+ }
325
+ },
326
+ [refreshFromSession, reportError, session, userMessageSource]
327
+ );
328
+ const onSessionEvent = (0, import_react.useCallback)(
329
+ (event, context) => {
330
+ if (!isChatEventType2(event.type)) {
331
+ return;
332
+ }
333
+ if (!context?.replayed && event.type === chatAssistantChunkEventType) {
334
+ const chunkType = readAssistantChunkType(event.payload);
335
+ if (chunkType && isTerminalAssistantChunkType(chunkType)) {
336
+ setStatus("ready");
337
+ } else {
338
+ setStatus("streaming");
339
+ }
340
+ }
341
+ if (context?.replayed) {
342
+ scheduleReplayRefreshFromSession();
343
+ } else {
344
+ scheduleLiveRefreshFromSession();
345
+ }
346
+ },
347
+ [scheduleLiveRefreshFromSession, scheduleReplayRefreshFromSession]
348
+ );
349
+ (0, import_react.useEffect)(() => {
350
+ sessionKeyRef.current = sessionResetKey;
351
+ refreshVersionRef.current += 1;
352
+ setMessages([]);
353
+ setStatus("ready");
354
+ refreshFromSession();
355
+ const offEvent = session.on("event", onSessionEvent, { replay: false });
356
+ const offError = session.on("error", (error) => {
357
+ onErrorRef.current?.(normalizeError(error));
358
+ });
359
+ return () => {
360
+ refreshVersionRef.current += 1;
361
+ liveRefreshScheduledRef.current = false;
362
+ if (replayRefreshTimeoutRef.current !== null) {
363
+ clearTimeout(replayRefreshTimeoutRef.current);
364
+ replayRefreshTimeoutRef.current = null;
365
+ }
366
+ offEvent();
367
+ offError();
368
+ };
369
+ }, [onSessionEvent, refreshFromSession, session, sessionResetKey]);
370
+ return (0, import_react.useMemo)(
371
+ () => ({
372
+ messages,
373
+ sendMessage,
374
+ status
375
+ }),
376
+ [messages, sendMessage, status]
377
+ );
378
+ }
379
+ // Annotate the CommonJS export names for ESM import in node:
380
+ 0 && (module.exports = {
381
+ useStarciteChat
382
+ });
383
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/use-starcite-chat.ts","../src/chat-protocol.ts"],"sourcesContent":["/* biome-ignore-all lint/performance/noBarrelFile: package entrypoint intentionally re-exports public API. */\nexport type {\n SendMessageInput,\n StarciteChatSession,\n UseStarciteChatOptions,\n UseStarciteChatResult,\n} from \"./use-starcite-chat\";\nexport { useStarciteChat } from \"./use-starcite-chat\";\n","import type {\n AppendResult,\n SessionAppendInput,\n SessionEvent,\n SessionEventListener,\n SessionOnEventOptions,\n} from \"@starcite/sdk\";\nimport type { ChatStatus, UIMessage } from \"ai\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n appendUserMessageEvent,\n chatAssistantChunkEventType,\n chatUserMessageEventType,\n toUIMessagesFromEvents,\n} from \"./chat-protocol\";\n\nexport interface StarciteChatSession {\n readonly id: string;\n append(input: SessionAppendInput): Promise<AppendResult>;\n events(): readonly SessionEvent[];\n on(\n eventName: \"event\",\n listener: SessionEventListener,\n options?: SessionOnEventOptions<SessionEvent>\n ): () => void;\n on(eventName: \"error\", listener: (error: Error) => void): () => void;\n}\n\nexport type SendMessageInput =\n | {\n text: string;\n }\n | (Omit<UIMessage, \"id\"> & { id?: string });\n\nexport interface UseStarciteChatOptions {\n session: StarciteChatSession;\n id?: string;\n userMessageSource?: string;\n onError?: (error: Error) => void;\n}\n\nexport interface UseStarciteChatResult {\n messages: UIMessage[];\n sendMessage: (message: SendMessageInput) => Promise<void>;\n status: ChatStatus;\n}\n\ninterface ChatStateSnapshot {\n messages: UIMessage[];\n assistantOpen: boolean;\n}\n\nfunction createMessageId(): string {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n\n return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction isChatEventType(type: string): boolean {\n return (\n type === chatUserMessageEventType || type === chatAssistantChunkEventType\n );\n}\n\nfunction isTerminalAssistantChunkType(type: string): boolean {\n return type === \"finish\" || type === \"abort\";\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction readAssistantChunkType(payload: unknown): string | undefined {\n if (!isRecord(payload) || payload.kind !== chatAssistantChunkEventType) {\n return undefined;\n }\n\n const chunk = payload.chunk;\n if (!isRecord(chunk)) {\n return undefined;\n }\n\n return typeof chunk.type === \"string\" ? chunk.type : undefined;\n}\n\nfunction hasTextInput(message: SendMessageInput): message is { text: string } {\n return \"text\" in message && !(\"parts\" in message);\n}\n\nfunction normalizeOutgoingMessage(input: SendMessageInput): UIMessage {\n if (hasTextInput(input)) {\n return {\n id: createMessageId(),\n role: \"user\",\n parts: [{ type: \"text\", text: input.text }],\n };\n }\n\n return {\n ...input,\n id: input.id ?? createMessageId(),\n };\n}\n\nfunction normalizeError(error: unknown): Error {\n if (error instanceof Error) {\n return error;\n }\n\n return new Error(String(error));\n}\n\nasync function readChatState(\n events: readonly SessionEvent[]\n): Promise<ChatStateSnapshot> {\n const messages = await toUIMessagesFromEvents(events);\n let assistantOpen = false;\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index];\n if (!event || event.type !== chatAssistantChunkEventType) {\n continue;\n }\n\n const chunkType = readAssistantChunkType(event.payload);\n if (!chunkType) {\n break;\n }\n\n assistantOpen = !isTerminalAssistantChunkType(chunkType);\n break;\n }\n\n return {\n messages,\n assistantOpen,\n };\n}\n\nexport function useStarciteChat(\n options: UseStarciteChatOptions\n): UseStarciteChatResult {\n const { session, id, userMessageSource = \"use-chat\", onError } = options;\n\n const sessionResetKey = id ?? session.id;\n\n const [messages, setMessages] = useState<UIMessage[]>([]);\n const [status, setStatus] = useState<ChatStatus>(\"ready\");\n\n const refreshVersionRef = useRef(0);\n const sessionKeyRef = useRef(sessionResetKey);\n const onErrorRef = useRef(onError);\n const liveRefreshScheduledRef = useRef(false);\n const replayRefreshTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(\n null\n );\n\n useEffect(() => {\n onErrorRef.current = onError;\n }, [onError]);\n\n const reportError = useCallback((error: unknown): Error => {\n const normalized = normalizeError(error);\n setStatus(\"error\");\n onErrorRef.current?.(normalized);\n return normalized;\n }, []);\n\n const refreshFromSession = useCallback(() => {\n const version = refreshVersionRef.current + 1;\n refreshVersionRef.current = version;\n\n const snapshot = [...session.events()];\n\n readChatState(snapshot)\n .then((chatState) => {\n if (refreshVersionRef.current !== version) {\n return;\n }\n\n setMessages(chatState.messages);\n setStatus((current) => {\n if (chatState.assistantOpen) {\n return \"streaming\";\n }\n\n return current === \"submitted\" ? \"submitted\" : \"ready\";\n });\n })\n .catch((error) => {\n reportError(error);\n });\n }, [reportError, session]);\n\n const scheduleLiveRefreshFromSession = useCallback(() => {\n if (liveRefreshScheduledRef.current) {\n return;\n }\n\n liveRefreshScheduledRef.current = true;\n setTimeout(() => {\n liveRefreshScheduledRef.current = false;\n refreshFromSession();\n }, 16);\n }, [refreshFromSession]);\n\n const scheduleReplayRefreshFromSession = useCallback(() => {\n if (replayRefreshTimeoutRef.current !== null) {\n clearTimeout(replayRefreshTimeoutRef.current);\n }\n\n replayRefreshTimeoutRef.current = setTimeout(() => {\n replayRefreshTimeoutRef.current = null;\n refreshFromSession();\n }, 120);\n }, [refreshFromSession]);\n\n const sendMessage = useCallback(\n async (message: SendMessageInput): Promise<void> => {\n const requestSessionKey = sessionKeyRef.current;\n const outgoingMessage = normalizeOutgoingMessage(message);\n\n setStatus(\"submitted\");\n\n try {\n await appendUserMessageEvent(\n session,\n outgoingMessage as unknown as Record<string, unknown>,\n {\n source: userMessageSource,\n }\n );\n\n if (sessionKeyRef.current !== requestSessionKey) {\n return;\n }\n\n refreshFromSession();\n } catch (error) {\n refreshVersionRef.current += 1;\n throw reportError(error);\n }\n },\n [refreshFromSession, reportError, session, userMessageSource]\n );\n\n const onSessionEvent = useCallback(\n (event: SessionEvent, context?: { replayed: boolean }): void => {\n if (!isChatEventType(event.type)) {\n return;\n }\n\n if (!context?.replayed && event.type === chatAssistantChunkEventType) {\n const chunkType = readAssistantChunkType(event.payload);\n if (chunkType && isTerminalAssistantChunkType(chunkType)) {\n setStatus(\"ready\");\n } else {\n setStatus(\"streaming\");\n }\n }\n\n if (context?.replayed) {\n scheduleReplayRefreshFromSession();\n } else {\n scheduleLiveRefreshFromSession();\n }\n },\n [scheduleLiveRefreshFromSession, scheduleReplayRefreshFromSession]\n );\n\n useEffect(() => {\n sessionKeyRef.current = sessionResetKey;\n refreshVersionRef.current += 1;\n setMessages([]);\n setStatus(\"ready\");\n\n refreshFromSession();\n\n const offEvent = session.on(\"event\", onSessionEvent, { replay: false });\n const offError = session.on(\"error\", (error) => {\n onErrorRef.current?.(normalizeError(error));\n });\n\n return () => {\n refreshVersionRef.current += 1;\n\n liveRefreshScheduledRef.current = false;\n if (replayRefreshTimeoutRef.current !== null) {\n clearTimeout(replayRefreshTimeoutRef.current);\n replayRefreshTimeoutRef.current = null;\n }\n\n offEvent();\n offError();\n };\n }, [onSessionEvent, refreshFromSession, session, sessionResetKey]);\n\n return useMemo(\n () => ({\n messages,\n sendMessage,\n status,\n }),\n [messages, sendMessage, status]\n );\n}\n","import type { AppendResult, SessionAppendInput } from \"@starcite/sdk\";\nimport { readUIMessageStream, type UIMessage, type UIMessageChunk } from \"ai\";\n\nexport const chatUserMessageEventType = \"chat.user.message\";\nexport const chatAssistantChunkEventType = \"chat.assistant.chunk\";\n\ntype ChatRole = \"system\" | \"user\" | \"assistant\";\n\ninterface ChatUserMessagePayload {\n role: ChatRole;\n parts: unknown[];\n [key: string]: unknown;\n}\n\ninterface ChatAssistantChunkPayload {\n type: string;\n [key: string]: unknown;\n}\n\nexport type ChatPayloadEnvelope =\n | {\n kind: typeof chatUserMessageEventType;\n message: ChatUserMessagePayload;\n [key: string]: unknown;\n }\n | {\n kind: typeof chatAssistantChunkEventType;\n chunk: ChatAssistantChunkPayload;\n [key: string]: unknown;\n };\n\ninterface SessionAppender {\n append: (input: SessionAppendInput) => Promise<AppendResult>;\n}\n\nfunction isChatEventType(type: string): boolean {\n return (\n type === chatUserMessageEventType || type === chatAssistantChunkEventType\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction parseUserEnvelope(\n payload: Record<string, unknown>\n): ChatPayloadEnvelope {\n const message = payload.message;\n if (!isRecord(message)) {\n throw new Error(\"Invalid chat payload envelope: missing message\");\n }\n\n const role = message.role;\n const parts = message.parts;\n\n if (role !== \"system\" && role !== \"user\" && role !== \"assistant\") {\n throw new Error(\"Invalid chat payload envelope: invalid message role\");\n }\n\n if (!Array.isArray(parts)) {\n throw new Error(\"Invalid chat payload envelope: invalid message parts\");\n }\n\n return {\n ...payload,\n kind: chatUserMessageEventType,\n message: {\n ...message,\n role,\n parts,\n },\n };\n}\n\nfunction parseAssistantEnvelope(\n payload: Record<string, unknown>\n): ChatPayloadEnvelope {\n const chunk = payload.chunk;\n if (!isRecord(chunk)) {\n throw new Error(\"Invalid chat payload envelope: missing chunk\");\n }\n\n const type = chunk.type;\n if (typeof type !== \"string\" || type.length === 0) {\n throw new Error(\"Invalid chat payload envelope: invalid chunk type\");\n }\n\n return {\n ...payload,\n kind: chatAssistantChunkEventType,\n chunk: {\n ...chunk,\n type,\n },\n };\n}\n\nexport function createUserMessageEnvelope<\n TMessage extends Record<string, unknown>,\n>(\n message: TMessage\n): {\n kind: typeof chatUserMessageEventType;\n message: TMessage;\n} {\n return {\n kind: chatUserMessageEventType,\n message,\n };\n}\n\nexport function createAssistantChunkEnvelope<\n TChunk extends Record<string, unknown>,\n>(\n chunk: TChunk\n): {\n kind: typeof chatAssistantChunkEventType;\n chunk: TChunk;\n} {\n return {\n kind: chatAssistantChunkEventType,\n chunk,\n };\n}\n\nexport function parseChatPayloadEnvelope(\n payload: unknown\n): ChatPayloadEnvelope {\n if (!isRecord(payload)) {\n throw new Error(\"Invalid chat payload envelope: payload must be an object\");\n }\n\n const kind = payload.kind;\n if (kind === chatUserMessageEventType) {\n return parseUserEnvelope(payload);\n }\n\n if (kind === chatAssistantChunkEventType) {\n return parseAssistantEnvelope(payload);\n }\n\n throw new Error(\"Invalid chat payload envelope: unknown kind\");\n}\n\nexport function appendUserMessageEvent(\n session: SessionAppender,\n message: Record<string, unknown>,\n options: { source?: string } = {}\n): Promise<AppendResult> {\n return session.append({\n type: chatUserMessageEventType,\n source: options.source ?? \"use-chat\",\n payload: createUserMessageEnvelope(message),\n });\n}\n\nexport function appendAssistantChunkEvent(\n session: SessionAppender,\n chunk: Record<string, unknown>,\n options: { source?: string } = {}\n): Promise<AppendResult> {\n return session.append({\n type: chatAssistantChunkEventType,\n source: options.source ?? \"openai\",\n payload: createAssistantChunkEnvelope(chunk),\n });\n}\n\nasync function buildChunkMessages(\n chunks: readonly UIMessageChunk[]\n): Promise<UIMessage[]> {\n if (chunks.length === 0) {\n return [];\n }\n\n const messageIds: string[] = [];\n const latestById = new Map<string, UIMessage>();\n let index = 0;\n\n const stream = new ReadableStream<UIMessageChunk>({\n pull(controller) {\n const chunk = chunks[index];\n if (!chunk) {\n controller.close();\n return;\n }\n\n controller.enqueue(chunk);\n index += 1;\n },\n });\n\n try {\n for await (const message of readUIMessageStream({\n stream,\n terminateOnError: false,\n })) {\n if (!latestById.has(message.id)) {\n messageIds.push(message.id);\n }\n\n latestById.set(message.id, message);\n }\n } catch {\n // Best effort: keep messages emitted before malformed chunk sequences.\n }\n\n const messages: UIMessage[] = [];\n for (const messageId of messageIds) {\n const message = latestById.get(messageId);\n if (message) {\n messages.push(message);\n }\n }\n\n return messages;\n}\n\nexport async function toUIMessagesFromEvents(\n events: readonly { type: string; payload: unknown }[]\n): Promise<UIMessage[]> {\n const messages: UIMessage[] = [];\n const bufferedChunks: UIMessageChunk[] = [];\n\n const flushBufferedChunks = async (): Promise<void> => {\n if (bufferedChunks.length === 0) {\n return;\n }\n\n messages.push(...(await buildChunkMessages(bufferedChunks)));\n bufferedChunks.length = 0;\n };\n\n for (const event of events) {\n if (!isChatEventType(event.type)) {\n continue;\n }\n\n let envelope: ChatPayloadEnvelope;\n try {\n envelope = parseChatPayloadEnvelope(event.payload);\n } catch {\n // Skip malformed chat payloads and continue projecting the rest.\n continue;\n }\n\n if (envelope.kind === chatUserMessageEventType) {\n await flushBufferedChunks();\n messages.push(envelope.message as unknown as UIMessage);\n continue;\n }\n\n bufferedChunks.push(envelope.chunk as unknown as UIMessageChunk);\n }\n\n await flushBufferedChunks();\n return messages;\n}\n"],"mappings":"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","names":["isChatEventType","isRecord"]}
@@ -0,0 +1,29 @@
1
+ import { SessionAppendInput, AppendResult, SessionEvent, SessionEventListener, SessionOnEventOptions } from '@starcite/sdk';
2
+ import { UIMessage, ChatStatus } from 'ai';
3
+
4
+ interface StarciteChatSession {
5
+ readonly id: string;
6
+ append(input: SessionAppendInput): Promise<AppendResult>;
7
+ events(): readonly SessionEvent[];
8
+ on(eventName: "event", listener: SessionEventListener, options?: SessionOnEventOptions<SessionEvent>): () => void;
9
+ on(eventName: "error", listener: (error: Error) => void): () => void;
10
+ }
11
+ type SendMessageInput = {
12
+ text: string;
13
+ } | (Omit<UIMessage, "id"> & {
14
+ id?: string;
15
+ });
16
+ interface UseStarciteChatOptions {
17
+ session: StarciteChatSession;
18
+ id?: string;
19
+ userMessageSource?: string;
20
+ onError?: (error: Error) => void;
21
+ }
22
+ interface UseStarciteChatResult {
23
+ messages: UIMessage[];
24
+ sendMessage: (message: SendMessageInput) => Promise<void>;
25
+ status: ChatStatus;
26
+ }
27
+ declare function useStarciteChat(options: UseStarciteChatOptions): UseStarciteChatResult;
28
+
29
+ export { type SendMessageInput, type StarciteChatSession, type UseStarciteChatOptions, type UseStarciteChatResult, useStarciteChat };
@@ -0,0 +1,29 @@
1
+ import { SessionAppendInput, AppendResult, SessionEvent, SessionEventListener, SessionOnEventOptions } from '@starcite/sdk';
2
+ import { UIMessage, ChatStatus } from 'ai';
3
+
4
+ interface StarciteChatSession {
5
+ readonly id: string;
6
+ append(input: SessionAppendInput): Promise<AppendResult>;
7
+ events(): readonly SessionEvent[];
8
+ on(eventName: "event", listener: SessionEventListener, options?: SessionOnEventOptions<SessionEvent>): () => void;
9
+ on(eventName: "error", listener: (error: Error) => void): () => void;
10
+ }
11
+ type SendMessageInput = {
12
+ text: string;
13
+ } | (Omit<UIMessage, "id"> & {
14
+ id?: string;
15
+ });
16
+ interface UseStarciteChatOptions {
17
+ session: StarciteChatSession;
18
+ id?: string;
19
+ userMessageSource?: string;
20
+ onError?: (error: Error) => void;
21
+ }
22
+ interface UseStarciteChatResult {
23
+ messages: UIMessage[];
24
+ sendMessage: (message: SendMessageInput) => Promise<void>;
25
+ status: ChatStatus;
26
+ }
27
+ declare function useStarciteChat(options: UseStarciteChatOptions): UseStarciteChatResult;
28
+
29
+ export { type SendMessageInput, type StarciteChatSession, type UseStarciteChatOptions, type UseStarciteChatResult, useStarciteChat };