@kortyx/react 0.0.1

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.js ADDED
@@ -0,0 +1,679 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/index.ts
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
+ buildAssistantMessage: () => buildAssistantMessage,
23
+ createBrowserChatStorage: () => createBrowserChatStorage,
24
+ createChatTransport: () => createChatTransport,
25
+ createLiveChatPieces: () => createLiveChatPieces,
26
+ createRouteChatTransport: () => createRouteChatTransport,
27
+ toHumanInputPiece: () => toHumanInputPiece,
28
+ useChat: () => useChat,
29
+ useChatStreamDebug: () => useChatStreamDebug,
30
+ useStructuredStreams: () => useStructuredStreams
31
+ });
32
+ module.exports = __toCommonJS(index_exports);
33
+
34
+ // src/build-assistant-message.ts
35
+ function buildAssistantMessage(args) {
36
+ const plainTextContent = args.pieces.filter(
37
+ (piece) => piece.type === "text"
38
+ ).map((piece) => piece.content).join("");
39
+ const base = {
40
+ id: args.createId(),
41
+ role: "assistant",
42
+ content: plainTextContent,
43
+ debug: args.debug
44
+ };
45
+ return args.pieces.length > 0 ? { ...base, contentPieces: args.pieces } : base;
46
+ }
47
+
48
+ // src/chat-storage.ts
49
+ var DEFAULT_STORAGE_KEYS = {
50
+ messages: "chat.messages.v1",
51
+ includeHistory: "chat.includeHistory.v1",
52
+ sessionId: "chat.sessionId",
53
+ workflowId: "chat.workflowId"
54
+ };
55
+ var getLocalStorage = () => {
56
+ const candidate = globalThis;
57
+ return candidate.localStorage;
58
+ };
59
+ var defaultParseMessage = (value) => value;
60
+ var defaultSerializeMessage = (message) => message;
61
+ function createBrowserChatStorage(options) {
62
+ const keys = {
63
+ ...DEFAULT_STORAGE_KEYS,
64
+ ...options?.keys ?? {}
65
+ };
66
+ const maxMessages = options?.maxMessages ?? 60;
67
+ const parseMessage = options?.parseMessage ?? defaultParseMessage;
68
+ const serializeMessage = options?.serializeMessage ?? defaultSerializeMessage;
69
+ return {
70
+ load() {
71
+ try {
72
+ const storage = getLocalStorage();
73
+ if (!storage) {
74
+ return {};
75
+ }
76
+ const sessionId = storage.getItem(keys.sessionId);
77
+ const workflowId = storage.getItem(keys.workflowId) ?? "";
78
+ const includeHistoryRaw = storage.getItem(keys.includeHistory);
79
+ const rawMessages = storage.getItem(keys.messages);
80
+ const parsedMessages = rawMessages ? JSON.parse(rawMessages) : [];
81
+ const messages = Array.isArray(parsedMessages) ? parsedMessages.map((item) => parseMessage(item)).filter((message) => message !== null) : [];
82
+ return {
83
+ sessionId,
84
+ workflowId,
85
+ includeHistory: includeHistoryRaw !== "0",
86
+ messages
87
+ };
88
+ } catch {
89
+ return {};
90
+ }
91
+ },
92
+ save(state) {
93
+ try {
94
+ const storage = getLocalStorage();
95
+ if (!storage) return;
96
+ if (state.sessionId) {
97
+ storage.setItem(keys.sessionId, state.sessionId);
98
+ } else {
99
+ storage.removeItem(keys.sessionId);
100
+ }
101
+ storage.setItem(keys.workflowId, state.workflowId);
102
+ storage.setItem(keys.includeHistory, state.includeHistory ? "1" : "0");
103
+ const trimmedMessages = state.messages.slice(-maxMessages).map((message) => serializeMessage(message));
104
+ storage.setItem(keys.messages, JSON.stringify(trimmedMessages));
105
+ } catch {
106
+ }
107
+ },
108
+ clearMessages() {
109
+ try {
110
+ const storage = getLocalStorage();
111
+ if (!storage) return;
112
+ storage.removeItem(keys.messages);
113
+ } catch {
114
+ }
115
+ }
116
+ };
117
+ }
118
+
119
+ // src/chat-transport.ts
120
+ var import_browser = require("@kortyx/stream/browser");
121
+ function createChatTransport(args) {
122
+ return {
123
+ async stream({ onChunk, ...context }) {
124
+ for await (const chunk of await args.stream(context)) {
125
+ const shouldContinue = await onChunk(chunk);
126
+ if (chunk.type === "done" || shouldContinue === false) {
127
+ break;
128
+ }
129
+ }
130
+ }
131
+ };
132
+ }
133
+ function createRouteChatTransport(args) {
134
+ return createChatTransport({
135
+ stream: (context) => {
136
+ const routeArgs = {
137
+ endpoint: args.endpoint,
138
+ body: args.getBody(context),
139
+ ...args.method ? { method: args.method } : {},
140
+ ...args.headers ? { headers: args.headers } : {},
141
+ ...args.fetchImpl ? { fetchImpl: args.fetchImpl } : {}
142
+ };
143
+ return (0, import_browser.streamFromRoute)({
144
+ ...routeArgs
145
+ });
146
+ }
147
+ });
148
+ }
149
+
150
+ // src/create-live-chat-pieces.ts
151
+ var isNonEmptyTextPiece = (piece) => piece.type !== "text" || "content" in piece && typeof piece.content === "string" && piece.content.length > 0;
152
+ function createLiveChatPieces(args) {
153
+ const keyedPieces = [];
154
+ let sawTextDelta = false;
155
+ const emit = () => {
156
+ args.onChange(
157
+ keyedPieces.map((entry) => entry.piece).filter((piece) => isNonEmptyTextPiece(piece))
158
+ );
159
+ };
160
+ const findPieceIndex = (key) => keyedPieces.findIndex((entry) => entry.key === key);
161
+ const upsertPiece = (key, piece) => {
162
+ const existingIndex = findPieceIndex(key);
163
+ if (existingIndex >= 0) {
164
+ keyedPieces[existingIndex] = { key, piece };
165
+ } else {
166
+ keyedPieces.push({ key, piece });
167
+ }
168
+ emit();
169
+ };
170
+ const pushPiece = (piece) => {
171
+ keyedPieces.push({
172
+ key: `${piece.type}:${piece.id}`,
173
+ piece
174
+ });
175
+ emit();
176
+ };
177
+ const resolveTextStreamKey = (chunk, fallbackNode) => {
178
+ if ("segmentId" in chunk && typeof chunk.segmentId === "string") {
179
+ const seg = chunk.segmentId.trim();
180
+ if (seg.length > 0) {
181
+ const op = "opId" in chunk && typeof chunk.opId === "string" ? chunk.opId.trim() : "";
182
+ return op.length > 0 ? `${op}:${seg}` : seg;
183
+ }
184
+ }
185
+ if ("opId" in chunk && typeof chunk.opId === "string") {
186
+ const op = chunk.opId.trim();
187
+ if (op.length > 0) {
188
+ const node = ("node" in chunk && typeof chunk.node === "string" ? chunk.node : fallbackNode) ?? "__unknown__";
189
+ return `${op}:${node}`;
190
+ }
191
+ }
192
+ return fallbackNode ?? "__unknown__";
193
+ };
194
+ const ensureTextPiece = (key) => {
195
+ const pieceKey = `text:${key || "__unknown__"}`;
196
+ const existingIndex = findPieceIndex(pieceKey);
197
+ if (existingIndex >= 0) {
198
+ return keyedPieces[existingIndex]?.piece;
199
+ }
200
+ const nextPiece = {
201
+ id: args.createId(),
202
+ type: "text",
203
+ content: ""
204
+ };
205
+ keyedPieces.push({ key: pieceKey, piece: nextPiece });
206
+ return nextPiece;
207
+ };
208
+ const processChunk = (chunk, _options) => {
209
+ if (chunk.type === "text-start") {
210
+ ensureTextPiece(resolveTextStreamKey(chunk, chunk.node));
211
+ emit();
212
+ return true;
213
+ }
214
+ if (chunk.type === "text-delta") {
215
+ sawTextDelta = true;
216
+ const streamKey = resolveTextStreamKey(chunk, chunk.node);
217
+ const current = ensureTextPiece(streamKey);
218
+ upsertPiece(`text:${streamKey}`, {
219
+ ...current,
220
+ content: current.content + chunk.delta
221
+ });
222
+ return true;
223
+ }
224
+ if (chunk.type === "text-end") {
225
+ emit();
226
+ return true;
227
+ }
228
+ if (chunk.type === "structured-data") {
229
+ const nextItem = args.structuredStreams.applyStreamChunk(chunk);
230
+ if (nextItem) {
231
+ upsertPiece(`structured:${nextItem.streamId}`, {
232
+ id: nextItem.id,
233
+ type: "structured",
234
+ data: nextItem.state
235
+ });
236
+ }
237
+ return true;
238
+ }
239
+ if (chunk.type === "interrupt") {
240
+ pushPiece(args.toHumanInputPiece(chunk));
241
+ return true;
242
+ }
243
+ if (chunk.type === "message") {
244
+ if (!sawTextDelta) {
245
+ pushPiece({
246
+ id: args.createId(),
247
+ type: "text",
248
+ content: chunk.content ?? ""
249
+ });
250
+ }
251
+ return true;
252
+ }
253
+ if (chunk.type === "error") {
254
+ pushPiece({
255
+ id: args.createId(),
256
+ type: "error",
257
+ content: chunk.message ?? "An error occurred"
258
+ });
259
+ return true;
260
+ }
261
+ if (chunk.type === "done") {
262
+ return false;
263
+ }
264
+ return true;
265
+ };
266
+ return {
267
+ processChunk,
268
+ getPieces: () => keyedPieces.map((entry) => entry.piece).filter((piece) => isNonEmptyTextPiece(piece))
269
+ };
270
+ }
271
+
272
+ // src/to-human-input-piece.ts
273
+ function toHumanInputPiece(args) {
274
+ const hi = args.chunk;
275
+ const input = hi.input ?? {};
276
+ const kind = input.kind || (input.multiple ? "multi-choice" : "choice");
277
+ const isText = kind === "text";
278
+ const question = isText ? input.question : typeof input.question === "string" ? input.question : "Please choose";
279
+ const optionsSrc = Array.isArray(input.options) ? input.options : [];
280
+ const optionsArr = optionsSrc.map((option) => ({
281
+ id: String(option.id ?? ""),
282
+ label: String(option.label ?? ""),
283
+ ...typeof option.description === "string" && option.description ? { description: option.description } : {}
284
+ })).filter((option) => option.id && option.label);
285
+ return {
286
+ id: args.createId(),
287
+ type: "interrupt",
288
+ resumeToken: String(hi.resumeToken ?? ""),
289
+ requestId: String(hi.requestId ?? ""),
290
+ kind,
291
+ ...question !== void 0 ? { question } : {},
292
+ multiple: Boolean(input.multiple),
293
+ options: optionsArr
294
+ };
295
+ }
296
+
297
+ // src/use-chat.ts
298
+ var import_react3 = require("react");
299
+
300
+ // src/use-chat-stream-debug.ts
301
+ var import_react = require("react");
302
+ function useChatStreamDebug() {
303
+ const [streamDebug, setStreamDebug] = (0, import_react.useState)([]);
304
+ const clearStreamDebug = (0, import_react.useCallback)(() => {
305
+ setStreamDebug([]);
306
+ }, []);
307
+ const createRecorder = (0, import_react.useCallback)((initialMessage) => {
308
+ let seq = 0;
309
+ let lastTs = 0;
310
+ const accDebug = [];
311
+ const push = (chunk) => {
312
+ const ts = Date.now();
313
+ const withMeta = {
314
+ ...chunk,
315
+ _ts: ts,
316
+ _dt: lastTs ? ts - lastTs : 0,
317
+ _seq: seq++
318
+ };
319
+ lastTs = ts;
320
+ accDebug.push(withMeta);
321
+ setStreamDebug(
322
+ (current) => current.length > 1e3 ? [...current.slice(-1e3), withMeta] : [...current, withMeta]
323
+ );
324
+ };
325
+ push({
326
+ type: "status",
327
+ message: initialMessage
328
+ });
329
+ return {
330
+ push,
331
+ getAll: () => accDebug
332
+ };
333
+ }, []);
334
+ return {
335
+ streamDebug,
336
+ clearStreamDebug,
337
+ createRecorder
338
+ };
339
+ }
340
+
341
+ // src/use-structured-streams.ts
342
+ var import_browser2 = require("@kortyx/stream/browser");
343
+ var import_react2 = require("react");
344
+ var defaultCreateId = () => {
345
+ try {
346
+ if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
347
+ return crypto.randomUUID();
348
+ }
349
+ } catch {
350
+ }
351
+ return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
352
+ };
353
+ function useStructuredStreams(options) {
354
+ const createId = (0, import_react2.useRef)(options?.createId ?? defaultCreateId).current;
355
+ const initialChunks = (0, import_react2.useRef)(options?.initialChunks ?? []).current;
356
+ const accumulatorRef = (0, import_react2.useRef)(
357
+ (0, import_browser2.createStructuredStreamAccumulator)(initialChunks)
358
+ );
359
+ const initialItemsRef = (0, import_react2.useRef)(
360
+ void 0
361
+ );
362
+ if (initialItemsRef.current === void 0) {
363
+ initialItemsRef.current = accumulatorRef.current.entries().map(([streamId, state]) => ({
364
+ id: createId(),
365
+ streamId,
366
+ state
367
+ }));
368
+ }
369
+ const itemsRef = (0, import_react2.useRef)(initialItemsRef.current);
370
+ const [items, setItems] = (0, import_react2.useState)(initialItemsRef.current);
371
+ const setNextItems = (0, import_react2.useCallback)(
372
+ (nextItems) => {
373
+ itemsRef.current = nextItems;
374
+ setItems(nextItems);
375
+ },
376
+ []
377
+ );
378
+ const applyStreamChunk = (0, import_react2.useCallback)(
379
+ (chunk) => {
380
+ const nextState = accumulatorRef.current.applyStreamChunk(chunk);
381
+ if (!nextState) return void 0;
382
+ const currentItems = itemsRef.current;
383
+ const existingIndex = currentItems.findIndex(
384
+ (item) => item.streamId === nextState.streamId
385
+ );
386
+ const existingItem = existingIndex >= 0 ? currentItems[existingIndex] : void 0;
387
+ const nextItem = existingItem ? {
388
+ ...existingItem,
389
+ state: nextState
390
+ } : {
391
+ id: createId(),
392
+ streamId: nextState.streamId,
393
+ state: nextState
394
+ };
395
+ const nextItems = existingIndex >= 0 ? currentItems.map(
396
+ (item, index) => index === existingIndex ? nextItem : item
397
+ ) : [...currentItems, nextItem];
398
+ setNextItems(nextItems);
399
+ return nextItem;
400
+ },
401
+ [createId, setNextItems]
402
+ );
403
+ const clear = (0, import_react2.useCallback)(() => {
404
+ accumulatorRef.current = (0, import_browser2.createStructuredStreamAccumulator)();
405
+ setNextItems([]);
406
+ }, [setNextItems]);
407
+ const get = (0, import_react2.useCallback)((streamId) => {
408
+ return itemsRef.current.find((item) => item.streamId === streamId);
409
+ }, []);
410
+ const byStreamId = (0, import_react2.useMemo)(
411
+ () => Object.fromEntries(
412
+ items.map((item) => [item.streamId, item.state])
413
+ ),
414
+ [items]
415
+ );
416
+ return {
417
+ items,
418
+ byStreamId,
419
+ applyStreamChunk,
420
+ clear,
421
+ get
422
+ };
423
+ }
424
+
425
+ // src/use-chat.ts
426
+ var defaultCreateId2 = () => {
427
+ try {
428
+ if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
429
+ return crypto.randomUUID();
430
+ }
431
+ } catch {
432
+ }
433
+ return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
434
+ };
435
+ var defaultStorage = createBrowserChatStorage();
436
+ function useInitialValue(value) {
437
+ const ref = (0, import_react3.useRef)(void 0);
438
+ if (ref.current === void 0) {
439
+ ref.current = value;
440
+ }
441
+ return ref.current;
442
+ }
443
+ function findActiveTextInterrupt(args) {
444
+ const liveInterrupt = args.streamContentPieces.find(
445
+ (piece) => piece.type === "interrupt" && piece.kind === "text"
446
+ );
447
+ if (liveInterrupt) return liveInterrupt;
448
+ for (let i = args.messages.length - 1; i >= 0; i -= 1) {
449
+ const message = args.messages[i];
450
+ if (!message) continue;
451
+ if (message.role !== "assistant" || !message.contentPieces) continue;
452
+ const messageInterrupt = [...message.contentPieces].reverse().find(
453
+ (piece) => piece.type === "interrupt" && piece.kind === "text"
454
+ );
455
+ if (messageInterrupt) return messageInterrupt;
456
+ }
457
+ return void 0;
458
+ }
459
+ function useChat(options) {
460
+ const transport = useInitialValue(options.transport);
461
+ const storage = useInitialValue(options.storage ?? defaultStorage);
462
+ const createId = useInitialValue(options.createId ?? defaultCreateId2);
463
+ const [messages, setMessages] = (0, import_react3.useState)([]);
464
+ const [isStreaming, setIsStreaming] = (0, import_react3.useState)(false);
465
+ const [streamContentPieces, setStreamContentPieces] = (0, import_react3.useState)([]);
466
+ const [lastAssistantId, setLastAssistantId] = (0, import_react3.useState)(null);
467
+ const [includeHistory, setIncludeHistory] = (0, import_react3.useState)(true);
468
+ const [workflowId, setWorkflowId] = (0, import_react3.useState)("");
469
+ const [sessionId, setSessionId] = (0, import_react3.useState)(null);
470
+ const [didHydrateStorage, setDidHydrateStorage] = (0, import_react3.useState)(false);
471
+ const { streamDebug, clearStreamDebug, createRecorder } = useChatStreamDebug();
472
+ const { applyStreamChunk, clear: clearStructuredStreams } = useStructuredStreams({
473
+ createId
474
+ });
475
+ (0, import_react3.useEffect)(() => {
476
+ let cancelled = false;
477
+ void Promise.resolve(storage.load()).then((storedState) => {
478
+ if (cancelled) return;
479
+ if (typeof storedState.sessionId === "string") {
480
+ setSessionId(storedState.sessionId);
481
+ }
482
+ if (typeof storedState.workflowId === "string") {
483
+ setWorkflowId(storedState.workflowId);
484
+ }
485
+ if (typeof storedState.includeHistory === "boolean") {
486
+ setIncludeHistory(storedState.includeHistory);
487
+ }
488
+ if (Array.isArray(storedState.messages) && storedState.messages.length > 0) {
489
+ setMessages(storedState.messages);
490
+ }
491
+ setDidHydrateStorage(true);
492
+ });
493
+ return () => {
494
+ cancelled = true;
495
+ };
496
+ }, [storage]);
497
+ (0, import_react3.useEffect)(() => {
498
+ if (!didHydrateStorage) return;
499
+ void storage.save({
500
+ sessionId,
501
+ workflowId,
502
+ includeHistory,
503
+ messages
504
+ });
505
+ }, [
506
+ didHydrateStorage,
507
+ includeHistory,
508
+ messages,
509
+ sessionId,
510
+ storage,
511
+ workflowId
512
+ ]);
513
+ const clearChat = () => {
514
+ setMessages([]);
515
+ setStreamContentPieces([]);
516
+ clearStreamDebug();
517
+ clearStructuredStreams();
518
+ setLastAssistantId(null);
519
+ void storage.clearMessages();
520
+ };
521
+ const persistSessionId = (sid) => {
522
+ setSessionId(sid);
523
+ };
524
+ const resolveSessionId = () => {
525
+ const sid = sessionId ?? createId();
526
+ if (!sessionId) persistSessionId(sid);
527
+ return sid;
528
+ };
529
+ const streamAssistantResponse = async (args) => {
530
+ clearStructuredStreams();
531
+ setStreamContentPieces([]);
532
+ const debug = createRecorder(`${args.debugLabel} sessionId=${args.sid}`);
533
+ const pieces = createLiveChatPieces({
534
+ createId,
535
+ onChange: setStreamContentPieces,
536
+ structuredStreams: {
537
+ applyStreamChunk
538
+ },
539
+ toHumanInputPiece: (chunk) => toHumanInputPiece({
540
+ chunk,
541
+ createId
542
+ })
543
+ });
544
+ await transport.stream({
545
+ sessionId: args.sid,
546
+ workflowId,
547
+ messages: args.messagesToSend,
548
+ onChunk: (chunk) => {
549
+ debug.push(chunk);
550
+ if (chunk.type === "session") {
551
+ if (typeof chunk.sessionId === "string") {
552
+ persistSessionId(chunk.sessionId);
553
+ }
554
+ return;
555
+ }
556
+ return pieces.processChunk(chunk, {
557
+ openDebugOnInterrupt: args.openDebugOnInterrupt
558
+ });
559
+ }
560
+ });
561
+ const assistant = buildAssistantMessage({
562
+ createId,
563
+ pieces: pieces.getPieces(),
564
+ debug: debug.getAll()
565
+ });
566
+ setMessages((prev) => [...prev, assistant]);
567
+ setLastAssistantId(assistant.id);
568
+ clearStructuredStreams();
569
+ setStreamContentPieces([]);
570
+ clearStreamDebug();
571
+ };
572
+ const respondToHumanInput = async ({
573
+ resumeToken,
574
+ requestId,
575
+ selected,
576
+ text
577
+ }) => {
578
+ if (isStreaming) return;
579
+ const label = typeof text === "string" && text.length > 0 ? text : selected.length > 0 ? selected.length === 1 ? selected[0] : selected.join(", ") : "(selection)";
580
+ const userId = createId();
581
+ const userMsg = { id: userId, role: "user", content: label };
582
+ setMessages((prev) => [...prev, userMsg]);
583
+ setIsStreaming(true);
584
+ setStreamContentPieces([]);
585
+ clearStreamDebug();
586
+ clearStructuredStreams();
587
+ try {
588
+ const resumePayload = {
589
+ resume: { token: resumeToken, requestId, selected }
590
+ };
591
+ const outgoing = {
592
+ role: "user",
593
+ content: label,
594
+ metadata: resumePayload
595
+ };
596
+ const sid = resolveSessionId();
597
+ const history = includeHistory ? messages.map((message) => ({
598
+ role: message.role,
599
+ content: message.content
600
+ })) : [];
601
+ const messagesToSend = [...history, outgoing];
602
+ await streamAssistantResponse({
603
+ sid,
604
+ messagesToSend,
605
+ debugLabel: "runChat (resume)"
606
+ });
607
+ } finally {
608
+ setIsStreaming(false);
609
+ }
610
+ };
611
+ const send = async (text) => {
612
+ const content = text.trim();
613
+ if (!content || isStreaming) return;
614
+ const activeTextInterrupt = findActiveTextInterrupt({
615
+ messages,
616
+ streamContentPieces
617
+ });
618
+ if (activeTextInterrupt) {
619
+ await respondToHumanInput({
620
+ resumeToken: activeTextInterrupt.resumeToken,
621
+ requestId: activeTextInterrupt.requestId,
622
+ selected: [content],
623
+ text: content
624
+ });
625
+ return;
626
+ }
627
+ const userId = createId();
628
+ const userMsg = { id: userId, role: "user", content };
629
+ setMessages((prev) => [...prev, userMsg]);
630
+ setIsStreaming(true);
631
+ setStreamContentPieces([]);
632
+ clearStreamDebug();
633
+ clearStructuredStreams();
634
+ try {
635
+ const sid = resolveSessionId();
636
+ const history = includeHistory ? messages.map((message) => ({
637
+ role: message.role,
638
+ content: message.content
639
+ })) : [];
640
+ const messagesToSend = [...history, { role: "user", content }];
641
+ await streamAssistantResponse({
642
+ sid,
643
+ messagesToSend,
644
+ debugLabel: "runChat (send)",
645
+ openDebugOnInterrupt: true
646
+ });
647
+ } finally {
648
+ setIsStreaming(false);
649
+ }
650
+ };
651
+ return {
652
+ messages,
653
+ isStreaming,
654
+ streamContentPieces,
655
+ streamDebug,
656
+ lastAssistantId,
657
+ workflowId,
658
+ setWorkflowId,
659
+ send,
660
+ respondToHumanInput,
661
+ setMessages,
662
+ clearChat,
663
+ includeHistory,
664
+ setIncludeHistory
665
+ };
666
+ }
667
+ // Annotate the CommonJS export names for ESM import in node:
668
+ 0 && (module.exports = {
669
+ buildAssistantMessage,
670
+ createBrowserChatStorage,
671
+ createChatTransport,
672
+ createLiveChatPieces,
673
+ createRouteChatTransport,
674
+ toHumanInputPiece,
675
+ useChat,
676
+ useChatStreamDebug,
677
+ useStructuredStreams
678
+ });
679
+ //# sourceMappingURL=index.js.map