@assistant-ui/ai-sdk 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/adapters/aiSDKFormatAdapter.d.ts +2 -8
  2. package/dist/adapters/aiSDKFormatAdapter.js +1 -25
  3. package/dist/adapters/vercelAttachmentAdapter.d.ts +1 -2
  4. package/dist/adapters/vercelAttachmentAdapter.d.ts.map +1 -1
  5. package/dist/aiSDKExtras.d.ts +2 -3
  6. package/dist/aiSDKExtras.d.ts.map +1 -1
  7. package/dist/converters/convertMessage.d.ts +5 -4
  8. package/dist/converters/convertMessage.d.ts.map +1 -1
  9. package/dist/converters/convertMessage.js +40 -3
  10. package/dist/converters/convertMessage.js.map +1 -1
  11. package/dist/converters/modelContentEnvelope.d.ts +4 -5
  12. package/dist/converters/modelContentEnvelope.d.ts.map +1 -1
  13. package/dist/converters/toCreateMessage.d.ts +1 -2
  14. package/dist/converters/toCreateMessage.d.ts.map +1 -1
  15. package/dist/converters/toolOutputConversion.d.ts +2 -3
  16. package/dist/converters/toolOutputConversion.d.ts.map +1 -1
  17. package/dist/hooks.d.ts +2 -3
  18. package/dist/hooks.d.ts.map +1 -1
  19. package/dist/model-context/injectInteractableContext.d.ts +1 -2
  20. package/dist/model-context/injectInteractableContext.d.ts.map +1 -1
  21. package/dist/model-context/injectQuoteContext.d.ts +1 -2
  22. package/dist/model-context/injectQuoteContext.d.ts.map +1 -1
  23. package/dist/runtime/AISDKChat.d.ts +2 -3
  24. package/dist/runtime/AISDKChat.d.ts.map +1 -1
  25. package/dist/runtime/AISDKThreads.d.ts +2 -3
  26. package/dist/runtime/AISDKThreads.d.ts.map +1 -1
  27. package/dist/runtime/AISDKThreads.js +87 -68
  28. package/dist/runtime/AISDKThreads.js.map +1 -1
  29. package/dist/runtime/sdkIdentity.d.ts +5 -0
  30. package/dist/runtime/sdkIdentity.d.ts.map +1 -0
  31. package/dist/runtime/sdkIdentity.js +9 -0
  32. package/dist/runtime/sdkIdentity.js.map +1 -0
  33. package/dist/runtime/useAISDKRuntime.d.ts +17 -5
  34. package/dist/runtime/useAISDKRuntime.d.ts.map +1 -1
  35. package/dist/runtime/useAISDKRuntime.js +103 -38
  36. package/dist/runtime/useAISDKRuntime.js.map +1 -1
  37. package/dist/runtime/useChatRuntime.d.ts +2 -3
  38. package/dist/runtime/useChatRuntime.d.ts.map +1 -1
  39. package/dist/runtime/useChatRuntime.js +5 -1
  40. package/dist/runtime/useChatRuntime.js.map +1 -1
  41. package/dist/runtime/useChatThread.d.ts +19 -5
  42. package/dist/runtime/useChatThread.d.ts.map +1 -1
  43. package/dist/runtime/useChatThread.js +31 -10
  44. package/dist/runtime/useChatThread.js.map +1 -1
  45. package/dist/runtime/useExternalHistory.d.ts +2 -3
  46. package/dist/runtime/useExternalHistory.d.ts.map +1 -1
  47. package/dist/runtime/useExternalHistory.js +31 -20
  48. package/dist/runtime/useExternalHistory.js.map +1 -1
  49. package/dist/runtime/useResourceCleanup.d.ts +1 -2
  50. package/dist/runtime/useResourceCleanup.d.ts.map +1 -1
  51. package/dist/runtime/useStreamingTiming.d.ts +2 -3
  52. package/dist/runtime/useStreamingTiming.d.ts.map +1 -1
  53. package/dist/tools/frontendTools.d.ts +3 -4
  54. package/dist/tools/frontendTools.d.ts.map +1 -1
  55. package/dist/tools/generativeTools.d.ts +5 -6
  56. package/dist/tools/generativeTools.d.ts.map +1 -1
  57. package/dist/tools/mcp-stdio.unsupported.d.ts +1 -2
  58. package/dist/tools/mcp-stdio.unsupported.d.ts.map +1 -1
  59. package/dist/transport/AssistantChatTransport.d.ts +3 -4
  60. package/dist/transport/AssistantChatTransport.d.ts.map +1 -1
  61. package/dist/transport/resumable.d.ts +4 -5
  62. package/dist/transport/resumable.d.ts.map +1 -1
  63. package/dist/usage.d.ts +4 -5
  64. package/dist/usage.d.ts.map +1 -1
  65. package/dist/utils/getVercelAIMessages.d.ts +1 -2
  66. package/dist/utils/getVercelAIMessages.d.ts.map +1 -1
  67. package/dist/utils/sliceMessagesUntil.d.ts +1 -2
  68. package/dist/utils/sliceMessagesUntil.d.ts.map +1 -1
  69. package/package.json +15 -14
  70. package/src/adapters/aiSDKFormatAdapter.ts +4 -41
  71. package/src/converters/convertMessage.test.ts +152 -0
  72. package/src/converters/convertMessage.ts +95 -5
  73. package/src/runtime/AISDKChat.test.ts +4 -5
  74. package/src/runtime/AISDKThreads.cloud.test.ts +12 -3
  75. package/src/runtime/AISDKThreads.test.ts +140 -13
  76. package/src/runtime/AISDKThreads.ts +23 -4
  77. package/src/runtime/sdkIdentity.ts +9 -0
  78. package/src/runtime/useAISDKRuntime.approval.integration.test.tsx +287 -0
  79. package/src/runtime/useAISDKRuntime.approval.test.tsx +257 -1
  80. package/src/runtime/useAISDKRuntime.test.ts +46 -4
  81. package/src/runtime/useAISDKRuntime.ts +164 -24
  82. package/src/runtime/useAISDKRuntime.voice.test.tsx +270 -0
  83. package/src/runtime/useChatRuntime.test.ts +72 -5
  84. package/src/runtime/useChatRuntime.ts +2 -1
  85. package/src/runtime/useChatThread.test.ts +74 -0
  86. package/src/runtime/useChatThread.ts +45 -6
  87. package/src/runtime/useExternalHistory.test.ts +75 -0
  88. package/src/runtime/useExternalHistory.ts +28 -11
  89. package/src/tools/generativeTools.test.ts +7 -1
  90. package/src/transport/AssistantChatTransport.test.ts +1 -9
  91. package/dist/adapters/aiSDKFormatAdapter.d.ts.map +0 -1
  92. package/dist/adapters/aiSDKFormatAdapter.js.map +0 -1
