ai 2.2.23 → 2.2.25

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.
@@ -6,6 +6,129 @@ import useSWR from "swr";
6
6
 
7
7
  // shared/utils.ts
8
8
  import { customAlphabet } from "nanoid/non-secure";
9
+
10
+ // shared/stream-parts.ts
11
+ var textStreamPart = {
12
+ code: "0",
13
+ name: "text",
14
+ parse: (value) => {
15
+ if (typeof value !== "string") {
16
+ throw new Error('"text" parts expect a string value.');
17
+ }
18
+ return { type: "text", value };
19
+ }
20
+ };
21
+ var functionCallStreamPart = {
22
+ code: "1",
23
+ name: "function_call",
24
+ parse: (value) => {
25
+ 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") {
26
+ throw new Error(
27
+ '"function_call" parts expect an object with a "function_call" property.'
28
+ );
29
+ }
30
+ return {
31
+ type: "function_call",
32
+ value
33
+ };
34
+ }
35
+ };
36
+ var dataStreamPart = {
37
+ code: "2",
38
+ name: "data",
39
+ parse: (value) => {
40
+ if (!Array.isArray(value)) {
41
+ throw new Error('"data" parts expect an array value.');
42
+ }
43
+ return { type: "data", value };
44
+ }
45
+ };
46
+ var errorStreamPart = {
47
+ code: "3",
48
+ name: "error",
49
+ parse: (value) => {
50
+ if (typeof value !== "string") {
51
+ throw new Error('"error" parts expect a string value.');
52
+ }
53
+ return { type: "error", value };
54
+ }
55
+ };
56
+ var assistantMessage = {
57
+ code: "4",
58
+ name: "assistant_message",
59
+ parse: (value) => {
60
+ 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(
61
+ (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"
62
+ )) {
63
+ throw new Error(
64
+ '"assistant_message" parts expect an object with an "id", "role", and "content" property.'
65
+ );
66
+ }
67
+ return {
68
+ type: "assistant_message",
69
+ value
70
+ };
71
+ }
72
+ };
73
+ var assistantControlData = {
74
+ code: "5",
75
+ name: "assistant_control_data",
76
+ parse: (value) => {
77
+ if (value == null || typeof value !== "object" || !("threadId" in value) || !("messageId" in value) || typeof value.threadId !== "string" || typeof value.messageId !== "string") {
78
+ throw new Error(
79
+ '"assistant_control_data" parts expect an object with a "threadId" and "messageId" property.'
80
+ );
81
+ }
82
+ return {
83
+ type: "assistant_control_data",
84
+ value: {
85
+ threadId: value.threadId,
86
+ messageId: value.messageId
87
+ }
88
+ };
89
+ }
90
+ };
91
+ var streamParts = [
92
+ textStreamPart,
93
+ functionCallStreamPart,
94
+ dataStreamPart,
95
+ errorStreamPart,
96
+ assistantMessage,
97
+ assistantControlData
98
+ ];
99
+ var streamPartsByCode = {
100
+ [textStreamPart.code]: textStreamPart,
101
+ [functionCallStreamPart.code]: functionCallStreamPart,
102
+ [dataStreamPart.code]: dataStreamPart,
103
+ [errorStreamPart.code]: errorStreamPart,
104
+ [assistantMessage.code]: assistantMessage,
105
+ [assistantControlData.code]: assistantControlData
106
+ };
107
+ var StreamStringPrefixes = {
108
+ [textStreamPart.name]: textStreamPart.code,
109
+ [functionCallStreamPart.name]: functionCallStreamPart.code,
110
+ [dataStreamPart.name]: dataStreamPart.code,
111
+ [errorStreamPart.name]: errorStreamPart.code,
112
+ [assistantMessage.name]: assistantMessage.code,
113
+ [assistantControlData.name]: assistantControlData.code
114
+ };
115
+ var validCodes = streamParts.map((part) => part.code);
116
+ var parseStreamPart = (line) => {
117
+ const firstSeparatorIndex = line.indexOf(":");
118
+ if (firstSeparatorIndex === -1) {
119
+ throw new Error("Failed to parse stream string. No separator found.");
120
+ }
121
+ const prefix = line.slice(0, firstSeparatorIndex);
122
+ if (!validCodes.includes(prefix)) {
123
+ throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`);
124
+ }
125
+ const code = prefix;
126
+ const textValue = line.slice(firstSeparatorIndex + 1);
127
+ const jsonValue = JSON.parse(textValue);
128
+ return streamPartsByCode[code].parse(jsonValue);
129
+ };
130
+
131
+ // shared/utils.ts
9
132
  var nanoid = customAlphabet(
10
133
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
11
134
  7
@@ -21,50 +144,30 @@ function createChunkDecoder(complex) {
21
144
  }
22
145
  return function(chunk) {
23
146
  const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
24
- return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
147
+ return decoded.map(parseStreamPart).filter(Boolean);
25
148
  };
26
149
  }
27
- var StreamStringPrefixes = {
28
- text: 0,
29
- function_call: 1,
30
- data: 2
31
- // user_err: 3?
32
- };
33
- var getStreamStringTypeAndValue = (line) => {
34
- const firstSeperatorIndex = line.indexOf(":");
35
- if (firstSeperatorIndex === -1) {
36
- throw new Error("Failed to parse stream string");
37
- }
38
- const prefix = line.slice(0, firstSeperatorIndex);
39
- const type = Object.keys(StreamStringPrefixes).find(
40
- (key) => StreamStringPrefixes[key] === Number(prefix)
41
- );
42
- const val = line.slice(firstSeperatorIndex + 1);
43
- let parsedVal = val;
44
- if (!val) {
45
- return { type, value: "" };
46
- }
47
- try {
48
- parsedVal = JSON.parse(val);
49
- } catch (e) {
50
- console.error("Failed to parse JSON value:", val);
51
- }
52
- return { type, value: parsedVal };
53
- };
54
150
  var COMPLEX_HEADER = "X-Experimental-Stream-Data";
55
151
 
56
- // react/parse-complex-response.ts
152
+ // shared/call-api.ts
153
+ import { nanoid as nanoid2 } from "nanoid";
154
+
155
+ // shared/parse-complex-response.ts
57
156
  async function parseComplexResponse({
58
157
  reader,
59
158
  abortControllerRef,
60
159
  update,
61
- onFinish
160
+ onFinish,
161
+ generateId = nanoid,
162
+ getCurrentDate = () => /* @__PURE__ */ new Date()
62
163
  }) {
164
+ const createdAt = getCurrentDate();
63
165
  const decode = createChunkDecoder(true);
64
- const createdAt = /* @__PURE__ */ new Date();
65
- const prefixMap = {};
166
+ const prefixMap = {
167
+ data: []
168
+ };
66
169
  const NEWLINE = "\n".charCodeAt(0);
67
- let chunks = [];
170
+ const chunks = [];
68
171
  let totalLength = 0;
69
172
  while (true) {
70
173
  const { value } = await reader.read();
@@ -101,7 +204,7 @@ async function parseComplexResponse({
101
204
  };
102
205
  } else {
103
206
  prefixMap["text"] = {
104
- id: nanoid(),
207
+ id: generateId(),
105
208
  role: "assistant",
106
209
  content: value2,
107
210
  createdAt
@@ -110,37 +213,24 @@ async function parseComplexResponse({
110
213
  }
111
214
  let functionCallMessage = null;
112
215
  if (type === "function_call") {
113
- prefixMap["function_call"] = value2;
114
- let functionCall = prefixMap["function_call"];
115
- if (functionCall && typeof functionCall === "string") {
116
- const parsedFunctionCall = JSON.parse(
117
- functionCall
118
- ).function_call;
119
- functionCallMessage = {
120
- id: nanoid(),
121
- role: "assistant",
122
- content: "",
123
- function_call: parsedFunctionCall,
124
- name: parsedFunctionCall.name,
125
- createdAt
126
- };
127
- prefixMap["function_call"] = functionCallMessage;
128
- }
216
+ prefixMap["function_call"] = {
217
+ id: generateId(),
218
+ role: "assistant",
219
+ content: "",
220
+ function_call: value2.function_call,
221
+ name: value2.function_call.name,
222
+ createdAt
223
+ };
224
+ functionCallMessage = prefixMap["function_call"];
129
225
  }
130
226
  if (type === "data") {
131
- const parsedValue = JSON.parse(value2);
132
- if (prefixMap["data"]) {
133
- prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
134
- } else {
135
- prefixMap["data"] = parsedValue;
136
- }
227
+ prefixMap["data"].push(...value2);
137
228
  }
138
- const data = prefixMap["data"];
139
229
  const responseMessage = prefixMap["text"];
140
230
  const merged = [functionCallMessage, responseMessage].filter(
141
231
  Boolean
142
232
  );
143
- update(merged, data);
233
+ update(merged, [...prefixMap["data"]]);
144
234
  if ((abortControllerRef == null ? void 0 : abortControllerRef.current) === null) {
145
235
  reader.cancel();
146
236
  break;
@@ -148,7 +238,157 @@ async function parseComplexResponse({
148
238
  }
149
239
  }
150
240
  onFinish == null ? void 0 : onFinish(prefixMap);
151
- return prefixMap;
241
+ return {
242
+ messages: [prefixMap.text, prefixMap.function_call].filter(
243
+ Boolean
244
+ ),
245
+ data: prefixMap.data
246
+ };
247
+ }
248
+
249
+ // shared/call-api.ts
250
+ async function callApi({
251
+ api,
252
+ messages,
253
+ body,
254
+ credentials,
255
+ headers,
256
+ abortController,
257
+ appendMessage,
258
+ restoreMessagesOnFailure,
259
+ onResponse,
260
+ onUpdate,
261
+ onFinish
262
+ }) {
263
+ var _a;
264
+ const response = await fetch(api, {
265
+ method: "POST",
266
+ body: JSON.stringify({
267
+ messages,
268
+ ...body
269
+ }),
270
+ headers,
271
+ signal: (_a = abortController == null ? void 0 : abortController()) == null ? void 0 : _a.signal,
272
+ credentials
273
+ }).catch((err) => {
274
+ restoreMessagesOnFailure();
275
+ throw err;
276
+ });
277
+ if (onResponse) {
278
+ try {
279
+ await onResponse(response);
280
+ } catch (err) {
281
+ throw err;
282
+ }
283
+ }
284
+ if (!response.ok) {
285
+ restoreMessagesOnFailure();
286
+ throw new Error(
287
+ await response.text() || "Failed to fetch the chat response."
288
+ );
289
+ }
290
+ if (!response.body) {
291
+ throw new Error("The response body is empty.");
292
+ }
293
+ const reader = response.body.getReader();
294
+ const isComplexMode = response.headers.get(COMPLEX_HEADER) === "true";
295
+ if (isComplexMode) {
296
+ return await parseComplexResponse({
297
+ reader,
298
+ abortControllerRef: abortController != null ? { current: abortController() } : void 0,
299
+ update: onUpdate,
300
+ onFinish(prefixMap) {
301
+ if (onFinish && prefixMap.text != null) {
302
+ onFinish(prefixMap.text);
303
+ }
304
+ }
305
+ });
306
+ } else {
307
+ const createdAt = /* @__PURE__ */ new Date();
308
+ const decode = createChunkDecoder(false);
309
+ let streamedResponse = "";
310
+ const replyId = nanoid2();
311
+ let responseMessage = {
312
+ id: replyId,
313
+ createdAt,
314
+ content: "",
315
+ role: "assistant"
316
+ };
317
+ while (true) {
318
+ const { done, value } = await reader.read();
319
+ if (done) {
320
+ break;
321
+ }
322
+ streamedResponse += decode(value);
323
+ if (streamedResponse.startsWith('{"function_call":')) {
324
+ responseMessage["function_call"] = streamedResponse;
325
+ } else {
326
+ responseMessage["content"] = streamedResponse;
327
+ }
328
+ appendMessage({ ...responseMessage });
329
+ if ((abortController == null ? void 0 : abortController()) === null) {
330
+ reader.cancel();
331
+ break;
332
+ }
333
+ }
334
+ if (streamedResponse.startsWith('{"function_call":')) {
335
+ const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
336
+ responseMessage["function_call"] = parsedFunctionCall;
337
+ appendMessage({ ...responseMessage });
338
+ }
339
+ if (onFinish) {
340
+ onFinish(responseMessage);
341
+ }
342
+ return responseMessage;
343
+ }
344
+ }
345
+
346
+ // shared/process-chat-stream.ts
347
+ async function processChatStream({
348
+ getStreamedResponse: getStreamedResponse2,
349
+ experimental_onFunctionCall,
350
+ updateChatRequest,
351
+ getCurrentMessages
352
+ }) {
353
+ while (true) {
354
+ const messagesAndDataOrJustMessage = await getStreamedResponse2();
355
+ if ("messages" in messagesAndDataOrJustMessage) {
356
+ let hasFollowingResponse = false;
357
+ for (const message of messagesAndDataOrJustMessage.messages) {
358
+ if (message.function_call === void 0 || typeof message.function_call === "string") {
359
+ continue;
360
+ }
361
+ hasFollowingResponse = true;
362
+ if (experimental_onFunctionCall) {
363
+ const functionCall = message.function_call;
364
+ const functionCallResponse = await experimental_onFunctionCall(
365
+ getCurrentMessages(),
366
+ functionCall
367
+ );
368
+ if (functionCallResponse === void 0) {
369
+ hasFollowingResponse = false;
370
+ break;
371
+ }
372
+ updateChatRequest(functionCallResponse);
373
+ }
374
+ }
375
+ if (!hasFollowingResponse) {
376
+ break;
377
+ }
378
+ } else {
379
+ const streamedResponseMessage = messagesAndDataOrJustMessage;
380
+ if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
381
+ break;
382
+ }
383
+ if (experimental_onFunctionCall) {
384
+ const functionCall = streamedResponseMessage.function_call;
385
+ const functionCallResponse = await experimental_onFunctionCall(getCurrentMessages(), functionCall);
386
+ if (functionCallResponse === void 0)
387
+ break;
388
+ updateChatRequest(functionCallResponse);
389
+ }
390
+ }
391
+ }
152
392
  }
153
393
 
154
394
  // react/use-chat.ts
@@ -197,10 +437,10 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
197
437
  }
198
438
  return responseMessage;
199
439
  }
200
- const res = await fetch(api, {
201
- method: "POST",
202
- body: JSON.stringify({
203
- messages: constructedMessagesPayload,
440
+ return await callApi({
441
+ api,
442
+ messages: constructedMessagesPayload,
443
+ body: {
204
444
  data: chatRequest.data,
205
445
  ...extraMetadataRef.current.body,
206
446
  ...(_a = chatRequest.options) == null ? void 0 : _a.body,
@@ -210,95 +450,26 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
210
450
  ...chatRequest.function_call !== void 0 && {
211
451
  function_call: chatRequest.function_call
212
452
  }
213
- }),
453
+ },
214
454
  credentials: extraMetadataRef.current.credentials,
215
455
  headers: {
216
456
  ...extraMetadataRef.current.headers,
217
457
  ...(_b = chatRequest.options) == null ? void 0 : _b.headers
218
458
  },
219
- ...abortControllerRef.current !== null && {
220
- signal: abortControllerRef.current.signal
221
- }
222
- }).catch((err) => {
223
- mutate(previousMessages, false);
224
- throw err;
459
+ abortController: () => abortControllerRef.current,
460
+ appendMessage(message) {
461
+ mutate([...chatRequest.messages, message], false);
462
+ },
463
+ restoreMessagesOnFailure() {
464
+ mutate(previousMessages, false);
465
+ },
466
+ onResponse,
467
+ onUpdate(merged, data) {
468
+ mutate([...chatRequest.messages, ...merged], false);
469
+ mutateStreamData([...existingData || [], ...data || []], false);
470
+ },
471
+ onFinish
225
472
  });
226
- if (onResponse) {
227
- try {
228
- await onResponse(res);
229
- } catch (err) {
230
- throw err;
231
- }
232
- }
233
- if (!res.ok) {
234
- mutate(previousMessages, false);
235
- throw new Error(await res.text() || "Failed to fetch the chat response.");
236
- }
237
- if (!res.body) {
238
- throw new Error("The response body is empty.");
239
- }
240
- const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
241
- let responseMessages = [];
242
- const reader = res.body.getReader();
243
- let responseData = [];
244
- if (isComplexMode) {
245
- const prefixMap = await parseComplexResponse({
246
- reader,
247
- abortControllerRef,
248
- update(merged, data) {
249
- mutate([...chatRequest.messages, ...merged], false);
250
- mutateStreamData([...existingData || [], ...data || []], false);
251
- }
252
- });
253
- for (const [type, item] of Object.entries(prefixMap)) {
254
- if (onFinish && type === "text") {
255
- onFinish(item);
256
- }
257
- if (type === "data") {
258
- responseData.push(item);
259
- } else {
260
- responseMessages.push(item);
261
- }
262
- }
263
- return { messages: responseMessages, data: responseData };
264
- } else {
265
- const createdAt = /* @__PURE__ */ new Date();
266
- const decode = createChunkDecoder(false);
267
- let streamedResponse = "";
268
- const replyId = nanoid();
269
- let responseMessage = {
270
- id: replyId,
271
- createdAt,
272
- content: "",
273
- role: "assistant"
274
- };
275
- while (true) {
276
- const { done, value } = await reader.read();
277
- if (done) {
278
- break;
279
- }
280
- streamedResponse += decode(value);
281
- if (streamedResponse.startsWith('{"function_call":')) {
282
- responseMessage["function_call"] = streamedResponse;
283
- } else {
284
- responseMessage["content"] = streamedResponse;
285
- }
286
- mutate([...chatRequest.messages, { ...responseMessage }], false);
287
- if (abortControllerRef.current === null) {
288
- reader.cancel();
289
- break;
290
- }
291
- }
292
- if (streamedResponse.startsWith('{"function_call":')) {
293
- const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
294
- responseMessage["function_call"] = parsedFunctionCall;
295
- mutate([...chatRequest.messages, { ...responseMessage }]);
296
- }
297
- if (onFinish) {
298
- onFinish(responseMessage);
299
- }
300
- return responseMessage;
301
- }
302
473
  };
303
474
  function useChat({
304
475
  api = "/api/chat",
@@ -324,10 +495,7 @@ function useChat({
324
495
  [chatId, "loading"],
325
496
  null
326
497
  );
327
- const { data: streamData, mutate: mutateStreamData } = useSWR(
328
- [chatId, "streamData"],
329
- null
330
- );
498
+ const { data: streamData, mutate: mutateStreamData } = useSWR([chatId, "streamData"], null);
331
499
  const messagesRef = useRef(messages || []);
332
500
  useEffect(() => {
333
501
  messagesRef.current = messages || [];
@@ -353,8 +521,8 @@ function useChat({
353
521
  setError(void 0);
354
522
  const abortController = new AbortController();
355
523
  abortControllerRef.current = abortController;
356
- while (true) {
357
- const messagesAndDataOrJustMessage = await getStreamedResponse(
524
+ await processChatStream({
525
+ getStreamedResponse: () => getStreamedResponse(
358
526
  api,
359
527
  chatRequest,
360
528
  mutate,
@@ -366,47 +534,13 @@ function useChat({
366
534
  onFinish,
367
535
  onResponse,
368
536
  sendExtraMessageFields
369
- );
370
- if ("messages" in messagesAndDataOrJustMessage) {
371
- let hasFollowingResponse = false;
372
- for (const message of messagesAndDataOrJustMessage.messages) {
373
- if (message.function_call === void 0 || typeof message.function_call === "string") {
374
- continue;
375
- }
376
- hasFollowingResponse = true;
377
- if (experimental_onFunctionCall) {
378
- const functionCall = message.function_call;
379
- const functionCallResponse = await experimental_onFunctionCall(
380
- messagesRef.current,
381
- functionCall
382
- );
383
- if (functionCallResponse === void 0) {
384
- hasFollowingResponse = false;
385
- break;
386
- }
387
- chatRequest = functionCallResponse;
388
- }
389
- }
390
- if (!hasFollowingResponse) {
391
- break;
392
- }
393
- } else {
394
- const streamedResponseMessage = messagesAndDataOrJustMessage;
395
- if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
396
- break;
397
- }
398
- if (experimental_onFunctionCall) {
399
- const functionCall = streamedResponseMessage.function_call;
400
- const functionCallResponse = await experimental_onFunctionCall(
401
- messagesRef.current,
402
- functionCall
403
- );
404
- if (functionCallResponse === void 0)
405
- break;
406
- chatRequest = functionCallResponse;
407
- }
408
- }
409
- }
537
+ ),
538
+ experimental_onFunctionCall,
539
+ updateChatRequest: (chatRequestParam) => {
540
+ chatRequest = chatRequestParam;
541
+ },
542
+ getCurrentMessages: () => messagesRef.current
543
+ });
410
544
  abortControllerRef.current = null;
411
545
  } catch (err) {
412
546
  if (err.name === "AbortError") {
@@ -703,7 +837,115 @@ function useCompletion({
703
837
  isLoading
704
838
  };
705
839
  }
840
+
841
+ // react/use-assistant.ts
842
+ import { useState as useState3 } from "react";
843
+
844
+ // shared/process-message-stream.ts
845
+ async function processMessageStream(reader, processMessage) {
846
+ const decoder = new TextDecoder();
847
+ let buffer = "";
848
+ while (true) {
849
+ const { done, value } = await reader.read();
850
+ if (done) {
851
+ if (buffer.length > 0) {
852
+ processMessage(buffer);
853
+ }
854
+ break;
855
+ }
856
+ buffer += decoder.decode(value, { stream: true });
857
+ let endIndex;
858
+ while ((endIndex = buffer.indexOf("\n")) !== -1) {
859
+ processMessage(buffer.substring(0, endIndex).trim());
860
+ buffer = buffer.substring(endIndex + 1);
861
+ }
862
+ }
863
+ }
864
+
865
+ // react/use-assistant.ts
866
+ function experimental_useAssistant({
867
+ api,
868
+ threadId: threadIdParam
869
+ }) {
870
+ const [messages, setMessages] = useState3([]);
871
+ const [input, setInput] = useState3("");
872
+ const [threadId, setThreadId] = useState3(void 0);
873
+ const [status, setStatus] = useState3("awaiting_message");
874
+ const [error, setError] = useState3(void 0);
875
+ const handleInputChange = (e) => {
876
+ setInput(e.target.value);
877
+ };
878
+ const submitMessage = async (e) => {
879
+ var _a;
880
+ e.preventDefault();
881
+ if (input === "") {
882
+ return;
883
+ }
884
+ setStatus("in_progress");
885
+ setMessages((messages2) => [
886
+ ...messages2,
887
+ { id: "", role: "user", content: input }
888
+ ]);
889
+ setInput("");
890
+ const result = await fetch(api, {
891
+ method: "POST",
892
+ headers: { "Content-Type": "application/json" },
893
+ body: JSON.stringify({
894
+ // always use user-provided threadId when available:
895
+ threadId: (_a = threadIdParam != null ? threadIdParam : threadId) != null ? _a : null,
896
+ message: input
897
+ })
898
+ });
899
+ if (result.body == null) {
900
+ throw new Error("The response body is empty.");
901
+ }
902
+ await processMessageStream(result.body.getReader(), (message) => {
903
+ try {
904
+ const { type, value } = parseStreamPart(message);
905
+ switch (type) {
906
+ case "assistant_message": {
907
+ setMessages((messages2) => [
908
+ ...messages2,
909
+ {
910
+ id: value.id,
911
+ role: value.role,
912
+ content: value.content[0].text.value
913
+ }
914
+ ]);
915
+ break;
916
+ }
917
+ case "assistant_control_data": {
918
+ setThreadId(value.threadId);
919
+ setMessages((messages2) => {
920
+ const lastMessage = messages2[messages2.length - 1];
921
+ lastMessage.id = value.messageId;
922
+ return [...messages2.slice(0, messages2.length - 1), lastMessage];
923
+ });
924
+ break;
925
+ }
926
+ case "error": {
927
+ setError(value);
928
+ break;
929
+ }
930
+ }
931
+ } catch (error2) {
932
+ setError(error2);
933
+ }
934
+ });
935
+ setStatus("awaiting_message");
936
+ };
937
+ return {
938
+ messages,
939
+ threadId,
940
+ input,
941
+ handleInputChange,
942
+ submitMessage,
943
+ status,
944
+ error
945
+ };
946
+ }
706
947
  export {
948
+ experimental_useAssistant,
707
949
  useChat,
708
950
  useCompletion
709
951
  };