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.
@@ -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,50 +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
- if (firstSeperatorIndex === -1) {
72
- throw new Error("Failed to parse stream string");
73
- }
74
- const prefix = line.slice(0, firstSeperatorIndex);
75
- const type = Object.keys(StreamStringPrefixes).find(
76
- (key) => StreamStringPrefixes[key] === Number(prefix)
77
- );
78
- const val = line.slice(firstSeperatorIndex + 1);
79
- let parsedVal = val;
80
- if (!val) {
81
- return { type, value: "" };
82
- }
83
- try {
84
- parsedVal = JSON.parse(val);
85
- } catch (e) {
86
- console.error("Failed to parse JSON value:", val);
87
- }
88
- return { type, value: parsedVal };
89
- };
90
187
  var COMPLEX_HEADER = "X-Experimental-Stream-Data";
91
188
 
92
- // react/parse-complex-response.ts
189
+ // shared/call-api.ts
190
+ var import_nanoid = require("nanoid");
191
+
192
+ // shared/parse-complex-response.ts
93
193
  async function parseComplexResponse({
94
194
  reader,
95
195
  abortControllerRef,
96
196
  update,
97
- onFinish
197
+ onFinish,
198
+ generateId = nanoid,
199
+ getCurrentDate = () => /* @__PURE__ */ new Date()
98
200
  }) {
201
+ const createdAt = getCurrentDate();
99
202
  const decode = createChunkDecoder(true);
100
- const createdAt = /* @__PURE__ */ new Date();
101
- const prefixMap = {};
203
+ const prefixMap = {
204
+ data: []
205
+ };
102
206
  const NEWLINE = "\n".charCodeAt(0);
103
- let chunks = [];
207
+ const chunks = [];
104
208
  let totalLength = 0;
105
209
  while (true) {
106
210
  const { value } = await reader.read();
@@ -137,7 +241,7 @@ async function parseComplexResponse({
137
241
  };
138
242
  } else {
139
243
  prefixMap["text"] = {
140
- id: nanoid(),
244
+ id: generateId(),
141
245
  role: "assistant",
142
246
  content: value2,
143
247
  createdAt
@@ -146,37 +250,24 @@ async function parseComplexResponse({
146
250
  }
147
251
  let functionCallMessage = null;
148
252
  if (type === "function_call") {
149
- prefixMap["function_call"] = value2;
150
- let functionCall = prefixMap["function_call"];
151
- if (functionCall && typeof functionCall === "string") {
152
- const parsedFunctionCall = JSON.parse(
153
- functionCall
154
- ).function_call;
155
- functionCallMessage = {
156
- id: nanoid(),
157
- role: "assistant",
158
- content: "",
159
- function_call: parsedFunctionCall,
160
- name: parsedFunctionCall.name,
161
- createdAt
162
- };
163
- prefixMap["function_call"] = functionCallMessage;
164
- }
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"];
165
262
  }
166
263
  if (type === "data") {
167
- const parsedValue = JSON.parse(value2);
168
- if (prefixMap["data"]) {
169
- prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
170
- } else {
171
- prefixMap["data"] = parsedValue;
172
- }
264
+ prefixMap["data"].push(...value2);
173
265
  }
174
- const data = prefixMap["data"];
175
266
  const responseMessage = prefixMap["text"];
176
267
  const merged = [functionCallMessage, responseMessage].filter(
177
268
  Boolean
178
269
  );
179
- update(merged, data);
270
+ update(merged, [...prefixMap["data"]]);
180
271
  if ((abortControllerRef == null ? void 0 : abortControllerRef.current) === null) {
181
272
  reader.cancel();
182
273
  break;
@@ -184,7 +275,157 @@ async function parseComplexResponse({
184
275
  }
185
276
  }
186
277
  onFinish == null ? void 0 : onFinish(prefixMap);
187
- return 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) {
367
+ reader.cancel();
368
+ break;
369
+ }
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
+ }
428
+ }
188
429
  }
189
430
 
190
431
  // react/use-chat.ts
@@ -233,10 +474,10 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
233
474
  }
234
475
  return responseMessage;
235
476
  }
