@assistant-ui/react 0.14.27 → 0.14.29

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 (257) hide show
  1. package/dist/client/ExternalThread.d.ts +11 -1
  2. package/dist/client/ExternalThread.d.ts.map +1 -1
  3. package/dist/client/ExternalThread.js +758 -513
  4. package/dist/client/ExternalThread.js.map +1 -1
  5. package/dist/context/react/utils/createContextStoreHook.d.ts.map +1 -1
  6. package/dist/context/react/utils/createStateHookForRuntime.d.ts.map +1 -1
  7. package/dist/legacy-runtime/AssistantRuntimeProvider.js.map +1 -1
  8. package/dist/legacy-runtime/cloud/auiV0.d.ts +12 -1
  9. package/dist/legacy-runtime/cloud/auiV0.d.ts.map +1 -1
  10. package/dist/legacy-runtime/cloud/auiV0.js +2 -1
  11. package/dist/legacy-runtime/cloud/auiV0.js.map +1 -1
  12. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.d.ts +1 -1
  13. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.d.ts.map +1 -1
  14. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.js +7 -6
  15. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.js.map +1 -1
  16. package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.d.ts.map +1 -1
  17. package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.js +30 -15
  18. package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.js.map +1 -1
  19. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -1
  20. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +8 -4
  21. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
  22. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.js +1 -0
  23. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.js.map +1 -1
  24. package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  25. package/dist/model-context/makeAssistantVisible.d.ts.map +1 -1
  26. package/dist/model-context/makeAssistantVisible.js +7 -1
  27. package/dist/model-context/makeAssistantVisible.js.map +1 -1
  28. package/dist/primitives/actionBar/ActionBarCopy.d.ts.map +1 -1
  29. package/dist/primitives/actionBar/ActionBarEdit.d.ts.map +1 -1
  30. package/dist/primitives/actionBar/ActionBarExportMarkdown.d.ts.map +1 -1
  31. package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts.map +1 -1
  32. package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts.map +1 -1
  33. package/dist/primitives/actionBar/ActionBarReload.d.ts.map +1 -1
  34. package/dist/primitives/actionBar/ActionBarRoot.d.ts.map +1 -1
  35. package/dist/primitives/actionBar/ActionBarRoot.js +3 -3
  36. package/dist/primitives/actionBar/ActionBarRoot.js.map +1 -1
  37. package/dist/primitives/actionBar/ActionBarSpeak.d.ts.map +1 -1
  38. package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts.map +1 -1
  39. package/dist/primitives/actionBar/useActionBarFloatStatus.d.ts +7 -6
  40. package/dist/primitives/actionBar/useActionBarFloatStatus.d.ts.map +1 -1
  41. package/dist/primitives/actionBar/useActionBarFloatStatus.js +10 -11
  42. package/dist/primitives/actionBar/useActionBarFloatStatus.js.map +1 -1
  43. package/dist/primitives/actionBarMore/ActionBarMoreContent.d.ts.map +1 -1
  44. package/dist/primitives/actionBarMore/ActionBarMoreContent.js.map +1 -1
  45. package/dist/primitives/actionBarMore/ActionBarMoreItem.d.ts.map +1 -1
  46. package/dist/primitives/actionBarMore/ActionBarMoreSeparator.d.ts.map +1 -1
  47. package/dist/primitives/actionBarMore/ActionBarMoreTrigger.d.ts.map +1 -1
  48. package/dist/primitives/assistantModal/AssistantModalAnchor.d.ts.map +1 -1
  49. package/dist/primitives/assistantModal/AssistantModalContent.d.ts.map +1 -1
  50. package/dist/primitives/assistantModal/AssistantModalContent.js.map +1 -1
  51. package/dist/primitives/assistantModal/AssistantModalTrigger.d.ts.map +1 -1
  52. package/dist/primitives/assistantModal/popoverRenderPrimitives.d.ts.map +1 -1
  53. package/dist/primitives/attachment/AttachmentRemove.d.ts.map +1 -1
  54. package/dist/primitives/attachment/AttachmentRemove.js +1 -0
  55. package/dist/primitives/attachment/AttachmentRemove.js.map +1 -1
  56. package/dist/primitives/attachment/AttachmentRoot.d.ts.map +1 -1
  57. package/dist/primitives/attachment/AttachmentThumb.d.ts.map +1 -1
  58. package/dist/primitives/attachment/AttachmentThumb.js.map +1 -1
  59. package/dist/primitives/branchPicker/BranchPickerNext.d.ts.map +1 -1
  60. package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts.map +1 -1
  61. package/dist/primitives/branchPicker/BranchPickerRoot.d.ts.map +1 -1
  62. package/dist/primitives/branchPicker/BranchPickerRoot.js.map +1 -1
  63. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts.map +1 -1
  64. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +1 -0
  65. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
  66. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts.map +1 -1
  67. package/dist/primitives/composer/ComposerAddAttachment.d.ts.map +1 -1
  68. package/dist/primitives/composer/ComposerAddAttachment.js +8 -2
  69. package/dist/primitives/composer/ComposerAddAttachment.js.map +1 -1
  70. package/dist/primitives/composer/ComposerAttachmentDropzone.d.ts.map +1 -1
  71. package/dist/primitives/composer/ComposerAttachmentDropzone.js +1 -3
  72. package/dist/primitives/composer/ComposerAttachmentDropzone.js.map +1 -1
  73. package/dist/primitives/composer/ComposerCancel.d.ts.map +1 -1
  74. package/dist/primitives/composer/ComposerDictate.d.ts.map +1 -1
  75. package/dist/primitives/composer/ComposerDictationTranscript.d.ts.map +1 -1
  76. package/dist/primitives/composer/ComposerDictationTranscript.js.map +1 -1
  77. package/dist/primitives/composer/ComposerInput.js +6 -4
  78. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  79. package/dist/primitives/composer/ComposerQuote.d.ts.map +1 -1
  80. package/dist/primitives/composer/ComposerQuote.js.map +1 -1
  81. package/dist/primitives/composer/ComposerRoot.d.ts +5 -0
  82. package/dist/primitives/composer/ComposerRoot.d.ts.map +1 -1
  83. package/dist/primitives/composer/ComposerRoot.js +86 -40
  84. package/dist/primitives/composer/ComposerRoot.js.map +1 -1
  85. package/dist/primitives/composer/ComposerSend.d.ts.map +1 -1
  86. package/dist/primitives/composer/ComposerSend.js +1 -0
  87. package/dist/primitives/composer/ComposerSend.js.map +1 -1
  88. package/dist/primitives/composer/ComposerStopDictation.d.ts.map +1 -1
  89. package/dist/primitives/composer/ComposerStopDictation.js +1 -0
  90. package/dist/primitives/composer/ComposerStopDictation.js.map +1 -1
  91. package/dist/primitives/composer/trigger/TriggerPopover.d.ts.map +1 -1
  92. package/dist/primitives/composer/trigger/TriggerPopover.js.map +1 -1
  93. package/dist/primitives/composer/trigger/TriggerPopoverBack.d.ts.map +1 -1
  94. package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts.map +1 -1
  95. package/dist/primitives/composer/trigger/TriggerPopoverCategories.js.map +1 -1
  96. package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts.map +1 -1
  97. package/dist/primitives/composer/trigger/TriggerPopoverItems.js.map +1 -1
  98. package/dist/primitives/composer/trigger/TriggerPopoverResource.d.ts.map +1 -1
  99. package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js.map +1 -1
  100. package/dist/primitives/composer/trigger/detectTrigger.d.ts +1 -1
  101. package/dist/primitives/composer/trigger/triggerDetectionResource.d.ts.map +1 -1
  102. package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts.map +1 -1
  103. package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts.map +1 -1
  104. package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts.map +1 -1
  105. package/dist/primitives/dropdownMenuRenderPrimitives.d.ts.map +1 -1
  106. package/dist/primitives/error/ErrorMessage.d.ts.map +1 -1
  107. package/dist/primitives/error/ErrorMessage.js.map +1 -1
  108. package/dist/primitives/error/ErrorRoot.d.ts.map +1 -1
  109. package/dist/primitives/message/MessageParts.js.map +1 -1
  110. package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
  111. package/dist/primitives/message/MessageRoot.d.ts.map +1 -1
  112. package/dist/primitives/messagePart/MessagePartImage.d.ts.map +1 -1
  113. package/dist/primitives/messagePart/MessagePartText.d.ts.map +1 -1
  114. package/dist/primitives/messagePart/MessagePartText.js.map +1 -1
  115. package/dist/primitives/messagePart/useMessagePartData.d.ts +3 -2
  116. package/dist/primitives/messagePart/useMessagePartData.d.ts.map +1 -1
  117. package/dist/primitives/messagePart/useMessagePartData.js +3 -2
  118. package/dist/primitives/messagePart/useMessagePartData.js.map +1 -1
  119. package/dist/primitives/messagePart/useMessagePartFile.d.ts +5 -4
  120. package/dist/primitives/messagePart/useMessagePartFile.d.ts.map +1 -1
  121. package/dist/primitives/messagePart/useMessagePartFile.js +11 -3
  122. package/dist/primitives/messagePart/useMessagePartFile.js.map +1 -1
  123. package/dist/primitives/messagePart/useMessagePartImage.d.ts +5 -4
  124. package/dist/primitives/messagePart/useMessagePartImage.d.ts.map +1 -1
  125. package/dist/primitives/messagePart/useMessagePartImage.js +10 -3
  126. package/dist/primitives/messagePart/useMessagePartImage.js.map +1 -1
  127. package/dist/primitives/messagePart/useMessagePartReasoning.d.ts +5 -4
  128. package/dist/primitives/messagePart/useMessagePartReasoning.d.ts.map +1 -1
  129. package/dist/primitives/messagePart/useMessagePartReasoning.js +10 -3
  130. package/dist/primitives/messagePart/useMessagePartReasoning.js.map +1 -1
  131. package/dist/primitives/messagePart/useMessagePartSource.d.ts +6 -4
  132. package/dist/primitives/messagePart/useMessagePartSource.d.ts.map +1 -1
  133. package/dist/primitives/messagePart/useMessagePartSource.js +12 -3
  134. package/dist/primitives/messagePart/useMessagePartSource.js.map +1 -1
  135. package/dist/primitives/messagePart/useMessagePartText.d.ts +6 -5
  136. package/dist/primitives/messagePart/useMessagePartText.d.ts.map +1 -1
  137. package/dist/primitives/messagePart/useMessagePartText.js +10 -3
  138. package/dist/primitives/messagePart/useMessagePartText.js.map +1 -1
  139. package/dist/primitives/queueItem/QueueItemRemove.d.ts.map +1 -1
  140. package/dist/primitives/queueItem/QueueItemRemove.js +1 -0
  141. package/dist/primitives/queueItem/QueueItemRemove.js.map +1 -1
  142. package/dist/primitives/queueItem/QueueItemSteer.d.ts.map +1 -1
  143. package/dist/primitives/queueItem/QueueItemSteer.js +1 -0
  144. package/dist/primitives/queueItem/QueueItemSteer.js.map +1 -1
  145. package/dist/primitives/queueItem/QueueItemText.d.ts.map +1 -1
  146. package/dist/primitives/queueItem/QueueItemText.js.map +1 -1
  147. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.d.ts.map +1 -1
  148. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts.map +1 -1
  149. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js.map +1 -1
  150. package/dist/primitives/suggestion/SuggestionDescription.d.ts.map +1 -1
  151. package/dist/primitives/suggestion/SuggestionDescription.js.map +1 -1
  152. package/dist/primitives/suggestion/SuggestionTitle.d.ts.map +1 -1
  153. package/dist/primitives/suggestion/SuggestionTitle.js.map +1 -1
  154. package/dist/primitives/suggestion/SuggestionTrigger.d.ts.map +1 -1
  155. package/dist/primitives/suggestion/SuggestionTrigger.js +1 -0
  156. package/dist/primitives/suggestion/SuggestionTrigger.js.map +1 -1
  157. package/dist/primitives/thread/ThreadRoot.d.ts.map +1 -1
  158. package/dist/primitives/thread/ThreadScrollToBottom.d.ts.map +1 -1
  159. package/dist/primitives/thread/ThreadScrollToBottom.js +1 -0
  160. package/dist/primitives/thread/ThreadScrollToBottom.js.map +1 -1
  161. package/dist/primitives/thread/ThreadSuggestion.d.ts.map +1 -1
  162. package/dist/primitives/thread/ThreadViewport.d.ts.map +1 -1
  163. package/dist/primitives/thread/ThreadViewport.js +53 -19
  164. package/dist/primitives/thread/ThreadViewport.js.map +1 -1
  165. package/dist/primitives/thread/ThreadViewportFooter.d.ts.map +1 -1
  166. package/dist/primitives/thread/topAnchor/createReserveObservers.d.ts.map +1 -1
  167. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.d.ts +4 -0
  168. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.d.ts.map +1 -1
  169. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js +14 -1
  170. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js.map +1 -1
  171. package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts +13 -1
  172. package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts.map +1 -1
  173. package/dist/primitives/thread/topAnchor/topAnchorTurn.js +14 -1
  174. package/dist/primitives/thread/topAnchor/topAnchorTurn.js.map +1 -1
  175. package/dist/primitives/thread/useThreadViewportAutoScroll.js +2 -1
  176. package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
  177. package/dist/primitives/threadList/ThreadListLoadMore.d.ts.map +1 -1
  178. package/dist/primitives/threadList/ThreadListNew.d.ts.map +1 -1
  179. package/dist/primitives/threadList/ThreadListRoot.d.ts.map +1 -1
  180. package/dist/primitives/threadList/ThreadListRoot.js.map +1 -1
  181. package/dist/primitives/threadListFocusGroup.d.ts.map +1 -1
  182. package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts.map +1 -1
  183. package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts.map +1 -1
  184. package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts.map +1 -1
  185. package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
  186. package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts.map +1 -1
  187. package/dist/primitives/threadListItem/ThreadListItemTrigger.js.map +1 -1
  188. package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts.map +1 -1
  189. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.d.ts.map +1 -1
  190. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js.map +1 -1
  191. package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.d.ts.map +1 -1
  192. package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js.map +1 -1
  193. package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.d.ts.map +1 -1
  194. package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.d.ts.map +1 -1
  195. package/dist/tests/setup.d.ts +1 -1
  196. package/dist/utils/Primitive.d.ts.map +1 -1
  197. package/dist/utils/Primitive.js.map +1 -1
  198. package/dist/utils/createActionButton.d.ts.map +1 -1
  199. package/dist/utils/hooks/useOnResizeContent.js +1 -0
  200. package/dist/utils/hooks/useOnResizeContent.js.map +1 -1
  201. package/dist/utils/hooks/useSizeHandle.js +1 -0
  202. package/dist/utils/hooks/useSizeHandle.js.map +1 -1
  203. package/dist/utils/smooth/useSmooth.d.ts.map +1 -1
  204. package/dist/utils/smooth/useSmooth.js +2 -2
  205. package/dist/utils/smooth/useSmooth.js.map +1 -1
  206. package/package.json +20 -20
  207. package/src/client/ExternalThread.ts +341 -53
  208. package/src/legacy-runtime/cloud/auiV0.ts +14 -0
  209. package/src/legacy-runtime/runtime-cores/assistant-transport/commandQueue.ts +4 -1
  210. package/src/legacy-runtime/runtime-cores/assistant-transport/runManager.ts +37 -10
  211. package/src/legacy-runtime/runtime-cores/assistant-transport/transport-delivery.test.tsx +79 -0
  212. package/src/legacy-runtime/runtime-cores/assistant-transport/transport-parentid.test.tsx +97 -0
  213. package/src/legacy-runtime/runtime-cores/assistant-transport/transport-scheduling.test.ts +113 -2
  214. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransport.spec.md +10 -2
  215. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.test.tsx +189 -0
  216. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.ts +20 -4
  217. package/src/model-context/makeAssistantVisible.test.tsx +146 -0
  218. package/src/model-context/makeAssistantVisible.tsx +18 -1
  219. package/src/primitives/actionBar/useActionBarFloatStatus.ts +7 -5
  220. package/src/primitives/composer/ComposerAddAttachment.test.tsx +108 -0
  221. package/src/primitives/composer/ComposerAddAttachment.ts +10 -4
  222. package/src/primitives/composer/ComposerAttachmentDropzone.test.tsx +3 -2
  223. package/src/primitives/composer/ComposerAttachmentDropzone.tsx +3 -2
  224. package/src/primitives/composer/ComposerInput.test.tsx +98 -1
  225. package/src/primitives/composer/ComposerInput.tsx +10 -8
  226. package/src/primitives/composer/ComposerRoot.test.tsx +226 -5
  227. package/src/primitives/composer/ComposerRoot.tsx +50 -1
  228. package/src/primitives/messagePart/useMessagePartData.ts +3 -2
  229. package/src/primitives/messagePart/useMessagePartFile.ts +19 -7
  230. package/src/primitives/messagePart/useMessagePartImage.ts +18 -7
  231. package/src/primitives/messagePart/useMessagePartReasoning.ts +15 -6
  232. package/src/primitives/messagePart/useMessagePartSource.ts +20 -7
  233. package/src/primitives/messagePart/useMessagePartText.ts +15 -5
  234. package/src/primitives/thread/ThreadViewport.tsx +15 -0
  235. package/src/primitives/thread/topAnchor/mountTopAnchorReserve.test.ts +243 -0
  236. package/src/primitives/thread/topAnchor/mountTopAnchorReserve.ts +28 -7
  237. package/src/primitives/thread/topAnchor/topAnchorTurn.test.ts +69 -0
  238. package/src/primitives/thread/topAnchor/topAnchorTurn.ts +29 -0
  239. package/src/primitives/thread/useThreadViewportAutoScroll.test.tsx +86 -1
  240. package/src/primitives/thread/useThreadViewportAutoScroll.ts +6 -1
  241. package/src/tests/DataRenderers.test.tsx +212 -0
  242. package/src/tests/RemoteThreadListRuntime.adapterProvider.test.tsx +1 -11
  243. package/src/tests/external-thread-attachments.test.tsx +372 -0
  244. package/src/tests/external-thread-parity.test.tsx +232 -0
  245. package/src/tests/generative-ui.test.tsx +1 -46
  246. package/src/tests/messagePartSwitchRace.test.tsx +172 -0
  247. package/src/tests/messagePartTypeMismatch.test.tsx +146 -0
  248. package/src/tests/threadMessageById.test.tsx +0 -7
  249. package/src/utils/smooth/useSmooth.ts +7 -4
  250. package/src/tests/BaseComposerRuntimeCore.test.ts +0 -612
  251. package/src/tests/BaseSubscribable.test.ts +0 -54
  252. package/src/tests/DataRenderers.test.ts +0 -355
  253. package/src/tests/ExternalStoreThreadRuntimeCore.test.ts +0 -685
  254. package/src/tests/LocalThreadRuntimeCore.test.ts +0 -324
  255. package/src/tests/auiV0Encode.test.ts +0 -188
  256. package/src/tests/external-message-converter.test.ts +0 -346
  257. package/src/tests/shouldContinue.test.ts +0 -122
