ai 2.2.22 → 2.2.24

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.
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // react/index.ts
32
32
  var react_exports = {};
33
33
  __export(react_exports, {
34
+ experimental_useAssistant: () => experimental_useAssistant,
34
35
  useChat: () => useChat,
35
36
  useCompletion: () => useCompletion
36
37
  });
@@ -42,6 +43,129 @@ var import_swr = __toESM(require("swr"));
42
43
 
43
44
  // shared/utils.ts
44
45
  var import_non_secure = require("nanoid/non-secure");
46
+
47
+ // shared/stream-parts.ts
48
+ var textStreamPart = {
49
+ code: "0",
50
+ name: "text",
51
+ parse: (value) => {
52
+ if (typeof value !== "string") {
53
+ throw new Error('"text" parts expect a string value.');
54
+ }
55
+ return { type: "text", value };
56
+ }
57
+ };
58
+ var functionCallStreamPart = {
59
+ code: "1",
60
+ name: "function_call",
61
+ parse: (value) => {
62
+ if (value == null || typeof value !== "object" || !("function_call" in value) || typeof value.function_call !== "object" || value.function_call == null || !("name" in value.function_call) || !("arguments" in value.function_call) || typeof value.function_call.name !== "string" || typeof value.function_call.arguments !== "string") {
63
+ throw new Error(
64
+ '"function_call" parts expect an object with a "function_call" property.'
65
+ );
66
+ }
67
+ return {
68
+ type: "function_call",
69
+ value
70
+ };
71
+ }
72
+ };
73
+ var dataStreamPart = {
74
+ code: "2",
75
+ name: "data",
76
+ parse: (value) => {
77
+ if (!Array.isArray(value)) {
78
+ throw new Error('"data" parts expect an array value.');
79
+ }
80
+ return { type: "data", value };
81
+ }
82
+ };
83
+ var errorStreamPart = {
84
+ code: "3",
85
+ name: "error",
86
+ parse: (value) => {
87
+ if (typeof value !== "string") {
88
+ throw new Error('"error" parts expect a string value.');
89
+ }
90
+ return { type: "error", value };
91
+ }
92
+ };
93
+ var assistantMessage = {
94
+ code: "4",
95
+ name: "assistant_message",
96
+ parse: (value) => {
97
+ if (value == null || typeof value !== "object" || !("id" in value) || !("role" in value) || !("content" in value) || typeof value.id !== "string" || typeof value.role !== "string" || value.role !== "assistant" || !Array.isArray(value.content) || !value.content.every(
98
+ (item) => item != null && typeof item === "object" && "type" in item && item.type === "text" && "text" in item && item.text != null && typeof item.text === "object" && "value" in item.text && typeof item.text.value === "string"
99
+ )) {
100
+ throw new Error(
101
+ '"assistant_message" parts expect an object with an "id", "role", and "content" property.'
102
+ );
103
+ }
104
+ return {
105
+ type: "assistant_message",
106
+ value
107
+ };
108
+ }
109
+ };
110
+ var assistantControlData = {
111
+ code: "5",
112
+ name: "assistant_control_data",
113
+ parse: (value) => {
114
+ if (value == null || typeof value !== "object" || !("threadId" in value) || !("messageId" in value) || typeof value.threadId !== "string" || typeof value.messageId !== "string") {
115
+ throw new Error(
116
+ '"assistant_control_data" parts expect an object with a "threadId" and "messageId" property.'
117
+ );
118
+ }
119
+ return {
120
+ type: "assistant_control_data",
121
+ value: {
122
+ threadId: value.threadId,
123
+ messageId: value.messageId
124
+ }
125
+ };
126
+ }
127
+ };
128
+ var streamParts = [
129
+ textStreamPart,
130
+ functionCallStreamPart,
131
+ dataStreamPart,
132
+ errorStreamPart,
133
+ assistantMessage,
134
+ assistantControlData
135
+ ];
136
+ var streamPartsByCode = {
137
+ [textStreamPart.code]: textStreamPart,
138
+ [functionCallStreamPart.code]: functionCallStreamPart,
139
+ [dataStreamPart.code]: dataStreamPart,
140
+ [errorStreamPart.code]: errorStreamPart,
141
+ [assistantMessage.code]: assistantMessage,
142
+ [assistantControlData.code]: assistantControlData
143
+ };
144
+ var StreamStringPrefixes = {
145
+ [textStreamPart.name]: textStreamPart.code,
146
+ [functionCallStreamPart.name]: functionCallStreamPart.code,
147
+ [dataStreamPart.name]: dataStreamPart.code,
148
+ [errorStreamPart.name]: errorStreamPart.code,
149
+ [assistantMessage.name]: assistantMessage.code,
150
+ [assistantControlData.name]: assistantControlData.code
151
+ };
152
+ var validCodes = streamParts.map((part) => part.code);
153
+ var parseStreamPart = (line) => {
154
+ const firstSeparatorIndex = line.indexOf(":");
155
+ if (firstSeparatorIndex === -1) {
156
+ throw new Error("Failed to parse stream string. No separator found.");
157
+ }
158
+ const prefix = line.slice(0, firstSeparatorIndex);
159
+ if (!validCodes.includes(prefix)) {
160
+ throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`);
161
+ }
162
+ const code = prefix;
163
+ const textValue = line.slice(firstSeparatorIndex + 1);
164
+ const jsonValue = JSON.parse(textValue);
165
+ return streamPartsByCode[code].parse(jsonValue);
166
+ };
167
+
168
+ // shared/utils.ts
45
169
  var nanoid = (0, import_non_secure.customAlphabet)(
46
170
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
47
171
  7
@@ -57,46 +181,30 @@ function createChunkDecoder(complex) {
57
181
  }
58
182
  return function(chunk) {
59
183
  const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
60
- return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
184
+ return decoded.map(parseStreamPart).filter(Boolean);
61
185
  };
62
186
  }
63
- var StreamStringPrefixes = {
64
- text: 0,
65
- function_call: 1,
66
- data: 2
67
- // user_err: 3?
68
- };
69
- var getStreamStringTypeAndValue = (line) => {
70
- const firstSeperatorIndex = line.indexOf(":");
71
- const prefix = line.slice(0, firstSeperatorIndex);
72
- const type = Object.keys(StreamStringPrefixes).find(
73
- (key) => StreamStringPrefixes[key] === Number(prefix)
74
- );
75
- const val = line.slice(firstSeperatorIndex + 1);
76
- let parsedVal = val;
77
- if (!val) {
78
- return { type, value: "" };
79
- }
80
- try {
81
- parsedVal = JSON.parse(val);
82
- } catch (e) {
83
- console.error("Failed to parse JSON value:", val);
84
- }
85
- return { type, value: parsedVal };
86
- };
87
187
  var COMPLEX_HEADER = "X-Experimental-Stream-Data";
88
188
 
89
- // react/parse-complex-response.ts
189
+ // shared/call-api.ts
190
+ var import_nanoid = require("nanoid");
191
+
192
+ // shared/parse-complex-response.ts
90
193
  async function parseComplexResponse({
91
194
  reader,
92
195
  abortControllerRef,
93
- update
196
+ update,
197
+ onFinish,
198
+ generateId = nanoid,
199
+ getCurrentDate = () => /* @__PURE__ */ new Date()
94
200
  }) {
201
+ const createdAt = getCurrentDate();
95
202
  const decode = createChunkDecoder(true);
96
- const createdAt = /* @__PURE__ */ new Date();
97
- const prefixMap = {};
203
+ const prefixMap = {
204
+ data: []
205
+ };
98
206
  const NEWLINE = "\n".charCodeAt(0);
99
- let chunks = [];
207
+ const chunks = [];
100
208
  let totalLength = 0;
101
209
  while (true) {
102
210
  const { value } = await reader.read();
@@ -133,7 +241,7 @@ async function parseComplexResponse({
133
241
  };
134
242
  } else {
135
243
  prefixMap["text"] = {
136
- id: nanoid(),
244
+ id: generateId(),
137
245
  role: "assistant",
138
246
  content: value2,
139
247
  createdAt
@@ -142,44 +250,182 @@ async function parseComplexResponse({
142
250
  }
143
251
  let functionCallMessage = null;
144
252
  if (type === "function_call") {
145
- prefixMap["function_call"] = value2;
146
- let functionCall = prefixMap["function_call"];
147
- if (functionCall && typeof functionCall === "string") {
148
- const parsedFunctionCall = JSON.parse(
149
- functionCall
150
- ).function_call;
151
- functionCallMessage = {
152
- id: nanoid(),
153
- role: "assistant",
154
- content: "",
155
- function_call: parsedFunctionCall,
156
- name: parsedFunctionCall.name,
157
- createdAt
158
- };
159
- prefixMap["function_call"] = functionCallMessage;
160
- }
253
+ prefixMap["function_call"] = {
254
+ id: generateId(),
255
+ role: "assistant",
256
+ content: "",
257
+ function_call: value2.function_call,
258
+ name: value2.function_call.name,
259
+ createdAt
260
+ };
261
+ functionCallMessage = prefixMap["function_call"];
161
262
  }
162
263
  if (type === "data") {
163
- const parsedValue = JSON.parse(value2);
164
- if (prefixMap["data"]) {
165
- prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
166
- } else {
167
- prefixMap["data"] = parsedValue;
168
- }
264
+ prefixMap["data"].push(...value2);
169
265
  }
170
- const data = prefixMap["data"];
171
266
  const responseMessage = prefixMap["text"];
172
267
  const merged = [functionCallMessage, responseMessage].filter(
173
268
  Boolean
174
269
  );
175
- update(merged, data);
176
- if (abortControllerRef.current === null) {
270
+ update(merged, [...prefixMap["data"]]);
271
+ if ((abortControllerRef == null ? void 0 : abortControllerRef.current) === null) {
272
+ reader.cancel();
273
+ break;
274
+ }
275
+ }
276
+ }
277
+ onFinish == null ? void 0 : onFinish(prefixMap);
278
+ return {
279
+ messages: [prefixMap.text, prefixMap.function_call].filter(
280
+ Boolean
281
+ ),
282
+ data: prefixMap.data
283
+ };
284
+ }
285
+
286
+ // shared/call-api.ts
287
+ async function callApi({
288
+ api,
289
+ messages,
290
+ body,
291
+ credentials,
292
+ headers,
293
+ abortController,
294
+ appendMessage,
295
+ restoreMessagesOnFailure,
296
+ onResponse,
297
+ onUpdate,
298
+ onFinish
299
+ }) {
300
+ var _a;
301
+ const response = await fetch(api, {
302
+ method: "POST",
303
+ body: JSON.stringify({
304
+ messages,
305
+ ...body
306
+ }),
307
+ headers,
308
+ signal: (_a = abortController == null ? void 0 : abortController()) == null ? void 0 : _a.signal,
309
+ credentials
310
+ }).catch((err) => {
311
+ restoreMessagesOnFailure();
312
+ throw err;
313
+ });
314
+ if (onResponse) {
315
+ try {
316
+ await onResponse(response);
317
+ } catch (err) {
318
+ throw err;
319
+ }
320
+ }
321
+ if (!response.ok) {
322
+ restoreMessagesOnFailure();
323
+ throw new Error(
324
+ await response.text() || "Failed to fetch the chat response."
325
+ );
326
+ }
327
+ if (!response.body) {
328
+ throw new Error("The response body is empty.");
329
+ }
330
+ const reader = response.body.getReader();
331
+ const isComplexMode = response.headers.get(COMPLEX_HEADER) === "true";
332
+ if (isComplexMode) {
333
+ return await parseComplexResponse({
334
+ reader,
335
+ abortControllerRef: abortController != null ? { current: abortController() } : void 0,
336
+ update: onUpdate,
337
+ onFinish(prefixMap) {
338
+ if (onFinish && prefixMap.text != null) {
339
+ onFinish(prefixMap.text);
340
+ }
341
+ }
342
+ });
343
+ } else {
344
+ const createdAt = /* @__PURE__ */ new Date();
345
+ const decode = createChunkDecoder(false);
346
+ let streamedResponse = "";
347
+ const replyId = (0, import_nanoid.nanoid)();
348
+ let responseMessage = {
349
+ id: replyId,
350
+ createdAt,
351
+ content: "",
352
+ role: "assistant"
353
+ };
354
+ while (true) {
355
+ const { done, value } = await reader.read();
356
+ if (done) {
357
+ break;
358
+ }
359
+ streamedResponse += decode(value);
360
+ if (streamedResponse.startsWith('{"function_call":')) {
361
+ responseMessage["function_call"] = streamedResponse;
362
+ } else {
363
+ responseMessage["content"] = streamedResponse;
364
+ }
365
+ appendMessage({ ...responseMessage });
366
+ if ((abortController == null ? void 0 : abortController()) === null) {
177
367
  reader.cancel();
178
368
  break;
179
369
  }
180
370
  }
371
+ if (streamedResponse.startsWith('{"function_call":')) {
372
+ const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
373
+ responseMessage["function_call"] = parsedFunctionCall;
374
+ appendMessage({ ...responseMessage });
375
+ }
376
+ if (onFinish) {
377
+ onFinish(responseMessage);
378
+ }
379
+ return responseMessage;
380
+ }
381
+ }
382
+
383
+ // shared/process-chat-stream.ts
384
+ async function processChatStream({
385
+ getStreamedResponse: getStreamedResponse2,
386
+ experimental_onFunctionCall,
387
+ updateChatRequest,
388
+ getCurrentMessages
389
+ }) {
390
+ while (true) {
391
+ const messagesAndDataOrJustMessage = await getStreamedResponse2();
392
+ if ("messages" in messagesAndDataOrJustMessage) {
393
+ let hasFollowingResponse = false;
394
+ for (const message of messagesAndDataOrJustMessage.messages) {
395
+ if (message.function_call === void 0 || typeof message.function_call === "string") {
396
+ continue;
397
+ }
398
+ hasFollowingResponse = true;
399
+ if (experimental_onFunctionCall) {
400
+ const functionCall = message.function_call;
401
+ const functionCallResponse = await experimental_onFunctionCall(
402
+ getCurrentMessages(),
403
+ functionCall
404
+ );
405
+ if (functionCallResponse === void 0) {
406
+ hasFollowingResponse = false;
407
+ break;
408
+ }
409
+ updateChatRequest(functionCallResponse);
410
+ }
411
+ }
412
+ if (!hasFollowingResponse) {
413
+ break;
414
+ }
415
+ } else {
416
+ const streamedResponseMessage = messagesAndDataOrJustMessage;
417
+ if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
418
+ break;
419
+ }
420
+ if (experimental_onFunctionCall) {
421
+ const functionCall = streamedResponseMessage.function_call;
422
+ const functionCallResponse = await experimental_onFunctionCall(getCurrentMessages(), functionCall);
423
+ if (functionCallResponse === void 0)
424
+ break;
425
+ updateChatRequest(functionCallResponse);
426
+ }
427
+ }
181
428
  }
182
- return prefixMap;
183
429
  }
184
430
 
185
431
  // react/use-chat.ts
@@ -215,7 +461,8 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
215
461
  }
216
462
  try {
217
463
  const promise = api({
218
- messages: constructedMessagesPayload
464
+ messages: constructedMessagesPayload,
465
+ data: chatRequest.data
219
466
  });
220
467
  await readRow(promise);
221
468
  } catch (e) {
@@ -227,10 +474,11 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
227
474
  }
228
475
  return responseMessage;
229
476
  }
230
- const res = await fetch(api, {
231
- method: "POST",
232
- body: JSON.stringify({
233
- messages: constructedMessagesPayload,
477
+ return await callApi({
478
+ api,
479
+ messages: constructedMessagesPayload,
480
+ body: {
481
+ data: chatRequest.data,
234
482
  ...extraMetadataRef.current.body,
235
483
  ...(_a = chatRequest.options) == null ? void 0 : _a.body,
236
484
  ...chatRequest.functions !== void 0 && {
@@ -239,95 +487,26 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
239
487
  ...chatRequest.function_call !== void 0 && {
240
488
  function_call: chatRequest.function_call
241
489
  }
242
- }),
490
+ },
243
491
  credentials: extraMetadataRef.current.credentials,
244
492
  headers: {
245
493
  ...extraMetadataRef.current.headers,
246
494
  ...(_b = chatRequest.options) == null ? void 0 : _b.headers
247
495
  },
248
- ...abortControllerRef.current !== null && {
249
- signal: abortControllerRef.current.signal
250
- }
251
- }).catch((err) => {
252
- mutate(previousMessages, false);
253
- throw err;
496
+ abortController: () => abortControllerRef.current,
497
+ appendMessage(message) {
498
+ mutate([...chatRequest.messages, message], false);
499
+ },
500
+ restoreMessagesOnFailure() {
501
+ mutate(previousMessages, false);
502
+ },
503
+ onResponse,
504
+ onUpdate(merged, data) {
505
+ mutate([...chatRequest.messages, ...merged], false);
506
+ mutateStreamData([...existingData || [], ...data || []], false);
507
+ },
508
+ onFinish
254
509
  });
255
- if (onResponse) {
256
- try {
257
- await onResponse(res);
258
- } catch (err) {
259
- throw err;
260
- }
261
- }
262
- if (!res.ok) {
263
- mutate(previousMessages, false);
264
- throw new Error(await res.text() || "Failed to fetch the chat response.");
265
- }
266
- if (!res.body) {
267
- throw new Error("The response body is empty.");
268
- }
269
- const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
270
- let responseMessages = [];
271
- const reader = res.body.getReader();
272
- let responseData = [];
273
- if (isComplexMode) {
274
- const prefixMap = await parseComplexResponse({
275
- reader,
276
- abortControllerRef,
277
- update(merged, data) {
278
- mutate([...chatRequest.messages, ...merged], false);
279
- mutateStreamData([...existingData || [], ...data || []], false);
280
- }
281
- });
282
- for (const [type, item] of Object.entries(prefixMap)) {
283
- if (onFinish && type === "text") {
284
- onFinish(item);
285
- }
286
- if (type === "data") {
287
- responseData.push(item);
288
- } else {
289
- responseMessages.push(item);
290
- }
291
- }
292
- return { messages: responseMessages, data: responseData };
293
- } else {
294
- const createdAt = /* @__PURE__ */ new Date();
295
- const decode = createChunkDecoder(false);
296
- let streamedResponse = "";
297
- const replyId = nanoid();
298
- let responseMessage = {
299
- id: replyId,
300
- createdAt,
301
- content: "",
302
- role: "assistant"
303
- };
304
- while (true) {
305
- const { done, value } = await reader.read();
306
- if (done) {
307
- break;
308
- }
309
- streamedResponse += decode(value);
310
- if (streamedResponse.startsWith('{"function_call":')) {
311
- responseMessage["function_call"] = streamedResponse;
312
- } else {
313
- responseMessage["content"] = streamedResponse;
314
- }
315
- mutate([...chatRequest.messages, { ...responseMessage }], false);
316
- if (abortControllerRef.current === null) {
317
- reader.cancel();
318
- break;
319
- }
320
- }
321
- if (streamedResponse.startsWith('{"function_call":')) {
322
- const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
323
- responseMessage["function_call"] = parsedFunctionCall;
324
- mutate([...chatRequest.messages, { ...responseMessage }]);
325
- }
326
- if (onFinish) {
327
- onFinish(responseMessage);
328
- }
329
- return responseMessage;
330
- }
331
510
  };
332
511
  function useChat({
333
512
  api = "/api/chat",
@@ -353,10 +532,7 @@ function useChat({
353
532
  [chatId, "loading"],
354
533
  null
355
534
  );
356
- const { data: streamData, mutate: mutateStreamData } = (0, import_swr.default)(
357
- [chatId, "streamData"],
358
- null
359
- );
535
+ const { data: streamData, mutate: mutateStreamData } = (0, import_swr.default)([chatId, "streamData"], null);
360
536
  const messagesRef = (0, import_react.useRef)(messages || []);
361
537
  (0, import_react.useEffect)(() => {
362
538
  messagesRef.current = messages || [];
@@ -382,8 +558,8 @@ function useChat({
382
558
  setError(void 0);
383
559
  const abortController = new AbortController();
384
560
  abortControllerRef.current = abortController;
385
- while (true) {
386
- const messagesAndDataOrJustMessage = await getStreamedResponse(
561
+ await processChatStream({
562
+ getStreamedResponse: () => getStreamedResponse(
387
563
  api,
388
564
  chatRequest,
389
565
  mutate,
@@ -395,47 +571,13 @@ function useChat({
395
571
  onFinish,
396
572
  onResponse,
397
573
  sendExtraMessageFields
398
- );
399
- if ("messages" in messagesAndDataOrJustMessage) {
400
- let hasFollowingResponse = false;
401
- for (const message of messagesAndDataOrJustMessage.messages) {
402
- if (message.function_call === void 0 || typeof message.function_call === "string") {
403
- continue;
404
- }
405
- hasFollowingResponse = true;
406
- if (experimental_onFunctionCall) {
407
- const functionCall = message.function_call;
408
- const functionCallResponse = await experimental_onFunctionCall(
409
- messagesRef.current,
410
- functionCall
411
- );
412
- if (functionCallResponse === void 0) {
413
- hasFollowingResponse = false;
414
- break;
415
- }
416
- chatRequest = functionCallResponse;
417
- }
418
- }
419
- if (!hasFollowingResponse) {
420
- break;
421
- }
422
- } else {
423
- const streamedResponseMessage = messagesAndDataOrJustMessage;
424
- if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
425
- break;
426
- }
427
- if (experimental_onFunctionCall) {
428
- const functionCall = streamedResponseMessage.function_call;
429
- const functionCallResponse = await experimental_onFunctionCall(
430
- messagesRef.current,
431
- functionCall
432
- );
433
- if (functionCallResponse === void 0)
434
- break;
435
- chatRequest = functionCallResponse;
436
- }
437
- }
438
- }
574
+ ),
575
+ experimental_onFunctionCall,
576
+ updateChatRequest: (chatRequestParam) => {
577
+ chatRequest = chatRequestParam;
578
+ },
579
+ getCurrentMessages: () => messagesRef.current
580
+ });
439
581
  abortControllerRef.current = null;
440
582
  } catch (err) {
441
583
  if (err.name === "AbortError") {
@@ -468,13 +610,14 @@ function useChat({
468
610
  ]
469
611
  );
470
612
  const append = (0, import_react.useCallback)(
471
- async (message, { options, functions, function_call } = {}) => {
613
+ async (message, { options, functions, function_call, data } = {}) => {
472
614
  if (!message.id) {
473
615
  message.id = nanoid();
474
616
  }
475
617
  const chatRequest = {
476
618
  messages: messagesRef.current.concat(message),
477
619
  options,
620
+ data,
478
621
  ...functions !== void 0 && { functions },
479
622
  ...function_call !== void 0 && { function_call }
480
623
  };
@@ -521,7 +664,7 @@ function useChat({
521
664
  );
522
665
  const [input, setInput] = (0, import_react.useState)(initialInput);
523
666
  const handleSubmit = (0, import_react.useCallback)(
524
- (e, { options, functions, function_call } = {}, metadata) => {
667
+ (e, options = {}, metadata) => {
525
668
  if (metadata) {
526
669
  extraMetadataRef.current = {
527
670
  ...extraMetadataRef.current,
@@ -537,7 +680,7 @@ function useChat({
537
680
  role: "user",
538
681
  createdAt: /* @__PURE__ */ new Date()
539
682
  },
540
- { options, functions, function_call }
683
+ options
541
684
  );
542
685
  setInput("");
543
686
  },
@@ -731,8 +874,115 @@ function useCompletion({
731
874
  isLoading
732
875
  };
733
876
  }
877
+
878
+ // react/use-assistant.ts
879
+ var import_react3 = require("react");
880
+
881
+ // shared/process-message-stream.ts
882
+ async function processMessageStream(reader, processMessage) {
883
+ const decoder = new TextDecoder();
884
+ let buffer = "";
885
+ while (true) {
886
+ const { done, value } = await reader.read();
887
+ if (done) {
888
+ if (buffer.length > 0) {
889
+ processMessage(buffer);
890
+ }
891
+ break;
892
+ }
893
+ buffer += decoder.decode(value, { stream: true });
894
+ let endIndex;
895
+ while ((endIndex = buffer.indexOf("\n")) !== -1) {
896
+ processMessage(buffer.substring(0, endIndex).trim());
897
+ buffer = buffer.substring(endIndex + 1);
898
+ }
899
+ }
900
+ }
901
+
902
+ // react/use-assistant.ts
903
+ function experimental_useAssistant({
904
+ api,
905
+ threadId: threadIdParam
906
+ }) {
907
+ const [messages, setMessages] = (0, import_react3.useState)([]);
908
+ const [input, setInput] = (0, import_react3.useState)("");
909
+ const [threadId, setThreadId] = (0, import_react3.useState)(void 0);
910
+ const [status, setStatus] = (0, import_react3.useState)("awaiting_message");
911
+ const [error, setError] = (0, import_react3.useState)(void 0);
912
+ const handleInputChange = (e) => {
913
+ setInput(e.target.value);
914
+ };
915
+ const submitMessage = async (e) => {
916
+ var _a;
917
+ e.preventDefault();
918
+ if (input === "") {
919
+ return;
920
+ }
921
+ setStatus("in_progress");
922
+ setMessages((messages2) => [
923
+ ...messages2,
924
+ { id: "", role: "user", content: input }
925
+ ]);
926
+ setInput("");
927
+ const result = await fetch(api, {
928
+ method: "POST",
929
+ headers: { "Content-Type": "application/json" },
930
+ body: JSON.stringify({
931
+ // always use user-provided threadId when available:
932
+ threadId: (_a = threadIdParam != null ? threadIdParam : threadId) != null ? _a : null,
933
+ message: input
934
+ })
935
+ });
936
+ if (result.body == null) {
937
+ throw new Error("The response body is empty.");
938
+ }
939
+ await processMessageStream(result.body.getReader(), (message) => {
940
+ try {
941
+ const { type, value } = parseStreamPart(message);
942
+ switch (type) {
943
+ case "assistant_message": {
944
+ setMessages((messages2) => [
945
+ ...messages2,
946
+ {
947
+ id: value.id,
948
+ role: value.role,
949
+ content: value.content[0].text.value
950
+ }
951
+ ]);
952
+ break;
953
+ }
954
+ case "assistant_control_data": {
955
+ setThreadId(value.threadId);
956
+ setMessages((messages2) => {
957
+ const lastMessage = messages2[messages2.length - 1];
958
+ lastMessage.id = value.messageId;
959
+ return [...messages2.slice(0, messages2.length - 1), lastMessage];
960
+ });
961
+ break;
962
+ }
963
+ case "error": {
964
+ setError(value);
965
+ break;
966
+ }
967
+ }
968
+ } catch (error2) {
969
+ setError(error2);
970
+ }
971
+ });
972
+ setStatus("awaiting_message");
973
+ };
974
+ return {
975
+ messages,
976
+ input,
977
+ handleInputChange,
978
+ submitMessage,
979
+ status,
980
+ error
981
+ };
982
+ }
734
983
  // Annotate the CommonJS export names for ESM import in node:
735
984
  0 && (module.exports = {
985
+ experimental_useAssistant,
736
986
  useChat,
737
987
  useCompletion
738
988
  });