236
- const res = await fetch(api, {
237
- method: "POST",
238
- body: JSON.stringify({
239
- messages: constructedMessagesPayload,
477
+ return await callApi({
478
+ api,
479
+ messages: constructedMessagesPayload,
480
+ body: {
240
481
  data: chatRequest.data,
241
482
  ...extraMetadataRef.current.body,
242
483
  ...(_a = chatRequest.options) == null ? void 0 : _a.body,
@@ -246,95 +487,26 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
246
487
  ...chatRequest.function_call !== void 0 && {
247
488
  function_call: chatRequest.function_call
248
489
  }
249
- }),
490
+ },
250
491
  credentials: extraMetadataRef.current.credentials,
251
492
  headers: {
252
493
  ...extraMetadataRef.current.headers,
253
494
  ...(_b = chatRequest.options) == null ? void 0 : _b.headers
254
495
  },
255
- ...abortControllerRef.current !== null && {
256
- signal: abortControllerRef.current.signal
257
- }
258
- }).catch((err) => {
259
- mutate(previousMessages, false);
260
- 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
261
509
  });
262
- if (onResponse) {
263
- try {
264
- await onResponse(res);
265
- } catch (err) {
266
- throw err;
267
- }
268
- }
269
- if (!res.ok) {
270
- mutate(previousMessages, false);
271
- throw new Error(await res.text() || "Failed to fetch the chat response.");
272
- }
273
- if (!res.body) {
274
- throw new Error("The response body is empty.");
275
- }
276
- const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
277
- let responseMessages = [];
278
- const reader = res.body.getReader();
279
- let responseData = [];
280
- if (isComplexMode) {
281
- const prefixMap = await parseComplexResponse({
282
- reader,
283
- abortControllerRef,
284
- update(merged, data) {
285
- mutate([...chatRequest.messages, ...merged], false);
286
- mutateStreamData([...existingData || [], ...data || []], false);
287
- }
288
- });
289
- for (const [type, item] of Object.entries(prefixMap)) {
290
- if (onFinish && type === "text") {
291
- onFinish(item);
292
- }
293
- if (type === "data") {
294
- responseData.push(item);
295
- } else {
296
- responseMessages.push(item);
297
- }
298
- }
299
- return { messages: responseMessages, data: responseData };
300
- } else {
301
- const createdAt = /* @__PURE__ */ new Date();
302
- const decode = createChunkDecoder(false);
303
- let streamedResponse = "";
304
- const replyId = nanoid();
305
- let responseMessage = {
306
- id: replyId,
307
- createdAt,
308
- content: "",
309
- role: "assistant"
310
- };
311
- while (true) {
312
- const { done, value } = await reader.read();
313
- if (done) {
314
- break;
315
- }
316
- streamedResponse += decode(value);
317
- if (streamedResponse.startsWith('{"function_call":')) {
318
- responseMessage["function_call"] = streamedResponse;
319
- } else {
320
- responseMessage["content"] = streamedResponse;
321
- }
322
- mutate([...chatRequest.messages, { ...responseMessage }], false);
323
- if (abortControllerRef.current === null) {
324
- reader.cancel();
325
- break;
326
- }
327
- }
328
- if (streamedResponse.startsWith('{"function_call":')) {
329
- const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
330
- responseMessage["function_call"] = parsedFunctionCall;
331
- mutate([...chatRequest.messages, { ...responseMessage }]);
332
- }
333
- if (onFinish) {
334
- onFinish(responseMessage);
335
- }
336
- return responseMessage;
337
- }
338
510
  };
339
511
  function useChat({
340
512
  api = "/api/chat",
@@ -360,10 +532,7 @@ function useChat({
360
532
  [chatId, "loading"],
361
533
  null
362
534
  );
363
- const { data: streamData, mutate: mutateStreamData } = (0, import_swr.default)(
364
- [chatId, "streamData"],
365
- null
366
- );
535
+ const { data: streamData, mutate: mutateStreamData } = (0, import_swr.default)([chatId, "streamData"], null);
367
536
  const messagesRef = (0, import_react.useRef)(messages || []);
368
537
  (0, import_react.useEffect)(() => {
369
538
  messagesRef.current = messages || [];
@@ -389,8 +558,8 @@ function useChat({
389
558
  setError(void 0);
390
559
  const abortController = new AbortController();
391
560
  abortControllerRef.current = abortController;
392
- while (true) {
393
- const messagesAndDataOrJustMessage = await getStreamedResponse(
561
+ await processChatStream({
562
+ getStreamedResponse: () => getStreamedResponse(
394
563
  api,
395
564
  chatRequest,
396
565
  mutate,
@@ -402,47 +571,13 @@ function useChat({
402
571
  onFinish,
403
572
  onResponse,
404
573
  sendExtraMessageFields
405
- );
406
- if ("messages" in messagesAndDataOrJustMessage) {
407
- let hasFollowingResponse = false;
408
- for (const message of messagesAndDataOrJustMessage.messages) {
409
- if (message.function_call === void 0 || typeof message.function_call === "string") {
410
- continue;
411
- }
412
- hasFollowingResponse = true;
413
- if (experimental_onFunctionCall) {
414
- const functionCall = message.function_call;
415
- const functionCallResponse = await experimental_onFunctionCall(
416
- messagesRef.current,
417
- functionCall
418
- );
419
- if (functionCallResponse === void 0) {
420
- hasFollowingResponse = false;
421
- break;
422
- }
423
- chatRequest = functionCallResponse;
424
- }
425
- }
426
- if (!hasFollowingResponse) {
427
- break;
428
- }
429
- } else {
430
- const streamedResponseMessage = messagesAndDataOrJustMessage;
431
- if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
432
- break;
433
- }
434
- if (experimental_onFunctionCall) {
435
- const functionCall = streamedResponseMessage.function_call;
436
- const functionCallResponse = await experimental_onFunctionCall(
437
- messagesRef.current,
438
- functionCall
439
- );
440
- if (functionCallResponse === void 0)
441
- break;
442
- chatRequest = functionCallResponse;
443
- }
444
- }
445
- }
574
+ ),
575
+ experimental_onFunctionCall,
576
+ updateChatRequest: (chatRequestParam) => {
577
+ chatRequest = chatRequestParam;
578
+ },
579
+ getCurrentMessages: () => messagesRef.current
580
+ });
446
581
  abortControllerRef.current = null;
447
582
  } catch (err) {
448
583
  if (err.name === "AbortError") {
@@ -739,8 +874,116 @@ function useCompletion({
739
874
  isLoading
740
875
  };
741
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
+ threadId,
977
+ input,
978
+ handleInputChange,
979
+ submitMessage,
980
+ status,
981
+ error
982
+ };
983
+ }
742
984
  // Annotate the CommonJS export names for ESM import in node:
743
985
  0 && (module.exports = {
986
+ experimental_useAssistant,
744
987
  useChat,
745
988
  useCompletion
746
989
  });