@@ -1,346 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { convertExternalMessages } from "../legacy-runtime/runtime-cores/external-store/external-message-converter";
3
- import type { useExternalMessageConverter } from "../legacy-runtime/runtime-cores/external-store/external-message-converter";
4
- import { isErrorMessageId } from "@assistant-ui/core/internal";
5
-
6
- describe("convertExternalMessages", () => {
7
- describe("reasoning part merging", () => {
8
- it("should merge reasoning parts with the same parentId", () => {
9
- const messages = [
10
- {
11
- id: "msg1",
12
- role: "assistant" as const,
13
- content: [
14
- {
15
- type: "reasoning" as const,
16
- text: "First reasoning",
17
- parentId: "parent1",
18
- },
19
- ],
20
- },
21
- {
22
- id: "msg2",
23
- role: "assistant" as const,
24
- content: [
25
- {
26
- type: "reasoning" as const,
27
- text: "Second reasoning",
28
- parentId: "parent1",
29
- },
30
- ],
31
- },
32
- ];
33
-
34
- const callback: useExternalMessageConverter.Callback<
35
- (typeof messages)[number]
36
- > = (msg) => msg;
37
-
38
- const result = convertExternalMessages(messages, callback, false, {});
39
-
40
- expect(result).toHaveLength(1);
41
- expect(result[0]!.role).toBe("assistant");
42
-
43
- const reasoningParts = result[0]!.content.filter(
44
- (p) => p.type === "reasoning",
45
- );
46
- expect(reasoningParts).toHaveLength(1);
47
- expect((reasoningParts[0] as any).text).toBe(
48
- "First reasoning\n\nSecond reasoning",
49
- );
50
- expect((reasoningParts[0] as any).parentId).toBe("parent1");
51
- });
52
-
53
- it("should keep reasoning parts without parentId separate", () => {
54
- const messages = [
55
- {
56
- id: "msg1",
57
- role: "assistant" as const,
58
- content: [{ type: "reasoning" as const, text: "First reasoning" }],
59
- },
60
- {
61
- id: "msg2",
62
- role: "assistant" as const,
63
- content: [{ type: "reasoning" as const, text: "Second reasoning" }],
64
- },
65
- ];
66
-
67
- const callback: useExternalMessageConverter.Callback<
68
- (typeof messages)[number]
69
- > = (msg) => msg;
70
-
71
- const result = convertExternalMessages(messages, callback, false, {});
72
-
73
- expect(result).toHaveLength(1);
74
-
75
- const reasoningParts = result[0]!.content.filter(
76
- (p) => p.type === "reasoning",
77
- );
78
- expect(reasoningParts).toHaveLength(2);
79
- expect((reasoningParts[0] as any).text).toBe("First reasoning");
80
- expect((reasoningParts[1] as any).text).toBe("Second reasoning");
81
- });
82
-
83
- it("should keep reasoning parts with different parentIds separate", () => {
84
- const messages = [
85
- {
86
- id: "msg1",
87
- role: "assistant" as const,
88
- content: [
89
- {
90
- type: "reasoning" as const,
91
- text: "Reasoning for parent1",
92
- parentId: "parent1",
93
- },
94
- ],
95
- },
96
- {
97
- id: "msg2",
98
- role: "assistant" as const,
99
- content: [
100
- {
101
- type: "reasoning" as const,
102
- text: "Reasoning for parent2",
103
- parentId: "parent2",
104
- },
105
- ],
106
- },
107
- ];
108
-
109
- const callback: useExternalMessageConverter.Callback<
110
- (typeof messages)[number]
111
- > = (msg) => msg;
112
-
113
- const result = convertExternalMessages(messages, callback, false, {});
114
-
115
- expect(result).toHaveLength(1);
116
-
117
- const reasoningParts = result[0]!.content.filter(
118
- (p) => p.type === "reasoning",
119
- );
120
- expect(reasoningParts).toHaveLength(2);
121
- expect((reasoningParts[0] as any).parentId).toBe("parent1");
122
- expect((reasoningParts[1] as any).parentId).toBe("parent2");
123
- });
124
-
125
- it("should still merge tool results with matching tool calls", () => {
126
- const messages = [
127
- {
128
- id: "msg1",
129
- role: "assistant" as const,
130
- content: [
131
- {
132
- type: "tool-call" as const,
133
- toolCallId: "tc1",
134
- toolName: "search",
135
- args: { query: "test" },
136
- argsText: '{"query":"test"}',
137
- },
138
- ],
139
- },
140
- {
141
- role: "tool" as const,
142
- toolCallId: "tc1",
143
- result: { data: "result" },
144
- },
145
- ];
146
-
147
- const callback: useExternalMessageConverter.Callback<
148
- (typeof messages)[number]
149
- > = (msg) => msg;
150
-
151
- const result = convertExternalMessages(messages, callback, false, {});
152
-
153
- expect(result).toHaveLength(1);
154
-
155
- const toolCallParts = result[0]!.content.filter(
156
- (p) => p.type === "tool-call",
157
- );
158
- expect(toolCallParts).toHaveLength(1);
159
- expect((toolCallParts[0] as any).result).toEqual({ data: "result" });
160
- });
161
-
162
- it("should merge duplicate tool calls by toolCallId across assistant messages", () => {
163
- const messages = [
164
- {
165
- id: "msg1",
166
- role: "assistant" as const,
167
- content: [
168
- {
169
- type: "tool-call" as const,
170
- toolCallId: "tc1",
171
- toolName: "search",
172
- args: { query: "old" },
173
- argsText: '{"query":"old"',
174
- },
175
- ],
176
- },
177
- {
178
- id: "msg2",
179
- role: "assistant" as const,
180
- content: [
181
- {
182
- type: "tool-call" as const,
183
- toolCallId: "tc1",
184
- toolName: "search",
185
- args: { query: "new" },
186
- argsText: '{"query":"new"}',
187
- },
188
- ],
189
- },
190
- ];
191
-
192
- const callback: useExternalMessageConverter.Callback<
193
- (typeof messages)[number]
194
- > = (msg) => msg;
195
-
196
- const result = convertExternalMessages(messages, callback, false, {});
197
-
198
- expect(result).toHaveLength(1);
199
- expect(result[0]!.role).toBe("assistant");
200
- const toolCallParts = result[0]!.content.filter(
201
- (p) => p.type === "tool-call",
202
- );
203
- expect(toolCallParts).toHaveLength(1);
204
- expect((toolCallParts[0] as any).args).toEqual({ query: "new" });
205
- expect((toolCallParts[0] as any).argsText).toBe('{"query":"new"}');
206
- });
207
-
208
- it("should ignore orphaned tool results without throwing", () => {
209
- const messages = [
210
- {
211
- id: "msg1",
212
- role: "assistant" as const,
213
- content: "First response",
214
- },
215
- {
216
- role: "tool" as const,
217
- toolCallId: "missing-tool-call",
218
- toolName: "search",
219
- result: { data: "orphan result" },
220
- },
221
- {
222
- id: "msg2",
223
- role: "assistant" as const,
224
- content: "Second response",
225
- },
226
- ];
227
-
228
- const callback: useExternalMessageConverter.Callback<
229
- (typeof messages)[number]
230
- > = (msg) => msg;
231
-
232
- const result = convertExternalMessages(messages, callback, false, {});
233
- expect(result).toHaveLength(1);
234
- expect(result[0]!.role).toBe("assistant");
235
-
236
- const textParts = result[0]!.content.filter((p) => p.type === "text");
237
- expect(textParts).toHaveLength(2);
238
- expect((textParts[0] as any).text).toBe("First response");
239
- expect((textParts[1] as any).text).toBe("Second response");
240
- });
241
- });
242
-
243
- describe("synthetic error message", () => {
244
- it("should create synthetic error message when error exists and no messages", () => {
245
- const messages: never[] = [];
246
- const callback: useExternalMessageConverter.Callback<never> = (msg) =>
247
- msg;
248
-
249
- const result = convertExternalMessages(messages, callback, false, {
250
- error: "API key is missing",
251
- });
252
-
253
- expect(result).toHaveLength(1);
254
- expect(result[0]!.role).toBe("assistant");
255
- expect(result[0]!.content).toHaveLength(0);
256
- expect(result[0]!.status).toEqual({
257
- type: "incomplete",
258
- reason: "error",
259
- error: "API key is missing",
260
- });
261
- expect(isErrorMessageId(result[0]!.id)).toBe(true);
262
- });
263
-
264
- it("should create synthetic error message when error exists and last message is user", () => {
265
- const messages = [
266
- {
267
- id: "user1",
268
- role: "user" as const,
269
- content: "Hello",
270
- },
271
- ];
272
-
273
- const callback: useExternalMessageConverter.Callback<
274
- (typeof messages)[number]
275
- > = (msg) => msg;
276
-
277
- const result = convertExternalMessages(messages, callback, false, {
278
- error: { message: "Invalid API key" },
279
- });
280
-
281
- expect(result).toHaveLength(2);
282
- expect(result[0]!.role).toBe("user");
283
- expect(result[1]!.role).toBe("assistant");
284
- expect(result[1]!.content).toHaveLength(0);
285
- expect(result[1]!.status).toEqual({
286
- type: "incomplete",
287
- reason: "error",
288
- error: { message: "Invalid API key" },
289
- });
290
- expect(isErrorMessageId(result[1]!.id)).toBe(true);
291
- });
292
-
293
- it("should not create synthetic error message when last message is assistant", () => {
294
- const messages = [
295
- {
296
- id: "user1",
297
- role: "user" as const,
298
- content: "Hello",
299
- },
300
- {
301
- id: "assistant1",
302
- role: "assistant" as const,
303
- content: "Hi there",
304
- },
305
- ];
306
-
307
- const callback: useExternalMessageConverter.Callback<
308
- (typeof messages)[number]
309
- > = (msg) => msg;
310
-
311
- const result = convertExternalMessages(messages, callback, false, {
312
- error: "Connection error",
313
- });
314
-
315
- expect(result).toHaveLength(2);
316
- expect(result[0]!.role).toBe("user");
317
- expect(result[1]!.role).toBe("assistant");
318
- expect(result[1]!.id).toBe("assistant1");
319
- expect(result[1]!.status).toMatchObject({
320
- type: "incomplete",
321
- reason: "error",
322
- error: "Connection error",
323
- });
324
- expect(isErrorMessageId(result[1]!.id)).toBe(false);
325
- });
326
-
327
- it("should not create synthetic message when no error", () => {
328
- const messages = [
329
- {
330
- id: "user1",
331
- role: "user" as const,
332
- content: "Hello",
333
- },
334
- ];
335
-
336
- const callback: useExternalMessageConverter.Callback<
337
- (typeof messages)[number]
338
- > = (msg) => msg;
339
-
340
- const result = convertExternalMessages(messages, callback, false, {});
341
-
342
- expect(result).toHaveLength(1);
343
- expect(result[0]!.role).toBe("user");
344
- });
345
- });
346
- });
@@ -1,122 +0,0 @@
1
- import type { ThreadAssistantMessage } from "@assistant-ui/core";
2
- import { describe, expect, it } from "vitest";
3
- import { shouldContinue } from "../legacy-runtime/runtime-cores/local/shouldContinue";
4
-
5
- const makeMessage = (
6
- overrides: Partial<ThreadAssistantMessage>,
7
- ): ThreadAssistantMessage => ({
8
- id: "msg-1",
9
- role: "assistant",
10
- createdAt: new Date(),
11
- content: [],
12
- status: { type: "complete", reason: "stop" },
13
- metadata: {
14
- unstable_state: null,
15
- unstable_annotations: [],
16
- unstable_data: [],
17
- steps: [],
18
- custom: {},
19
- },
20
- ...overrides,
21
- });
22
-
23
- const toolCall = (toolName: string, result?: unknown) => ({
24
- type: "tool-call" as const,
25
- toolCallId: `call-${toolName}`,
26
- toolName,
27
- args: {},
28
- argsText: "{}",
29
- ...(result !== undefined ? { result } : {}),
30
- });
31
-
32
- describe("shouldContinue", () => {
33
- it("returns false when status is not requires-action", () => {
34
- const msg = makeMessage({
35
- status: { type: "complete", reason: "stop" },
36
- });
37
- expect(shouldContinue(msg, undefined)).toBe(false);
38
- });
39
-
40
- it("returns false when reason is not tool-calls", () => {
41
- const msg = makeMessage({
42
- status: { type: "requires-action", reason: "interrupt" },
43
- });
44
- expect(shouldContinue(msg, undefined)).toBe(false);
45
- });
46
-
47
- it("returns true when all tool calls have results (no humanToolNames)", () => {
48
- const msg = makeMessage({
49
- status: { type: "requires-action", reason: "tool-calls" },
50
- content: [toolCall("search", "found it"), toolCall("calculate", 42)],
51
- });
52
- expect(shouldContinue(msg, undefined)).toBe(true);
53
- });
54
-
55
- it("returns false when some tool calls have no result (no humanToolNames)", () => {
56
- const msg = makeMessage({
57
- status: { type: "requires-action", reason: "tool-calls" },
58
- content: [toolCall("search", "found it"), toolCall("calculate")],
59
- });
60
- expect(shouldContinue(msg, undefined)).toBe(false);
61
- });
62
-
63
- it("returns true when unresolved tool call is not a human tool", () => {
64
- const msg = makeMessage({
65
- status: { type: "requires-action", reason: "tool-calls" },
66
- content: [toolCall("auto-tool")],
67
- });
68
- expect(shouldContinue(msg, ["human-approval"])).toBe(true);
69
- });
70
-
71
- it("returns false when unresolved tool call IS a human tool", () => {
72
- const msg = makeMessage({
73
- status: { type: "requires-action", reason: "tool-calls" },
74
- content: [toolCall("human-approval")],
75
- });
76
- expect(shouldContinue(msg, ["human-approval"])).toBe(false);
77
- });
78
-
79
- it("returns true for non-tool-call content parts", () => {
80
- const msg = makeMessage({
81
- status: { type: "requires-action", reason: "tool-calls" },
82
- content: [
83
- { type: "text", text: "Hello" } as any,
84
- toolCall("search", "done"),
85
- ],
86
- });
87
- expect(shouldContinue(msg, undefined)).toBe(true);
88
- });
89
-
90
- it("returns false while a tool call has a pending approval", () => {
91
- const msg = makeMessage({
92
- status: { type: "requires-action", reason: "tool-calls" },
93
- content: [{ ...toolCall("deploy"), approval: { id: "a1" } }],
94
- });
95
- expect(shouldContinue(msg, undefined)).toBe(false);
96
- expect(shouldContinue(msg, ["human-approval"])).toBe(false);
97
- });
98
-
99
- it("returns true when a decided approval has no result", () => {
100
- const msg = makeMessage({
101
- status: { type: "requires-action", reason: "tool-calls" },
102
- content: [
103
- { ...toolCall("deploy"), approval: { id: "a1", approved: true } },
104
- ],
105
- });
106
- expect(shouldContinue(msg, undefined)).toBe(true);
107
- expect(shouldContinue(msg, ["human-approval"])).toBe(true);
108
- });
109
-
110
- it("exempts approval-gated tool calls from the human tool result requirement", () => {
111
- const msg = makeMessage({
112
- status: { type: "requires-action", reason: "tool-calls" },
113
- content: [
114
- {
115
- ...toolCall("human-approval"),
116
- approval: { id: "a1", approved: true },
117
- },
118
- ],
119
- });
120
- expect(shouldContinue(msg, ["human-approval"])).toBe(true);
121
- });
122
- });