@@ -9,6 +9,7 @@ import {
9
9
  } from "@assistant-ui/core/react";
10
10
  import { useAui, useAuiState } from "@assistant-ui/store";
11
11
  import { useChatThread, type ChatThreadOptions } from "./useChatThread";
12
+ import { AI_SDK_SDK } from "./sdkIdentity";
12
13
 
13
14
  export type UseChatRuntimeOptions<UI_MESSAGE extends UIMessage = UIMessage> =
14
15
  ChatThreadOptions<UI_MESSAGE> & {
@@ -38,7 +39,7 @@ export const useChatRuntime = <UI_MESSAGE extends UIMessage = UIMessage>({
38
39
  onThreadIdChange,
39
40
  ...options
40
41
  }: UseChatRuntimeOptions<UI_MESSAGE> = {}): AssistantRuntime => {
41
- const cloudAdapter = useCloudThreadListAdapter({ cloud });
42
+ const cloudAdapter = useCloudThreadListAdapter({ cloud, sdk: AI_SDK_SDK });
42
43
  return useRemoteThreadListRuntime({
43
44
  runtimeHook: function RuntimeHook() {
44
45
  return useChatThreadRuntime(options);
@@ -0,0 +1,74 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { describe, expect, it, vi } from "vitest";
4
+ import { resource, useResource, flushTapSync } from "@assistant-ui/tap";
5
+ import { useState } from "react";
6
+ import {
7
+ RuntimeAdapter,
8
+ runtimeAdapterTransformScopes,
9
+ } from "@assistant-ui/core/store";
10
+ import {
11
+ attachTransformScopes,
12
+ AuiConfig,
13
+ createAssistantClient,
14
+ } from "@assistant-ui/store/client";
15
+ import { useChatThread, type ChatThreadEnvironment } from "./useChatThread";
16
+ import {
17
+ createCancellableTransport,
18
+ nextTask,
19
+ } from "./__tests__/controlled-transport";
20
+
21
+ const createHost = (
22
+ env: Pick<ChatThreadEnvironment, "stopOnClientDestroy">,
23
+ ) => {
24
+ const useHost = (options: Parameters<typeof useChatThread>[0]) => {
25
+ const [threadListItem] = useState(() => ({
26
+ initialize: async () => ({ remoteId: "main", externalId: undefined }),
27
+ }));
28
+ const runtime = useChatThread(options, {
29
+ id: "main",
30
+ isMainThread: true,
31
+ getThreadListItem: () => threadListItem,
32
+ ...env,
33
+ });
34
+ return useResource(RuntimeAdapter(runtime));
35
+ };
36
+ attachTransformScopes(useHost, runtimeAdapterTransformScopes);
37
+ return resource(useHost);
38
+ };
39
+
40
+ const streamThenDestroy = async (
41
+ env: Pick<ChatThreadEnvironment, "stopOnClientDestroy">,
42
+ ) => {
43
+ const { transport, getCancelCount, close } = createCancellableTransport();
44
+ const Host = createHost(env);
45
+ const handle = createAssistantClient(
46
+ AuiConfig({ threads: Host({ transport }) }),
47
+ );
48
+ handle.subscribe(() => {});
49
+ const aui = handle.getClient();
50
+
51
+ try {
52
+ flushTapSync(() => aui.composer.setText("stop me"));
53
+ flushTapSync(() => aui.composer.send());
54
+ await vi.waitFor(() => {
55
+ expect(aui.thread.getState().isRunning).toBe(true);
56
+ });
57
+ } finally {
58
+ handle.destroy();
59
+ }
60
+ await nextTask();
61
+ const cancelCount = getCancelCount();
62
+ if (cancelCount === 0) close();
63
+ return cancelCount;
64
+ };
65
+
66
+ describe("useChatThread", () => {
67
+ it("stops an in-flight chat on client destroy when stopOnClientDestroy is omitted", async () => {
68
+ expect(await streamThenDestroy({})).toBe(1);
69
+ });
70
+
71
+ it("leaves an in-flight chat running on client destroy when stopOnClientDestroy is false", async () => {
72
+ expect(await streamThenDestroy({ stopOnClientDestroy: false })).toBe(0);
73
+ });
74
+ });
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { useChat, type Chat, type UIMessage } from "@ai-sdk/react";
3
+ import { Chat, useChat, type UIMessage } from "@ai-sdk/react";
4
4
  import type { MessageRepository } from "@assistant-ui/core/internal";
5
5
  import {
6
6
  pickExternalStoreSharedOptions,
@@ -26,6 +26,7 @@ import {
26
26
  useEffect,
27
27
  useMemo,
28
28
  useRef,
29
+ useState,
29
30
  useSyncExternalStore,
30
31
  } from "react";
31
32
  import { useResourceCleanup } from "./useResourceCleanup";
@@ -38,6 +39,7 @@ export type ChatThreadOptions<UI_MESSAGE extends UIMessage = UIMessage> =
38
39
  toCreateMessage?: CustomToCreateMessageFunction;
39
40
  onResume?: AISDKRuntimeAdapter["onResume"];
40
41
  onResumeToolCall?: AISDKRuntimeAdapter["onResumeToolCall"];
42
+ onRespondToToolApproval?: AISDKRuntimeAdapter["onRespondToToolApproval"];
41
43
  /**
42
44
  * Called when an automatic resumable stream reconnect fails. Use this to
43
45
  * surface a toast, report telemetry, or mark the thread as needing a
@@ -140,6 +142,7 @@ export const splitChatThreadOptions = <UI_MESSAGE extends UIMessage>(
140
142
  suggestions: _suggestions,
141
143
  onResume,
142
144
  onResumeToolCall,
145
+ onRespondToToolApproval,
143
146
  onResumeError,
144
147
  joinStrategy,
145
148
  messageRepository,
@@ -158,6 +161,7 @@ export const splitChatThreadOptions = <UI_MESSAGE extends UIMessage>(
158
161
  toCreateMessage,
159
162
  onResume,
160
163
  onResumeToolCall,
164
+ onRespondToToolApproval,
161
165
  onResumeError,
162
166
  joinStrategy,
163
167
  messageRepository,
@@ -166,6 +170,30 @@ export const splitChatThreadOptions = <UI_MESSAGE extends UIMessage>(
166
170
  };
167
171
  };
168
172
 
173
+ type ChatCallbacks<UI_MESSAGE extends UIMessage> = Pick<
174
+ ChatInit<UI_MESSAGE>,
175
+ "onToolCall" | "onData" | "onFinish" | "onError" | "sendAutomaticallyWhen"
176
+ >;
177
+
178
+ /**
179
+ * Constructs a `Chat` whose callbacks read the latest options through
180
+ * `callbacksRef`, the forwarding `useChat` applies only to a chat it
181
+ * constructs itself.
182
+ */
183
+ export const createChat = <UI_MESSAGE extends UIMessage>(
184
+ init: ChatInit<UI_MESSAGE>,
185
+ callbacksRef: { readonly current: ChatCallbacks<UI_MESSAGE> | undefined },
186
+ ): Chat<UI_MESSAGE> =>
187
+ new Chat<UI_MESSAGE>({
188
+ ...init,
189
+ onToolCall: (arg) => callbacksRef.current?.onToolCall?.(arg),
190
+ onData: (arg) => callbacksRef.current?.onData?.(arg),
191
+ onFinish: (arg) => callbacksRef.current?.onFinish?.(arg),
192
+ onError: (arg) => callbacksRef.current?.onError?.(arg),
193
+ sendAutomaticallyWhen: (arg) =>
194
+ callbacksRef.current?.sendAutomaticallyWhen?.(arg) ?? false,
195
+ });
196
+
169
197
  export const useChatThread = <UI_MESSAGE extends UIMessage = UIMessage>(
170
198
  options: ChatThreadOptions<UI_MESSAGE> | undefined,
171
199
  env: ChatThreadEnvironment<UI_MESSAGE>,
@@ -177,6 +205,7 @@ export const useChatThread = <UI_MESSAGE extends UIMessage = UIMessage>(
177
205
  toCreateMessage,
178
206
  onResume,
179
207
  onResumeToolCall,
208
+ onRespondToToolApproval,
180
209
  onResumeError,
181
210
  joinStrategy,
182
211
  messageRepository,
@@ -188,7 +217,7 @@ export const useChatThread = <UI_MESSAGE extends UIMessage = UIMessage>(
188
217
  id,
189
218
  isMainThread,
190
219
  getThreadListItem,
191
- stopOnClientDestroy = false,
220
+ stopOnClientDestroy = true,
192
221
  chat: externalChat,
193
222
  messageRepositoryInstance,
194
223
  } = env;
@@ -197,12 +226,21 @@ export const useChatThread = <UI_MESSAGE extends UIMessage = UIMessage>(
197
226
  const sourceTransport = transportOptions ?? defaultTransport;
198
227
  const transport = useDynamicChatTransport(sourceTransport);
199
228
 
229
+ const latestChatOptionsRef = useRef(chatOptions);
230
+ useEffect(() => {
231
+ latestChatOptionsRef.current = chatOptions;
232
+ });
233
+ // `useChat` stops a chat it constructs whenever it unmounts, and a
234
+ // resource's soft unmount runs that cleanup, so the thread owns its chat.
235
+ const [ownedChat] = useState(
236
+ () =>
237
+ externalChat ??
238
+ createChat({ ...chatOptions, id, transport }, latestChatOptionsRef),
239
+ );
240
+
200
241
  const chat = useChat({
201
- ...chatOptions,
202
- id,
203
- transport,
242
+ chat: externalChat ?? ownedChat,
204
243
  ...(throttle !== undefined && { throttle }),
205
- ...(externalChat !== undefined && { chat: externalChat }),
206
244
  });
207
245
 
208
246
  useResourceCleanup(stopOnClientDestroy, () => {
@@ -215,6 +253,7 @@ export const useChatThread = <UI_MESSAGE extends UIMessage = UIMessage>(
215
253
  ...(toCreateMessage && { toCreateMessage }),
216
254
  ...(onResume && { onResume }),
217
255
  ...(onResumeToolCall && { onResumeToolCall }),
256
+ ...(onRespondToToolApproval && { onRespondToToolApproval }),
218
257
  ...(joinStrategy && { joinStrategy }),
219
258
  ...(messageRepository && { messageRepository }),
220
259
  ...(messageRepositoryInstance && {
@@ -498,6 +498,52 @@ describe("useExternalHistory persistence", () => {
498
498
  };
499
499
  };
500
500
 
501
+ it("persists a message that lands while the thread is idle", async () => {
502
+ const { append, step } = createPersistenceHarness(false);
503
+ const message = createAssistantMessage(
504
+ { type: "complete", reason: "stop" },
505
+ [{ id: "spoken-1", parts: ["spoken"] }],
506
+ );
507
+
508
+ await step({ messages: [message] });
509
+
510
+ await waitFor(() => expect(append).toHaveBeenCalledTimes(1));
511
+ expect(append).toHaveBeenCalledWith({
512
+ parentId: null,
513
+ message: { id: "spoken-1", parts: ["spoken"] },
514
+ });
515
+ });
516
+
517
+ it("schedules one idle persistence attempt per landed message when append fails", async () => {
518
+ const { append, step, flush } = createPersistenceHarness(false);
519
+ append.mockRejectedValueOnce(new Error("offline"));
520
+ const first = createAssistantMessage(
521
+ { type: "complete", reason: "stop" },
522
+ [{ id: "spoken-1", parts: ["first"] }],
523
+ "assistant-a",
524
+ );
525
+
526
+ await step({ messages: [first] });
527
+ await waitFor(() => expect(append).toHaveBeenCalledTimes(1));
528
+ await step({ messages: [first] });
529
+ await step({ messages: [first] });
530
+ await flush();
531
+ expect(append).toHaveBeenCalledTimes(1);
532
+
533
+ const second = createAssistantMessage(
534
+ { type: "complete", reason: "stop" },
535
+ [{ id: "spoken-2", parts: ["second"] }],
536
+ "assistant-b",
537
+ );
538
+ await step({ messages: [first, second] });
539
+ await waitFor(() => expect(append).toHaveBeenCalledTimes(3));
540
+ expect(append.mock.calls.map(([item]) => item)).toEqual([
541
+ { parentId: null, message: { id: "spoken-1", parts: ["first"] } },
542
+ { parentId: null, message: { id: "spoken-1", parts: ["first"] } },
543
+ { parentId: "spoken-1", message: { id: "spoken-2", parts: ["second"] } },
544
+ ]);
545
+ });
546
+
501
547
  it("persists a settled turn when the history adapter becomes active after it", async () => {
502
548
  let listener: (() => void) | undefined;
503
549
  let isRunning = false;
@@ -780,6 +826,35 @@ describe("useExternalHistory persistence", () => {
780
826
  ],
781
827
  expect.any(Object),
782
828
  );
829
+ expect(reportTelemetry.mock.calls[0]![1]).toMatchObject({
830
+ message: expect.objectContaining({
831
+ id: "assistant-a",
832
+ status: { type: "complete", reason: "stop" },
833
+ }),
834
+ });
835
+ });
836
+
837
+ it("reports a run that failed before any assistant message", async () => {
838
+ const { append, reportTelemetry, runCycle, flush } =
839
+ createPersistenceHarness(true);
840
+ const failed = createAssistantMessage(
841
+ {
842
+ type: "incomplete",
843
+ reason: "error",
844
+ error: { code: "AI_APICallError", message: "upstream failed" },
845
+ },
846
+ [],
847
+ );
848
+
849
+ await runCycle([failed]);
850
+ await flush();
851
+
852
+ expect(append).not.toHaveBeenCalled();
853
+ expect(reportTelemetry).toHaveBeenCalledTimes(1);
854
+ expect(reportTelemetry).toHaveBeenCalledWith(
855
+ [],
856
+ expect.objectContaining({ message: failed }),
857
+ );
783
858
  });
784
859
 
785
860
  it("restores deferred telemetry for reloaded paused messages", async () => {
@@ -50,6 +50,11 @@ const isAwaitingToolApproval = (message: ThreadMessage) =>
50
50
  message.status?.type === "requires-action" &&
51
51
  message.status.reason === "tool-calls";
52
52
 
53
+ const isTerminalMessage = (message: ThreadMessage) =>
54
+ message.status === undefined ||
55
+ message.status.type === "complete" ||
56
+ message.status.type === "incomplete";
57
+
53
58
  const encodeContent = <TMessage>(
54
59
  storageFormatAdapter: MessageFormatAdapter<TMessage, any>,
55
60
  item: MessageFormatItem<TMessage>,
@@ -185,6 +190,14 @@ export const useExternalHistory = <TMessage>(
185
190
  if (!formatAdapter) return;
186
191
  const adapter = formatAdapter;
187
192
 
193
+ const idleScheduledInnerIds = new Set<string>();
194
+ const unpersistedInnerIds = (message: ThreadMessage) =>
195
+ isTerminalMessage(message)
196
+ ? getExternalStoreMessages<TMessage>(message)
197
+ .map((innerMessage) => storageFormatAdapter.getId(innerMessage))
198
+ .filter((innerId) => !persistedInnerMessages.current.has(innerId))
199
+ : [];
200
+
188
201
  const unsubscribe = runtimeRef.current.thread.subscribe(() => {
189
202
  const threadState = runtimeRef.current.thread.getState();
190
203
  const { isRunning } = threadState;
@@ -220,12 +233,16 @@ export const useExternalHistory = <TMessage>(
220
233
  return;
221
234
  }
222
235
 
223
- // Only act on the true→false transition
224
- if (!wasRunning) return;
225
-
226
- // Record step boundary offset (synchronous for accuracy)
227
- if (runStartRef.current != null) {
228
- stepBoundariesRef.current.push(Date.now() - runStartRef.current);
236
+ if (wasRunning) {
237
+ // Record step boundary offset (synchronous for accuracy)
238
+ if (runStartRef.current != null) {
239
+ stepBoundariesRef.current.push(Date.now() - runStartRef.current);
240
+ }
241
+ } else {
242
+ const pending = threadState.messages.flatMap(unpersistedInnerIds);
243
+ if (pending.every((innerId) => idleScheduledInnerIds.has(innerId)))
244
+ return;
245
+ for (const innerId of pending) idleScheduledInnerIds.add(innerId);
229
246
  }
230
247
 
231
248
  // Debounce: wait one macrotask so agentic step flickers are absorbed
@@ -313,10 +330,7 @@ export const useExternalHistory = <TMessage>(
313
330
  for (const message of messages) {
314
331
  const innerMessages = getExternalStoreMessages<TMessage>(message);
315
332
 
316
- const isTerminal =
317
- message.status === undefined ||
318
- message.status.type === "complete" ||
319
- message.status.type === "incomplete";
333
+ const isTerminal = isTerminalMessage(message);
320
334
  const isAwaitingToolCalls = isAwaitingToolApproval(message);
321
335
  // A paused message's later content can only reach storage via update, so it is persisted early only when the adapter supports update.
322
336
  const isReady =
@@ -371,7 +385,10 @@ export const useExternalHistory = <TMessage>(
371
385
 
372
386
  if (deferredTelemetryIds.current.has(message.id) && isTerminal) {
373
387
  deferredTelemetryIds.current.delete(message.id);
374
- adapter.reportTelemetry?.(batchItems, telemetryOptions);
388
+ adapter.reportTelemetry?.(batchItems, {
389
+ ...telemetryOptions,
390
+ message,
391
+ });
375
392
  }
376
393
  }
377
394
  })
@@ -623,8 +623,14 @@ describe("AISDKToolkit", () => {
623
623
  toolCallId: "call-docs-search",
624
624
  messages: [],
625
625
  };
626
+ const execute = toolSet.docs_search?.execute as
627
+ | ((
628
+ args: { query: string },
629
+ options: typeof executeOptions,
630
+ ) => Promise<string>)
631
+ | undefined;
626
632
  await expect(
627
- toolSet.docs_search?.execute?.({ query: "assistant-ui" }, executeOptions),
633
+ execute?.({ query: "assistant-ui" }, executeOptions),
628
634
  ).resolves.toBe("docs result");
629
635
  expect(docsExecute).toHaveBeenCalledWith(
630
636
  { query: "assistant-ui" },
@@ -1,5 +1,5 @@
1
1
  import type { UIMessage } from "ai";
2
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { describe, expect, it, vi } from "vitest";
3
3
 
4
4
  import { RESUMABLE_STREAM_ID_HEADER } from "./resumable";
5
5
  import { AssistantChatTransport } from "./AssistantChatTransport";
@@ -26,10 +26,6 @@ const sendMessagesOptions = {
26
26
  };
27
27
 
28
28
  describe("AssistantChatTransport.prepareSendMessagesRequest", () => {
29
- beforeEach(() => {
30
- vi.clearAllMocks();
31
- });
32
-
33
29
  it("passes the initialized remote thread id to prepareSendMessagesRequest as options.id", async () => {
34
30
  const threadListItem = createThreadListItem("remote-thread-id");
35
31
  const captured: { id: unknown } = { id: undefined };
@@ -209,10 +205,6 @@ const wrappedFetchOf = (
209
205
  ).fetch;
210
206
 
211
207
  describe("AssistantChatTransport resumable fetch wrapper", () => {
212
- beforeEach(() => {
213
- vi.clearAllMocks();
214
- });
215
-
216
208
  it("passes a 204 with a non-null empty body through untouched (WebKit)", async () => {
217
209
  const response = nullBodyStatusWithBody(204);
218
210
  const fetchMock = vi.fn(async () => response);
@@ -1 +0,0 @@
1
- {"version":3,"file":"aiSDKFormatAdapter.d.ts","names":[],"sources":["../../src/adapters/aiSDKFormatAdapter.ts"],"mappings":";;;KAQY,qBAAqB,KAAK;cAEzB,sBAAsB,qBACjC,WACA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"aiSDKFormatAdapter.js","names":["UIMessage","MessageFormatAdapter","MessageFormatItem","MessageStorageEntry","AISDKStorageFormat","Omit","aiSDKV6FormatAdapter","format","encode","message","id","parts","decode","stored","parentId","parent_id","content","getId"],"sources":["../../src/adapters/aiSDKFormatAdapter.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\nimport type {\n MessageFormatAdapter,\n MessageFormatItem,\n MessageStorageEntry,\n} from \"@assistant-ui/core\";\n\n// Storage format for AI SDK messages - just the UIMessage\nexport type AISDKStorageFormat = Omit<UIMessage, \"id\">;\n\nexport const aiSDKV6FormatAdapter: MessageFormatAdapter<\n UIMessage,\n AISDKStorageFormat\n> = {\n format: \"ai-sdk/v6\",\n\n encode({\n message: { id, parts, ...message },\n }: MessageFormatItem<UIMessage>): AISDKStorageFormat {\n return {\n ...message,\n parts,\n };\n },\n\n decode(\n stored: MessageStorageEntry<AISDKStorageFormat>,\n ): MessageFormatItem<UIMessage> {\n return {\n parentId: stored.parent_id,\n message: {\n id: stored.id,\n ...stored.content,\n },\n };\n },\n\n getId(message: UIMessage): string {\n return message.id;\n },\n};\n"],"mappings":";AAUA,MAAaM,uBAGT;CACFC,QAAQ;CAERC,OAAO,EACLC,SAAS,EAAEC,IAAIC,OAAO,GAAGF,aAC0B;EACnD,OAAO;GACL,GAAGA;GACHE;EACF;CACF;CAEAC,OACEC,QAC8B;EAC9B,OAAO;GACLC,UAAUD,OAAOE;GACjBN,SAAS;IACPC,IAAIG,OAAOH;IACX,GAAGG,OAAOG;GACZ;EACF;CACF;CAEAC,MAAMR,SAA4B;EAChC,OAAOA,QAAQC;CACjB;AACF"}