@assistant-ui/core 0.2.7 → 0.2.9

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 (160) hide show
  1. package/dist/adapters/attachment.d.ts.map +1 -1
  2. package/dist/adapters/speech.d.ts.map +1 -1
  3. package/dist/adapters/speech.js.map +1 -1
  4. package/dist/index.d.ts +2 -1
  5. package/dist/index.js +2 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/internal/duplicate-detection.d.ts.map +1 -1
  8. package/dist/internal.d.ts +2 -2
  9. package/dist/internal.js +2 -2
  10. package/dist/model-context/frame/host.d.ts.map +1 -1
  11. package/dist/model-context/frame/host.js.map +1 -1
  12. package/dist/model-context/frame/provider.d.ts.map +1 -1
  13. package/dist/model-context/frame/provider.js.map +1 -1
  14. package/dist/model-context/registry.d.ts.map +1 -1
  15. package/dist/model-context/tool.d.ts.map +1 -1
  16. package/dist/react/client/Interactables.js.map +1 -1
  17. package/dist/react/client/Tools.d.ts.map +1 -1
  18. package/dist/react/client/Tools.js +26 -15
  19. package/dist/react/client/Tools.js.map +1 -1
  20. package/dist/react/index.d.ts +6 -3
  21. package/dist/react/index.js +4 -1
  22. package/dist/react/model-context/define-toolkit.d.ts +20 -0
  23. package/dist/react/model-context/define-toolkit.d.ts.map +1 -0
  24. package/dist/react/model-context/define-toolkit.js +21 -0
  25. package/dist/react/model-context/define-toolkit.js.map +1 -0
  26. package/dist/react/model-context/hitl.d.ts +19 -0
  27. package/dist/react/model-context/hitl.d.ts.map +1 -0
  28. package/dist/react/model-context/hitl.js +22 -0
  29. package/dist/react/model-context/hitl.js.map +1 -0
  30. package/dist/react/model-context/toolbox.d.ts +29 -2
  31. package/dist/react/model-context/toolbox.d.ts.map +1 -1
  32. package/dist/react/model-context/toolbox.js +18 -0
  33. package/dist/react/model-context/toolbox.js.map +1 -0
  34. package/dist/react/model-context/useAssistantTool.d.ts.map +1 -1
  35. package/dist/react/model-context/useAssistantTool.js +6 -3
  36. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  37. package/dist/react/model-context/useAssistantToolUI.d.ts +6 -0
  38. package/dist/react/model-context/useAssistantToolUI.d.ts.map +1 -1
  39. package/dist/react/model-context/useAssistantToolUI.js +4 -2
  40. package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
  41. package/dist/react/model-context/useInlineRender.js.map +1 -1
  42. package/dist/react/primitives/message/MessageGroupedParts.d.ts +49 -7
  43. package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
  44. package/dist/react/primitives/message/MessageGroupedParts.js +28 -3
  45. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  46. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  47. package/dist/react/primitives/message/MessageParts.js +2 -7
  48. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  49. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  50. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  51. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
  52. package/dist/react/runtimes/RuntimeAdapterProvider.js +6 -5
  53. package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
  54. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  55. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  56. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  57. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  58. package/dist/react/runtimes/external-message-converter.js +1 -0
  59. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  60. package/dist/react/runtimes/useExternalStoreSharedOptions.d.ts +7 -0
  61. package/dist/react/runtimes/useExternalStoreSharedOptions.d.ts.map +1 -0
  62. package/dist/react/runtimes/useExternalStoreSharedOptions.js +21 -0
  63. package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -0
  64. package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
  65. package/dist/react/runtimes/useLocalRuntime.js.map +1 -1
  66. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  67. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  68. package/dist/react/types/scopes/tools.d.ts +19 -2
  69. package/dist/react/types/scopes/tools.d.ts.map +1 -1
  70. package/dist/react/utils/groupParts.d.ts +32 -11
  71. package/dist/react/utils/groupParts.d.ts.map +1 -1
  72. package/dist/react/utils/groupParts.js +13 -6
  73. package/dist/react/utils/groupParts.js.map +1 -1
  74. package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
  75. package/dist/runtime/api/attachment-runtime.d.ts.map +1 -1
  76. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  77. package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
  78. package/dist/runtime/api/message-runtime.d.ts.map +1 -1
  79. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  80. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  81. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  82. package/dist/runtime/base/base-assistant-runtime-core.d.ts.map +1 -1
  83. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  84. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  85. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  86. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  87. package/dist/runtime/utils/message-repository.d.ts +9 -1
  88. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  89. package/dist/runtime/utils/message-repository.js +34 -14
  90. package/dist/runtime/utils/message-repository.js.map +1 -1
  91. package/dist/runtime/utils/thread-message-like.d.ts +1 -0
  92. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  93. package/dist/runtime/utils/thread-message-like.js +2 -1
  94. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  95. package/dist/runtimes/external-store/external-store-shared-options.d.ts +8 -0
  96. package/dist/runtimes/external-store/external-store-shared-options.d.ts.map +1 -0
  97. package/dist/runtimes/external-store/external-store-shared-options.js +11 -0
  98. package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -0
  99. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  100. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +0 -2
  101. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  102. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +12 -23
  103. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  104. package/dist/runtimes/external-store/thread-message-converter.d.ts.map +1 -1
  105. package/dist/runtimes/local/local-thread-list-runtime-core.d.ts.map +1 -1
  106. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  107. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  108. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts.map +1 -1
  109. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
  110. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  111. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  112. package/dist/subscribable/subscribable.d.ts.map +1 -1
  113. package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
  114. package/dist/types/message.d.ts +6 -0
  115. package/dist/types/message.d.ts.map +1 -1
  116. package/dist/types/message.js.map +1 -1
  117. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  118. package/dist/utils/id.d.ts +1 -3
  119. package/dist/utils/id.d.ts.map +1 -1
  120. package/dist/utils/id.js +1 -4
  121. package/dist/utils/id.js.map +1 -1
  122. package/package.json +10 -10
  123. package/src/adapters/speech.ts +0 -1
  124. package/src/index.ts +2 -0
  125. package/src/internal.ts +0 -2
  126. package/src/model-context/frame/host.ts +0 -1
  127. package/src/model-context/frame/provider.ts +0 -1
  128. package/src/react/client/Interactables.ts +0 -1
  129. package/src/react/client/Tools.ts +50 -25
  130. package/src/react/index.ts +10 -2
  131. package/src/react/model-context/define-toolkit.test.ts +13 -0
  132. package/src/react/model-context/define-toolkit.ts +23 -0
  133. package/src/react/model-context/hitl.ts +22 -0
  134. package/src/react/model-context/toolbox.ts +46 -1
  135. package/src/react/model-context/useAssistantTool.ts +8 -3
  136. package/src/react/model-context/useAssistantToolUI.ts +9 -2
  137. package/src/react/model-context/useInlineRender.ts +0 -1
  138. package/src/react/primitives/message/MessageGroupedParts.tsx +101 -12
  139. package/src/react/primitives/message/MessageParts.tsx +4 -7
  140. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +0 -3
  141. package/src/react/runtimes/RuntimeAdapterProvider.tsx +12 -7
  142. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +0 -3
  143. package/src/react/runtimes/external-message-converter.ts +4 -0
  144. package/src/react/runtimes/useExternalStoreSharedOptions.ts +23 -0
  145. package/src/react/runtimes/useLocalRuntime.ts +0 -10
  146. package/src/react/runtimes/useRemoteThreadListRuntime.ts +0 -6
  147. package/src/react/types/scopes/tools.ts +20 -1
  148. package/src/react/utils/groupParts.ts +49 -18
  149. package/src/runtime/utils/message-repository.ts +57 -16
  150. package/src/runtime/utils/thread-message-like.ts +2 -0
  151. package/src/runtimes/external-store/external-store-shared-options.ts +18 -0
  152. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +18 -33
  153. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +0 -1
  154. package/src/tests/MessageRepository.test.ts +83 -52
  155. package/src/tests/OptimisticState-list-race.test.ts +0 -4
  156. package/src/tests/external-store-thread-runtime-core.test.ts +105 -73
  157. package/src/tests/groupParts.test.ts +70 -0
  158. package/src/tests/remote-thread-list-isLoading.test.ts +0 -5
  159. package/src/types/message.ts +6 -0
  160. package/src/utils/id.ts +0 -4
@@ -12,6 +12,8 @@ import { makeAssistantDataUI } from "./model-context/makeAssistantDataUI.js";
12
12
  import { useAssistantInstructions } from "./model-context/useAssistantInstructions.js";
13
13
  import { useAssistantContext } from "./model-context/useAssistantContext.js";
14
14
  import { useInlineRender } from "./model-context/useInlineRender.js";
15
+ import { defineToolkit } from "./model-context/define-toolkit.js";
16
+ import { hitl } from "./model-context/hitl.js";
15
17
  import { useAssistantInteractable } from "./model-context/useAssistantInteractable.js";
16
18
  import { useInteractableState } from "./model-context/useInteractableState.js";
17
19
  import { useToolArgsStatus } from "./model-context/useToolArgsStatus.js";
@@ -29,6 +31,7 @@ import { QueueItemByIndexProvider } from "./providers/QueueItemByIndexProvider.j
29
31
  import { ReadonlyThreadProvider } from "./providers/ReadonlyThreadProvider.js";
30
32
  import { RuntimeAdapterProvider, useRuntimeAdapters } from "./runtimes/RuntimeAdapterProvider.js";
31
33
  import { useExternalStoreRuntime } from "./runtimes/useExternalStoreRuntime.js";
34
+ import { useExternalStoreSharedOptions } from "./runtimes/useExternalStoreSharedOptions.js";
32
35
  import { convertExternalMessages, useExternalMessageConverter } from "./runtimes/external-message-converter.js";
33
36
  import { createMessageConverter } from "./runtimes/createMessageConverter.js";
34
37
  import { RemoteThreadListHookInstanceManager } from "./runtimes/RemoteThreadListHookInstanceManager.js";
@@ -85,4 +88,4 @@ import { useEditComposerCancel } from "./primitive-hooks/useEditComposerCancel.j
85
88
  import { useEditComposerSend } from "./primitive-hooks/useEditComposerSend.js";
86
89
  import { useMessageError } from "./primitive-hooks/useMessageError.js";
87
90
  import { splitLocalRuntimeOptions, useLocalRuntime } from "./runtimes/useLocalRuntime.js";
88
- export { AssistantProviderBase, AssistantRuntimeProvider, ChainOfThoughtByIndicesProvider, ChainOfThoughtPartByIndexProvider, ChainOfThoughtPrimitiveParts, CloudFileAttachmentAdapter, ComposerAttachmentByIndexProvider, ComposerPrimitiveAttachmentByIndex, ComposerPrimitiveAttachments, ComposerPrimitiveIf, ComposerPrimitiveQueue, DataRenderers, GenerativeUIRender, GenerativeUIRenderError, Interactables, MessageAttachmentByIndexProvider, MessageByIndexProvider, MessagePartComponent, MessagePartPrimitiveInProgress, MessagePrimitiveAttachmentByIndex, MessagePrimitiveAttachments, MessagePrimitiveGenerativeUI, MessagePrimitiveGroupedParts, MessagePrimitivePartByIndex, MessagePrimitiveParts, MessagePrimitiveQuote, PartByIndexProvider, PartPrimitiveMessages, PartPrimitiveMessagesImpl, QueueItemByIndexProvider, ReadonlyThreadProvider, RemoteThreadListHookInstanceManager, RemoteThreadListThreadListRuntimeCore, RuntimeAdapter, RuntimeAdapterProvider, SuggestionByIndexProvider, TextMessagePartProvider, ThreadListItemByIndexProvider, ThreadListItemPrimitiveTitle, ThreadListItemRuntimeProvider, ThreadListPrimitiveItemByIndex, ThreadListPrimitiveItems, ThreadPrimitiveMessageByIndex, ThreadPrimitiveMessages, ThreadPrimitiveMessagesImpl, ThreadPrimitiveSuggestionByIndex, ThreadPrimitiveSuggestions, ThreadPrimitiveSuggestionsImpl, Tools, convertExternalMessages, createLocalStorageAdapter, createMessageConverter, createSimpleTitleAdapter, getMessageQuote, getRenderComponent, groupPartByType, makeAssistantDataUI, makeAssistantTool, makeAssistantToolUI, defaultComponents as messagePartsDefaultComponents, splitLocalRuntimeOptions, useActionBarCopy, useActionBarEdit, useActionBarFeedbackNegative, useActionBarFeedbackPositive, useActionBarReload, useActionBarSpeak, useActionBarStopSpeaking, useAssistantCloudThreadHistoryAdapter, useAssistantContext, useAssistantDataUI, useAssistantInstructions, useAssistantInteractable, useAssistantTool, useAssistantToolUI, useBranchPickerNext, useBranchPickerPrevious, useCloudThreadListAdapter, useComposerAddAttachment, useComposerCancel, useComposerDictate, useComposerSend, useEditComposerCancel, useEditComposerSend, useExternalMessageConverter, useExternalStoreRuntime, useInlineRender, useInteractableState, useLocalRuntime, useMessageBranching, useMessageError, useMessageReload, useRemoteThreadListRuntime, useRuntimeAdapters, useSuggestionTrigger, useThreadIsEmpty, useThreadIsRunning, useThreadListItemArchive, useThreadListItemDelete, useThreadListItemTrigger, useThreadListItemUnarchive, useThreadListLoadMore, useThreadListNew, useThreadMessages, useToolArgsStatus, useVoiceControls, useVoiceState, useVoiceVolume };
91
+ export { AssistantProviderBase, AssistantRuntimeProvider, ChainOfThoughtByIndicesProvider, ChainOfThoughtPartByIndexProvider, ChainOfThoughtPrimitiveParts, CloudFileAttachmentAdapter, ComposerAttachmentByIndexProvider, ComposerPrimitiveAttachmentByIndex, ComposerPrimitiveAttachments, ComposerPrimitiveIf, ComposerPrimitiveQueue, DataRenderers, GenerativeUIRender, GenerativeUIRenderError, Interactables, MessageAttachmentByIndexProvider, MessageByIndexProvider, MessagePartComponent, MessagePartPrimitiveInProgress, MessagePrimitiveAttachmentByIndex, MessagePrimitiveAttachments, MessagePrimitiveGenerativeUI, MessagePrimitiveGroupedParts, MessagePrimitivePartByIndex, MessagePrimitiveParts, MessagePrimitiveQuote, PartByIndexProvider, PartPrimitiveMessages, PartPrimitiveMessagesImpl, QueueItemByIndexProvider, ReadonlyThreadProvider, RemoteThreadListHookInstanceManager, RemoteThreadListThreadListRuntimeCore, RuntimeAdapter, RuntimeAdapterProvider, SuggestionByIndexProvider, TextMessagePartProvider, ThreadListItemByIndexProvider, ThreadListItemPrimitiveTitle, ThreadListItemRuntimeProvider, ThreadListPrimitiveItemByIndex, ThreadListPrimitiveItems, ThreadPrimitiveMessageByIndex, ThreadPrimitiveMessages, ThreadPrimitiveMessagesImpl, ThreadPrimitiveSuggestionByIndex, ThreadPrimitiveSuggestions, ThreadPrimitiveSuggestionsImpl, Tools, convertExternalMessages, createLocalStorageAdapter, createMessageConverter, createSimpleTitleAdapter, defineToolkit, getMessageQuote, getRenderComponent, groupPartByType, hitl, makeAssistantDataUI, makeAssistantTool, makeAssistantToolUI, defaultComponents as messagePartsDefaultComponents, splitLocalRuntimeOptions, useActionBarCopy, useActionBarEdit, useActionBarFeedbackNegative, useActionBarFeedbackPositive, useActionBarReload, useActionBarSpeak, useActionBarStopSpeaking, useAssistantCloudThreadHistoryAdapter, useAssistantContext, useAssistantDataUI, useAssistantInstructions, useAssistantInteractable, useAssistantTool, useAssistantToolUI, useBranchPickerNext, useBranchPickerPrevious, useCloudThreadListAdapter, useComposerAddAttachment, useComposerCancel, useComposerDictate, useComposerSend, useEditComposerCancel, useEditComposerSend, useExternalMessageConverter, useExternalStoreRuntime, useExternalStoreSharedOptions, useInlineRender, useInteractableState, useLocalRuntime, useMessageBranching, useMessageError, useMessageReload, useRemoteThreadListRuntime, useRuntimeAdapters, useSuggestionTrigger, useThreadIsEmpty, useThreadIsRunning, useThreadListItemArchive, useThreadListItemDelete, useThreadListItemTrigger, useThreadListItemUnarchive, useThreadListLoadMore, useThreadListNew, useThreadMessages, useToolArgsStatus, useVoiceControls, useVoiceState, useVoiceVolume };
@@ -0,0 +1,20 @@
1
+ import { Toolkit, ToolkitDeclaration } from "./toolbox.js";
2
+
3
+ //#region src/react/model-context/define-toolkit.d.ts
4
+ /**
5
+ * Authoring helper for a `"use generative"` toolkit. Accepts the permissive
6
+ * {@link ToolkitDeclaration} (a `backend` tool may carry its server `execute`)
7
+ * and types the result as the canonical {@link Toolkit}.
8
+ *
9
+ * It has **no runtime implementation**. A `"use generative"` compiler (e.g.
10
+ * `@assistant-ui/next` or `@assistant-ui/vite`) strips the `defineToolkit(...)`
11
+ * wrapper (and its import) per build, so a correctly compiled
12
+ * `export default defineToolkit({...})` never calls this. If it *does* run, the
13
+ * module was not compiled by a use-generative loader — e.g. `defineToolkit` used
14
+ * outside a `"use generative"` file — which would ship a backend `execute` to the
15
+ * client. So it throws instead of silently leaking.
16
+ */
17
+ declare function defineToolkit(_declaration: ToolkitDeclaration): Toolkit;
18
+ //#endregion
19
+ export { defineToolkit };
20
+ //# sourceMappingURL=define-toolkit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-toolkit.d.ts","names":[],"sources":["../../../src/react/model-context/define-toolkit.ts"],"mappings":";;;;;AAeA;;;;;;;;AAAwE;;;iBAAxD,aAAA,CAAc,YAAA,EAAc,kBAAA,GAAqB,OAAO"}
@@ -0,0 +1,21 @@
1
+ //#region src/react/model-context/define-toolkit.ts
2
+ /**
3
+ * Authoring helper for a `"use generative"` toolkit. Accepts the permissive
4
+ * {@link ToolkitDeclaration} (a `backend` tool may carry its server `execute`)
5
+ * and types the result as the canonical {@link Toolkit}.
6
+ *
7
+ * It has **no runtime implementation**. A `"use generative"` compiler (e.g.
8
+ * `@assistant-ui/next` or `@assistant-ui/vite`) strips the `defineToolkit(...)`
9
+ * wrapper (and its import) per build, so a correctly compiled
10
+ * `export default defineToolkit({...})` never calls this. If it *does* run, the
11
+ * module was not compiled by a use-generative loader — e.g. `defineToolkit` used
12
+ * outside a `"use generative"` file — which would ship a backend `execute` to the
13
+ * client. So it throws instead of silently leaking.
14
+ */
15
+ function defineToolkit(_declaration) {
16
+ throw new Error("[assistant-ui] defineToolkit() has no runtime implementation — it is stripped at build time by the use-generative compiler. Reaching it means this module was not compiled (e.g. defineToolkit used outside a \"use generative\" file). Add the directive, or do not use defineToolkit here.");
17
+ }
18
+ //#endregion
19
+ export { defineToolkit };
20
+
21
+ //# sourceMappingURL=define-toolkit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-toolkit.js","names":[],"sources":["../../../src/react/model-context/define-toolkit.ts"],"sourcesContent":["import type { Toolkit, ToolkitDeclaration } from \"./toolbox\";\n\n/**\n * Authoring helper for a `\"use generative\"` toolkit. Accepts the permissive\n * {@link ToolkitDeclaration} (a `backend` tool may carry its server `execute`)\n * and types the result as the canonical {@link Toolkit}.\n *\n * It has **no runtime implementation**. A `\"use generative\"` compiler (e.g.\n * `@assistant-ui/next` or `@assistant-ui/vite`) strips the `defineToolkit(...)`\n * wrapper (and its import) per build, so a correctly compiled\n * `export default defineToolkit({...})` never calls this. If it *does* run, the\n * module was not compiled by a use-generative loader — e.g. `defineToolkit` used\n * outside a `\"use generative\"` file — which would ship a backend `execute` to the\n * client. So it throws instead of silently leaking.\n */\nexport function defineToolkit(_declaration: ToolkitDeclaration): Toolkit {\n throw new Error(\n \"[assistant-ui] defineToolkit() has no runtime implementation — it is \" +\n \"stripped at build time by the use-generative compiler. Reaching it means \" +\n 'this module was not compiled (e.g. defineToolkit used outside a \"use ' +\n 'generative\" file). Add the directive, or do not use defineToolkit here.',\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAeA,SAAgB,cAAc,cAA2C;CACvE,MAAM,IAAI,MACR,8RAIF;AACF"}
@@ -0,0 +1,19 @@
1
+ //#region src/react/model-context/hitl.d.ts
2
+ /**
3
+ * Marks a tool as **human-in-the-loop**: the agent pauses and the UI (`render`)
4
+ * supplies the result instead of code. Use it as the tool's `execute`:
5
+ *
6
+ * ```tsx
7
+ * confirm: { execute: hitl(), render: (props) => <Confirm {...props} /> }
8
+ * ```
9
+ *
10
+ * Like {@link defineToolkit}, it has **no runtime implementation**: a
11
+ * `"use generative"` compiler (e.g. `@assistant-ui/next` or `@assistant-ui/vite`)
12
+ * detects `execute: hitl()`, drops it, and stamps the tool `type: "human"`.
13
+ * Reaching it at runtime means the module wasn't compiled (used outside a
14
+ * `"use generative"` file), so it throws.
15
+ */
16
+ declare function hitl(): never;
17
+ //#endregion
18
+ export { hitl };
19
+ //# sourceMappingURL=hitl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hitl.d.ts","names":[],"sources":["../../../src/react/model-context/hitl.ts"],"mappings":";;AAcA;;;;AAAoB;;;;;;;;;iBAAJ,IAAA"}
@@ -0,0 +1,22 @@
1
+ //#region src/react/model-context/hitl.ts
2
+ /**
3
+ * Marks a tool as **human-in-the-loop**: the agent pauses and the UI (`render`)
4
+ * supplies the result instead of code. Use it as the tool's `execute`:
5
+ *
6
+ * ```tsx
7
+ * confirm: { execute: hitl(), render: (props) => <Confirm {...props} /> }
8
+ * ```
9
+ *
10
+ * Like {@link defineToolkit}, it has **no runtime implementation**: a
11
+ * `"use generative"` compiler (e.g. `@assistant-ui/next` or `@assistant-ui/vite`)
12
+ * detects `execute: hitl()`, drops it, and stamps the tool `type: "human"`.
13
+ * Reaching it at runtime means the module wasn't compiled (used outside a
14
+ * `"use generative"` file), so it throws.
15
+ */
16
+ function hitl() {
17
+ throw new Error("[assistant-ui] hitl() has no runtime implementation — it marks a human-in-the-loop tool and is stripped at build time by the use-generative compiler. Reaching it means this module was not compiled (e.g. hitl() used outside a \"use generative\" file).");
18
+ }
19
+ //#endregion
20
+ export { hitl };
21
+
22
+ //# sourceMappingURL=hitl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hitl.js","names":[],"sources":["../../../src/react/model-context/hitl.ts"],"sourcesContent":["/**\n * Marks a tool as **human-in-the-loop**: the agent pauses and the UI (`render`)\n * supplies the result instead of code. Use it as the tool's `execute`:\n *\n * ```tsx\n * confirm: { execute: hitl(), render: (props) => <Confirm {...props} /> }\n * ```\n *\n * Like {@link defineToolkit}, it has **no runtime implementation**: a\n * `\"use generative\"` compiler (e.g. `@assistant-ui/next` or `@assistant-ui/vite`)\n * detects `execute: hitl()`, drops it, and stamps the tool `type: \"human\"`.\n * Reaching it at runtime means the module wasn't compiled (used outside a\n * `\"use generative\"` file), so it throws.\n */\nexport function hitl(): never {\n throw new Error(\n \"[assistant-ui] hitl() has no runtime implementation — it marks a \" +\n \"human-in-the-loop tool and is stripped at build time by the \" +\n \"use-generative compiler. Reaching it means this module was not compiled \" +\n '(e.g. hitl() used outside a \"use generative\" file).',\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAcA,SAAgB,OAAc;CAC5B,MAAM,IAAI,MACR,4PAIF;AACF"}
@@ -1,7 +1,17 @@
1
1
  import { ToolCallMessagePartComponent } from "../types/MessagePartComponentTypes.js";
2
- import { Tool } from "assistant-stream";
2
+ import { Tool, ToolDeclaration } from "assistant-stream";
3
3
 
4
4
  //#region src/react/model-context/toolbox.d.ts
5
+ /**
6
+ * Resolves whether a tool's UI should be presented standalone (outside the
7
+ * chain-of-thought grouping), applying the type-based defaults.
8
+ *
9
+ * An explicit `display` wins. Otherwise `human` tools default to standalone
10
+ * (they prompt the user), and every other tool defaults to inline (a trace of
11
+ * what the model is doing). MCP-app tool calls are detected separately from
12
+ * the part itself and are not resolved here.
13
+ */
14
+ declare const isStandaloneToolDisplay: (tool: Pick<Tool<any, any>, "type" | "display">) => boolean;
5
15
  type WithRender<T, TArgs extends Record<string, unknown>, TResult> = T extends {
6
16
  type: "frontend" | "human";
7
17
  } ? T & {
@@ -38,10 +48,27 @@ type ToolDefinition<TArgs extends Record<string, unknown>, TResult> = WithRender
38
48
  * ```
39
49
  */
40
50
  type Toolkit = Record<string, ToolDefinition<any, any>>;
51
+ /**
52
+ * A tool as authored, before the build splits it: like {@link ToolDefinition}
53
+ * but it may declare `description`, `parameters`, and a server-side `execute`
54
+ * alongside its `render`. The `type` field is **not** authored — the
55
+ * `"use generative"` compiler infers it (`execute: hitl()` → human; `execute`
56
+ * with a `"use client"` directive → frontend; otherwise backend) and writes it
57
+ * back — so declaring it here is a type error.
58
+ */
59
+ type ToolkitDeclarationDefinition<TArgs extends Record<string, unknown>, TResult> = WithRender<Omit<ToolDeclaration<TArgs, TResult>, "type">, TArgs, TResult> & {
60
+ type?: never;
61
+ };
62
+ /**
63
+ * The permissive, authoring-time counterpart to {@link Toolkit} — the input to
64
+ * {@link defineToolkit}. Backend entries may carry their server `execute` here;
65
+ * the canonical {@link Toolkit} keeps those fields `undefined`.
66
+ */
67
+ type ToolkitDeclaration = Record<string, ToolkitDeclarationDefinition<any, any>>;
41
68
  /** Configuration for the {@link Tools} resource. */
42
69
  type ToolsConfig = {
43
70
  /** Tools to register with model context and, when provided, message renderers. */toolkit: Toolkit;
44
71
  };
45
72
  //#endregion
46
- export { ToolDefinition, Toolkit, ToolsConfig };
73
+ export { ToolDefinition, Toolkit, ToolkitDeclaration, ToolkitDeclarationDefinition, ToolsConfig, isStandaloneToolDisplay };
47
74
  //# sourceMappingURL=toolbox.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox.d.ts","names":[],"sources":["../../../src/react/model-context/toolbox.ts"],"mappings":";;;;KAGK,UAAA,kBAA4B,MAAA,8BAAoC,CAAA;EACnE,IAAA;AAAA,IAEE,CAAA;EAAM,MAAA,EAAQ,4BAAA,CAA6B,KAAA,EAAO,OAAA;AAAA,IAClD,CAAA;EACE,MAAA,GAAS,4BAAA,CAA6B,KAAA,EAAO,OAAA;AAAA;;;;;;;;;;KAYvC,cAAA,eACI,MAAA,8BAEZ,UAAA,CAAW,IAAA,CAAK,KAAA,EAAO,OAAA,GAAU,KAAA,EAAO,OAAA;;;;;;;;;;;;;;;;;;AAfc;KAmC9C,OAAA,GAAU,MAAM,SAAS,cAAA;;KAGzB,WAAA;EAzBI,kFA2Bd,OAAA,EAAS,OAAO;AAAA"}
1
+ {"version":3,"file":"toolbox.d.ts","names":[],"sources":["../../../src/react/model-context/toolbox.ts"],"mappings":";;;;;;AAYA;;;;;;;cAAa,uBAAA,GACX,IAAA,EAAM,IAAI,CAAC,IAAA;AAAA,KAMR,UAAA,kBAA4B,MAAA,8BAAoC,CAAA;EACnE,IAAA;AAAA,IAEE,CAAA;EAAM,MAAA,EAAQ,4BAAA,CAA6B,KAAA,EAAO,OAAA;AAAA,IAClD,CAAA;EACE,MAAA,GAAS,4BAAA,CAA6B,KAAA,EAAO,OAAA;AAAA;;;;;;;;;;KAYvC,cAAA,eACI,MAAA,8BAEZ,UAAA,CAAW,IAAA,CAAK,KAAA,EAAO,OAAA,GAAU,KAAA,EAAO,OAAA;;;;;;;;;;;;;;;;;AAfc;AAY1D;KAuBY,OAAA,GAAU,MAAM,SAAS,cAAA;;;;;;;;;KAUzB,4BAAA,eACI,MAAA,8BAEZ,UAAA,CACF,IAAA,CAAK,eAAA,CAAgB,KAAA,EAAO,OAAA,YAC5B,KAAA,EACA,OAAA;EAEA,IAAA;AAAA;;;;;;KAQU,kBAAA,GAAqB,MAAM,SAErC,4BAAA;;KAIU,WAAA;EApDuC,kFAsDjD,OAAA,EAAS,OAAO;AAAA"}
@@ -0,0 +1,18 @@
1
+ //#region src/react/model-context/toolbox.ts
2
+ /**
3
+ * Resolves whether a tool's UI should be presented standalone (outside the
4
+ * chain-of-thought grouping), applying the type-based defaults.
5
+ *
6
+ * An explicit `display` wins. Otherwise `human` tools default to standalone
7
+ * (they prompt the user), and every other tool defaults to inline (a trace of
8
+ * what the model is doing). MCP-app tool calls are detected separately from
9
+ * the part itself and are not resolved here.
10
+ */
11
+ const isStandaloneToolDisplay = (tool) => {
12
+ if (tool.display !== void 0) return tool.display === "standalone";
13
+ return tool.type === "human";
14
+ };
15
+ //#endregion
16
+ export { isStandaloneToolDisplay };
17
+
18
+ //# sourceMappingURL=toolbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbox.js","names":[],"sources":["../../../src/react/model-context/toolbox.ts"],"sourcesContent":["import type { Tool, ToolDeclaration } from \"assistant-stream\";\nimport type { ToolCallMessagePartComponent } from \"../types/MessagePartComponentTypes\";\n\n/**\n * Resolves whether a tool's UI should be presented standalone (outside the\n * chain-of-thought grouping), applying the type-based defaults.\n *\n * An explicit `display` wins. Otherwise `human` tools default to standalone\n * (they prompt the user), and every other tool defaults to inline (a trace of\n * what the model is doing). MCP-app tool calls are detected separately from\n * the part itself and are not resolved here.\n */\nexport const isStandaloneToolDisplay = (\n tool: Pick<Tool<any, any>, \"type\" | \"display\">,\n): boolean => {\n if (tool.display !== undefined) return tool.display === \"standalone\";\n return tool.type === \"human\";\n};\n\ntype WithRender<T, TArgs extends Record<string, unknown>, TResult> = T extends {\n type: \"frontend\" | \"human\";\n}\n ? T & { render: ToolCallMessagePartComponent<TArgs, TResult> }\n : T & {\n render?: ToolCallMessagePartComponent<TArgs, TResult> | undefined;\n };\n\n/**\n * Tool definition accepted by the React tool registry.\n *\n * Extends the core tool contract with a render component. Human tools rely on\n * the renderer to collect input from the user. Frontend tools execute in the\n * browser and require a UI surface for their progress and result. Backend\n * tools execute server-side and may omit a renderer. The `render` component is\n * required for frontend and human tools and optional for backend tools.\n */\nexport type ToolDefinition<\n TArgs extends Record<string, unknown>,\n TResult,\n> = WithRender<Tool<TArgs, TResult>, TArgs, TResult>;\n\n/**\n * Named collection of tools exposed to the assistant model.\n *\n * Keys are the tool names the model receives and uses in tool calls.\n *\n * @example\n * ```tsx\n * const toolkit = {\n * get_weather: {\n * type: \"frontend\",\n * description: \"Get the weather for a city.\",\n * parameters: weatherSchema,\n * execute: async ({ city }: { city: string }) => fetchWeather(city),\n * render: WeatherToolUI,\n * },\n * } satisfies Toolkit;\n * ```\n */\nexport type Toolkit = Record<string, ToolDefinition<any, any>>;\n\n/**\n * A tool as authored, before the build splits it: like {@link ToolDefinition}\n * but it may declare `description`, `parameters`, and a server-side `execute`\n * alongside its `render`. The `type` field is **not** authored — the\n * `\"use generative\"` compiler infers it (`execute: hitl()` → human; `execute`\n * with a `\"use client\"` directive → frontend; otherwise backend) and writes it\n * back — so declaring it here is a type error.\n */\nexport type ToolkitDeclarationDefinition<\n TArgs extends Record<string, unknown>,\n TResult,\n> = WithRender<\n Omit<ToolDeclaration<TArgs, TResult>, \"type\">,\n TArgs,\n TResult\n> & {\n type?: never;\n};\n\n/**\n * The permissive, authoring-time counterpart to {@link Toolkit} — the input to\n * {@link defineToolkit}. Backend entries may carry their server `execute` here;\n * the canonical {@link Toolkit} keeps those fields `undefined`.\n */\nexport type ToolkitDeclaration = Record<\n string,\n ToolkitDeclarationDefinition<any, any>\n>;\n\n/** Configuration for the {@link Tools} resource. */\nexport type ToolsConfig = {\n /** Tools to register with model context and, when provided, message renderers. */\n toolkit: Toolkit;\n};\n"],"mappings":";;;;;;;;;;AAYA,MAAa,2BACX,SACY;CACZ,IAAI,KAAK,YAAY,KAAA,GAAW,OAAO,KAAK,YAAY;CACxD,OAAO,KAAK,SAAS;AACvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAssistantTool.d.ts","names":[],"sources":["../../../src/react/model-context/useAssistantTool.ts"],"mappings":";;;;;;;KAQY,kBAAA,eACI,MAAA,8BAEZ,oBAAA,CAAuB,KAAA,EAAO,OAAA;EAHJ,yEAK5B,MAAA,GAAS,4BAAA,CAA6B,KAAA,EAAO,OAAA;AAAA;;;;;;;;;;;;;;;;;;;;AAAO;AAiCtD;;;;;;;;;;cAAa,gBAAA,iBACG,MAAA,4BAGd,IAAA,EAAM,kBAAA,CAAmB,KAAA,EAAO,OAAA"}
1
+ {"version":3,"file":"useAssistantTool.d.ts","names":[],"sources":["../../../src/react/model-context/useAssistantTool.ts"],"mappings":";;;;;;;KASY,kBAAA,eACI,MAAA,8BAEZ,oBAAA,CAAuB,KAAA,EAAO,OAAA;EAHJ,yEAK5B,MAAA,GAAS,4BAAA,CAA6B,KAAA,EAAO,OAAA;AAAA;;;;;;;;;;;;;;;;;;;;AAAO;AAiCtD;;;;;;;;;;cAAa,gBAAA,iBACG,MAAA,4BAGd,IAAA,EAAM,kBAAA,CAAmB,KAAA,EAAO,OAAA"}
@@ -1,3 +1,4 @@
1
+ import { isStandaloneToolDisplay } from "./toolbox.js";
1
2
  import { useEffect } from "react";
2
3
  import { useAui } from "@assistant-ui/store";
3
4
  //#region src/react/model-context/useAssistantTool.ts
@@ -33,16 +34,18 @@ import { useAui } from "@assistant-ui/store";
33
34
  */
34
35
  const useAssistantTool = (tool) => {
35
36
  const aui = useAui();
37
+ const standalone = isStandaloneToolDisplay(tool);
36
38
  useEffect(() => {
37
39
  if (!tool.render) return void 0;
38
- return aui.tools().setToolUI(tool.toolName, tool.render);
40
+ return aui.tools().setToolUI(tool.toolName, tool.render, { standalone });
39
41
  }, [
40
42
  aui,
41
43
  tool.toolName,
42
- tool.render
44
+ tool.render,
45
+ standalone
43
46
  ]);
44
47
  useEffect(() => {
45
- const { toolName, render, ...rest } = tool;
48
+ const { toolName, render, display, ...rest } = tool;
46
49
  const context = { tools: { [toolName]: rest } };
47
50
  return aui.modelContext().register({ getModelContext: () => context });
48
51
  }, [aui, tool]);
@@ -1 +1 @@
1
- {"version":3,"file":"useAssistantTool.js","names":[],"sources":["../../../src/react/model-context/useAssistantTool.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type { ToolCallMessagePartComponent } from \"../types/MessagePartComponentTypes\";\nimport type { AssistantToolProps as CoreAssistantToolProps } from \"../..\";\n\n/**\n * Props used to register a tool from React.\n */\nexport type AssistantToolProps<\n TArgs extends Record<string, unknown>,\n TResult,\n> = CoreAssistantToolProps<TArgs, TResult> & {\n /** Component used to render calls to this tool in assistant messages. */\n render?: ToolCallMessagePartComponent<TArgs, TResult> | undefined;\n};\n\n/**\n * Registers a tool with the assistant model context while the component is\n * mounted.\n *\n * If `render` is provided, it is also installed as the renderer for matching\n * tool-call message parts. The registration is removed automatically when the\n * component unmounts or the tool definition changes.\n *\n * Pass a referentially stable tool object, such as one declared at module\n * scope or memoized with `useMemo`, to avoid re-registering on every render.\n *\n * @param tool - Tool definition and name to register.\n *\n * @example\n * ```tsx\n * const weatherTool = {\n * toolName: \"get_weather\",\n * type: \"frontend\",\n * description: \"Get the weather for a city.\",\n * parameters: weatherSchema,\n * execute: async ({ city }: { city: string }) => fetchWeather(city),\n * render: WeatherToolUI,\n * } satisfies AssistantToolProps<{ city: string }, Weather>;\n *\n * function WeatherToolRegistration() {\n * useAssistantTool(weatherTool);\n * return null;\n * }\n * ```\n */\nexport const useAssistantTool = <\n TArgs extends Record<string, unknown>,\n TResult,\n>(\n tool: AssistantToolProps<TArgs, TResult>,\n) => {\n const aui = useAui();\n\n useEffect(() => {\n if (!tool.render) return undefined;\n return aui.tools().setToolUI(tool.toolName, tool.render);\n }, [aui, tool.toolName, tool.render]);\n\n useEffect(() => {\n const { toolName, render, ...rest } = tool;\n const context = {\n tools: {\n [toolName]: rest,\n },\n };\n return aui.modelContext().register({\n getModelContext: () => context,\n });\n }, [aui, tool]);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,MAAa,oBAIX,SACG;CACH,MAAM,MAAM,OAAO;CAEnB,gBAAgB;EACd,IAAI,CAAC,KAAK,QAAQ,OAAO,KAAA;EACzB,OAAO,IAAI,MAAM,EAAE,UAAU,KAAK,UAAU,KAAK,MAAM;CACzD,GAAG;EAAC;EAAK,KAAK;EAAU,KAAK;CAAM,CAAC;CAEpC,gBAAgB;EACd,MAAM,EAAE,UAAU,QAAQ,GAAG,SAAS;EACtC,MAAM,UAAU,EACd,OAAO,GACJ,WAAW,KACd,EACF;EACA,OAAO,IAAI,aAAa,EAAE,SAAS,EACjC,uBAAuB,QACzB,CAAC;CACH,GAAG,CAAC,KAAK,IAAI,CAAC;AAChB"}
1
+ {"version":3,"file":"useAssistantTool.js","names":[],"sources":["../../../src/react/model-context/useAssistantTool.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type { ToolCallMessagePartComponent } from \"../types/MessagePartComponentTypes\";\nimport type { AssistantToolProps as CoreAssistantToolProps } from \"../..\";\nimport { isStandaloneToolDisplay } from \"./toolbox\";\n\n/**\n * Props used to register a tool from React.\n */\nexport type AssistantToolProps<\n TArgs extends Record<string, unknown>,\n TResult,\n> = CoreAssistantToolProps<TArgs, TResult> & {\n /** Component used to render calls to this tool in assistant messages. */\n render?: ToolCallMessagePartComponent<TArgs, TResult> | undefined;\n};\n\n/**\n * Registers a tool with the assistant model context while the component is\n * mounted.\n *\n * If `render` is provided, it is also installed as the renderer for matching\n * tool-call message parts. The registration is removed automatically when the\n * component unmounts or the tool definition changes.\n *\n * Pass a referentially stable tool object, such as one declared at module\n * scope or memoized with `useMemo`, to avoid re-registering on every render.\n *\n * @param tool - Tool definition and name to register.\n *\n * @example\n * ```tsx\n * const weatherTool = {\n * toolName: \"get_weather\",\n * type: \"frontend\",\n * description: \"Get the weather for a city.\",\n * parameters: weatherSchema,\n * execute: async ({ city }: { city: string }) => fetchWeather(city),\n * render: WeatherToolUI,\n * } satisfies AssistantToolProps<{ city: string }, Weather>;\n *\n * function WeatherToolRegistration() {\n * useAssistantTool(weatherTool);\n * return null;\n * }\n * ```\n */\nexport const useAssistantTool = <\n TArgs extends Record<string, unknown>,\n TResult,\n>(\n tool: AssistantToolProps<TArgs, TResult>,\n) => {\n const aui = useAui();\n\n const standalone = isStandaloneToolDisplay(tool);\n\n useEffect(() => {\n if (!tool.render) return undefined;\n return aui.tools().setToolUI(tool.toolName, tool.render, { standalone });\n }, [aui, tool.toolName, tool.render, standalone]);\n\n useEffect(() => {\n // `render` and `display` are client-only presentation concerns and never\n // reach the model.\n const { toolName, render, display, ...rest } = tool;\n const context = {\n tools: {\n [toolName]: rest,\n },\n };\n return aui.modelContext().register({\n getModelContext: () => context,\n });\n }, [aui, tool]);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,MAAa,oBAIX,SACG;CACH,MAAM,MAAM,OAAO;CAEnB,MAAM,aAAa,wBAAwB,IAAI;CAE/C,gBAAgB;EACd,IAAI,CAAC,KAAK,QAAQ,OAAO,KAAA;EACzB,OAAO,IAAI,MAAM,EAAE,UAAU,KAAK,UAAU,KAAK,QAAQ,EAAE,WAAW,CAAC;CACzE,GAAG;EAAC;EAAK,KAAK;EAAU,KAAK;EAAQ;CAAU,CAAC;CAEhD,gBAAgB;EAGd,MAAM,EAAE,UAAU,QAAQ,SAAS,GAAG,SAAS;EAC/C,MAAM,UAAU,EACd,OAAO,GACJ,WAAW,KACd,EACF;EACA,OAAO,IAAI,aAAa,EAAE,SAAS,EACjC,uBAAuB,QACzB,CAAC;CACH,GAAG,CAAC,KAAK,IAAI,CAAC;AAChB"}
@@ -5,6 +5,12 @@ import { ToolCallMessagePartComponent } from "../types/MessagePartComponentTypes
5
5
  type AssistantToolUIProps<TArgs, TResult> = {
6
6
  /** Name of the tool whose calls should use this renderer. */toolName: string; /** Component rendered for matching tool-call message parts. */
7
7
  render: ToolCallMessagePartComponent<TArgs, TResult>;
8
+ /**
9
+ * How the UI is presented relative to the chain-of-thought trace. Set
10
+ * `"standalone"` to surface it on its own (e.g. human-in-the-loop or
11
+ * generative UI for a backend/MCP tool). Defaults to `"inline"`.
12
+ */
13
+ display?: "standalone" | "inline";
8
14
  };
9
15
  /**
10
16
  * Registers a tool-call renderer while the component is mounted.
@@ -1 +1 @@
1
- {"version":3,"file":"useAssistantToolUI.d.ts","names":[],"sources":["../../../src/react/model-context/useAssistantToolUI.ts"],"mappings":";;;;KAKY,oBAAA;EAAA,6DAEV,QAAA,UAF8B;EAI9B,MAAA,EAAQ,4BAAA,CAA6B,KAAA,EAAO,OAAA;AAAA;;;;;;;;;;cAYjC,kBAAA,GACX,IAA2C,EAArC,oBAAoB"}
1
+ {"version":3,"file":"useAssistantToolUI.d.ts","names":[],"sources":["../../../src/react/model-context/useAssistantToolUI.ts"],"mappings":";;;;KAKY,oBAAA;EAAA,6DAEV,QAAA,UAF8B;EAI9B,MAAA,EAAQ,4BAAA,CAA6B,KAAA,EAAO,OAAA;EAAA;;;;;EAM5C,OAAA;AAAA;;;;;;;AAAO;AAYT;;cAAa,kBAAA,GACX,IAA2C,EAArC,oBAAoB"}
@@ -12,13 +12,15 @@ import { useAui } from "@assistant-ui/store";
12
12
  */
13
13
  const useAssistantToolUI = (tool) => {
14
14
  const aui = useAui();
15
+ const standalone = tool?.display === "standalone";
15
16
  useEffect(() => {
16
17
  if (!tool?.toolName || !tool?.render) return void 0;
17
- return aui.tools().setToolUI(tool.toolName, tool.render);
18
+ return aui.tools().setToolUI(tool.toolName, tool.render, { standalone });
18
19
  }, [
19
20
  aui,
20
21
  tool?.toolName,
21
- tool?.render
22
+ tool?.render,
23
+ standalone
22
24
  ]);
23
25
  };
24
26
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"useAssistantToolUI.js","names":[],"sources":["../../../src/react/model-context/useAssistantToolUI.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type { ToolCallMessagePartComponent } from \"../types/MessagePartComponentTypes\";\n\n/** Props used to register a renderer for tool-call message parts. */\nexport type AssistantToolUIProps<TArgs, TResult> = {\n /** Name of the tool whose calls should use this renderer. */\n toolName: string;\n /** Component rendered for matching tool-call message parts. */\n render: ToolCallMessagePartComponent<TArgs, TResult>;\n};\n\n/**\n * Registers a tool-call renderer while the component is mounted.\n *\n * This only affects rendering. Pair it with {@link useAssistantTool},\n * {@link Tools}, or a backend tool registry to expose the actual tool\n * definition to the model.\n *\n * @param tool - Tool renderer registration, or `null` to skip registration.\n */\nexport const useAssistantToolUI = (\n tool: AssistantToolUIProps<any, any> | null,\n) => {\n const aui = useAui();\n useEffect(() => {\n if (!tool?.toolName || !tool?.render) return undefined;\n return aui.tools().setToolUI(tool.toolName, tool.render);\n }, [aui, tool?.toolName, tool?.render]);\n};\n"],"mappings":";;;;;;;;;;;;AAqBA,MAAa,sBACX,SACG;CACH,MAAM,MAAM,OAAO;CACnB,gBAAgB;EACd,IAAI,CAAC,MAAM,YAAY,CAAC,MAAM,QAAQ,OAAO,KAAA;EAC7C,OAAO,IAAI,MAAM,EAAE,UAAU,KAAK,UAAU,KAAK,MAAM;CACzD,GAAG;EAAC;EAAK,MAAM;EAAU,MAAM;CAAM,CAAC;AACxC"}
1
+ {"version":3,"file":"useAssistantToolUI.js","names":[],"sources":["../../../src/react/model-context/useAssistantToolUI.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type { ToolCallMessagePartComponent } from \"../types/MessagePartComponentTypes\";\n\n/** Props used to register a renderer for tool-call message parts. */\nexport type AssistantToolUIProps<TArgs, TResult> = {\n /** Name of the tool whose calls should use this renderer. */\n toolName: string;\n /** Component rendered for matching tool-call message parts. */\n render: ToolCallMessagePartComponent<TArgs, TResult>;\n /**\n * How the UI is presented relative to the chain-of-thought trace. Set\n * `\"standalone\"` to surface it on its own (e.g. human-in-the-loop or\n * generative UI for a backend/MCP tool). Defaults to `\"inline\"`.\n */\n display?: \"standalone\" | \"inline\";\n};\n\n/**\n * Registers a tool-call renderer while the component is mounted.\n *\n * This only affects rendering. Pair it with {@link useAssistantTool},\n * {@link Tools}, or a backend tool registry to expose the actual tool\n * definition to the model.\n *\n * @param tool - Tool renderer registration, or `null` to skip registration.\n */\nexport const useAssistantToolUI = (\n tool: AssistantToolUIProps<any, any> | null,\n) => {\n const aui = useAui();\n const standalone = tool?.display === \"standalone\";\n useEffect(() => {\n if (!tool?.toolName || !tool?.render) return undefined;\n return aui.tools().setToolUI(tool.toolName, tool.render, { standalone });\n }, [aui, tool?.toolName, tool?.render, standalone]);\n};\n"],"mappings":";;;;;;;;;;;;AA2BA,MAAa,sBACX,SACG;CACH,MAAM,MAAM,OAAO;CACnB,MAAM,aAAa,MAAM,YAAY;CACrC,gBAAgB;EACd,IAAI,CAAC,MAAM,YAAY,CAAC,MAAM,QAAQ,OAAO,KAAA;EAC7C,OAAO,IAAI,MAAM,EAAE,UAAU,KAAK,UAAU,KAAK,QAAQ,EAAE,WAAW,CAAC;CACzE,GAAG;EAAC;EAAK,MAAM;EAAU,MAAM;EAAQ;CAAU,CAAC;AACpD"}
@@ -1 +1 @@
1
- {"version":3,"file":"useInlineRender.js","names":[],"sources":["../../../src/react/model-context/useInlineRender.ts"],"sourcesContent":["import { type FC, useCallback, useEffect, useState } from \"react\";\nimport type { ToolCallMessagePartProps } from \"../types/MessagePartComponentTypes\";\nimport { create } from \"zustand\";\n\nexport const useInlineRender = <TArgs, TResult>(\n toolUI: FC<ToolCallMessagePartProps<TArgs, TResult>>,\n): FC<ToolCallMessagePartProps<TArgs, TResult>> => {\n const [useToolUIStore] = useState(() =>\n create(() => ({\n toolUI,\n })),\n );\n\n useEffect(() => {\n useToolUIStore.setState({ toolUI });\n }, [toolUI, useToolUIStore]);\n\n return useCallback(\n function ToolUI(args) {\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const store = useToolUIStore();\n return store.toolUI(args);\n },\n [useToolUIStore],\n );\n};\n"],"mappings":";;;AAIA,MAAa,mBACX,WACiD;CACjD,MAAM,CAAC,kBAAkB,eACvB,cAAc,EACZ,OACF,EAAE,CACJ;CAEA,gBAAgB;EACd,eAAe,SAAS,EAAE,OAAO,CAAC;CACpC,GAAG,CAAC,QAAQ,cAAc,CAAC;CAE3B,OAAO,YACL,SAAS,OAAO,MAAM;EAGpB,OADc,eACH,EAAE,OAAO,IAAI;CAC1B,GACA,CAAC,cAAc,CACjB;AACF"}
1
+ {"version":3,"file":"useInlineRender.js","names":[],"sources":["../../../src/react/model-context/useInlineRender.ts"],"sourcesContent":["import { type FC, useCallback, useEffect, useState } from \"react\";\nimport type { ToolCallMessagePartProps } from \"../types/MessagePartComponentTypes\";\nimport { create } from \"zustand\";\n\nexport const useInlineRender = <TArgs, TResult>(\n toolUI: FC<ToolCallMessagePartProps<TArgs, TResult>>,\n): FC<ToolCallMessagePartProps<TArgs, TResult>> => {\n const [useToolUIStore] = useState(() =>\n create(() => ({\n toolUI,\n })),\n );\n\n useEffect(() => {\n useToolUIStore.setState({ toolUI });\n }, [toolUI, useToolUIStore]);\n\n return useCallback(\n function ToolUI(args) {\n const store = useToolUIStore();\n return store.toolUI(args);\n },\n [useToolUIStore],\n );\n};\n"],"mappings":";;;AAIA,MAAa,mBACX,WACiD;CACjD,MAAM,CAAC,kBAAkB,eACvB,cAAc,EACZ,OACF,EAAE,CACJ;CAEA,gBAAgB;EACd,eAAe,SAAS,EAAE,OAAO,CAAC;CACpC,GAAG,CAAC,QAAQ,cAAc,CAAC;CAE3B,OAAO,YACL,SAAS,OAAO,MAAM;EAEpB,OADc,eACH,EAAE,OAAO,IAAI;CAC1B,GACA,CAAC,cAAc,CACjB;AACF"}
@@ -1,6 +1,7 @@
1
1
  import { MessagePartStatus, ToolCallMessagePartStatus } from "../../../types/message.js";
2
2
  import { PartState } from "../../../store/scopes/part.js";
3
3
  import { EnrichedPartState } from "./MessageParts.js";
4
+ import { GroupByContext } from "../../utils/groupParts.js";
4
5
  import { ReactNode } from "react";
5
6
 
6
7
  //#region src/react/primitives/message/MessageGroupedParts.d.ts
@@ -16,13 +17,38 @@ declare namespace MessagePrimitiveGroupedParts {
16
17
  readonly status: MessagePartStatus | ToolCallMessagePartStatus;
17
18
  readonly indices: readonly number[];
18
19
  };
20
+ /**
21
+ * Synthetic trailing slot for a streaming/loading affordance (a
22
+ * "thinking…" dot, etc.). Surfaced through the same `{ part }` channel
23
+ * as groups and leaf parts so a single `switch (part.type)` renders it
24
+ * via `case "indicator"`.
25
+ *
26
+ * It is only ever emitted while the message is running, so its presence
27
+ * alone means "render your loading UI here" — there's no `status` to
28
+ * branch on.
29
+ */
30
+ type IndicatorPart = {
31
+ readonly type: "indicator";
32
+ };
33
+ /**
34
+ * When to emit the synthetic {@link IndicatorPart}. It is **only** emitted
35
+ * while the message is running (streaming); the mode further restricts
36
+ * which running states qualify:
37
+ * - `"never"` — never.
38
+ * - `"empty"` — only when the message has no parts yet.
39
+ * - `"no-text"` (default) — when the last part isn't `text`/`reasoning`
40
+ * (e.g. it ended on a tool call, so the assistant likely isn't done).
41
+ * - `"always"` — whenever the message is running, regardless of parts.
42
+ */
43
+ type IndicatorMode = "never" | "empty" | "no-text" | "always";
19
44
  type RenderInfo<TKey extends `group-${string}` = `group-${string}`> = {
20
45
  /**
21
46
  * Either a coalesced group ({@link GroupPart}, identified by a
22
- * `group-…` `type`) or a single enriched part. Use one switch over
23
- * `part.type` to handle both.
47
+ * `group-…` `type`), a single enriched leaf part, or the synthetic
48
+ * {@link IndicatorPart} (`type: "indicator"`). Use one switch over
49
+ * `part.type` to handle all three.
24
50
  */
25
- readonly part: GroupPart<TKey> | EnrichedPartState;
51
+ readonly part: GroupPart<TKey> | EnrichedPartState | IndicatorPart;
26
52
  /**
27
53
  * For group nodes: the recursively-rendered subtree (subgroups +
28
54
  * leaf parts). For leaf parts: a sentinel that throws when rendered
@@ -46,6 +72,9 @@ declare namespace MessagePrimitiveGroupedParts {
46
72
  * the helper isn't expressive enough (e.g. branching on
47
73
  * `part.toolName` or part metadata).
48
74
  *
75
+ * The second argument is a {@link GroupByContext} carrying the tool-UI
76
+ * registry, for grouping that depends on it (e.g. standalone tool calls).
77
+ *
49
78
  * @example
50
79
  * ```tsx
51
80
  * import { groupPartByType } from "@assistant-ui/react";
@@ -58,11 +87,22 @@ declare namespace MessagePrimitiveGroupedParts {
58
87
  * >
59
88
  * ```
60
89
  */
61
- readonly groupBy: (part: PartState) => readonly TKey[] | null;
90
+ readonly groupBy: (part: PartState, context: GroupByContext) => readonly TKey[] | null;
91
+ /**
92
+ * Controls emission of the synthetic {@link IndicatorPart} — a
93
+ * trailing `{ part: { type: "indicator", status } }` render call you
94
+ * handle with `case "indicator"` to show loading/status UI.
95
+ *
96
+ * @default "no-text"
97
+ * @see IndicatorMode
98
+ */
99
+ readonly indicator?: IndicatorMode;
62
100
  /**
63
- * Render function called once per group node and once per leaf part.
64
- * Switch on `part.type`: `"group-…"` cases wrap `children`; real
65
- * part types (`"text"`, `"tool-call"`, …) render the part directly.
101
+ * Render function called once per group node, once per leaf part, and
102
+ * (when the `indicator` condition is met) once for the trailing
103
+ * {@link IndicatorPart}. Switch on `part.type`: `"group-…"` cases wrap
104
+ * `children`; real part types (`"text"`, `"tool-call"`, …) render the
105
+ * part directly; `"indicator"` renders status/loading UI.
66
106
  *
67
107
  * Leaf parts receive the same {@link EnrichedPartState} that
68
108
  * `<MessagePrimitive.Parts>` would produce (`toolUI`, `addResult`,
@@ -97,6 +137,7 @@ declare namespace MessagePrimitiveGroupedParts {
97
137
  * case "group-tool": return <ToolStack>{children}</ToolStack>;
98
138
  * case "text": return <MarkdownText />;
99
139
  * case "tool-call": return part.toolUI ?? <ToolFallback {...part} />;
140
+ * case "indicator": return <LoadingDots />;
100
141
  * default: return null;
101
142
  * }
102
143
  * }}
@@ -106,6 +147,7 @@ declare namespace MessagePrimitiveGroupedParts {
106
147
  declare const MessagePrimitiveGroupedParts: {
107
148
  <TKey extends `group-${string}`>({
108
149
  groupBy,
150
+ indicator,
109
151
  children
110
152
  }: MessagePrimitiveGroupedParts.Props<TKey>): ReactNode;
111
153
  displayName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"MessageGroupedParts.d.ts","names":[],"sources":["../../../../src/react/primitives/message/MessageGroupedParts.tsx"],"mappings":";;;;;;kBAiBiB,4BAAA;;AAAjB;;;;;OAOc,SAAA;IAAA,SACD,IAAA,EAAM,IAAA;IAAA,SACN,MAAA,EAAQ,iBAAA,GAAoB,yBAAA;IAAA,SAC5B,OAAA;EAAA;EAAA,KAGC,UAAA;IA2CsC;;;;;IAAA,SArCvC,IAAA,EAAM,SAAA,CAAU,IAAA,IAAQ,iBAAA;IAZvB;;;;;;IAAA,SAmBD,QAAA,EAAU,SAAA;EAAA;EAAA,KAGT,KAAA;IAhBW;;;;;;;;;;;;;;;;;;;AAsDmC;AAqF5D;;;;;;IA3IyB,SA2CZ,OAAA,GAAU,IAAA,EAAM,SAAA,cAAuB,IAAA;IAmGN;;;;;;;;;IAAA,SAxFjC,QAAA,GAAW,IAAA,EAAM,UAAA,CAAW,IAAA,MAAU,SAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAqFtC,4BAAA;EAAA;IAA8D,OAAA;IAAA;EAAA,GAGxE,4BAAA,CAA6B,KAAA,CAAM,IAAA,IAAQ,SAAA"}
1
+ {"version":3,"file":"MessageGroupedParts.d.ts","names":[],"sources":["../../../../src/react/primitives/message/MessageGroupedParts.tsx"],"mappings":";;;;;;;kBAkBiB,4BAAA;;AAAjB;;;;;OAOc,SAAA;IAAA,SACD,IAAA,EAAM,IAAA;IAAA,SACN,MAAA,EAAQ,iBAAA,GAAoB,yBAAA;IAAA,SAC5B,OAAA;EAAA;EA2CU;;;;;;;;;;EAAA,KA9BT,aAAA;IAAA,SACD,IAAA;EAAA;EAhBM;;;;;;;;;;EAAA,KA6BL,aAAA;EAAA,KAEA,UAAA;IAOe;;;;;;IAAA,SAAhB,IAAA,EAAM,SAAA,CAAU,IAAA,IAAQ,iBAAA,GAAoB,aAAA;IAwC5C;;;;;;IAAA,SAjCA,QAAA,EAAU,SAAA;EAAA;EAAA,KAGT,KAAA;IAwDgB;;;;;AAA8B;AA+G5D;;;;;;;;;;;;;;;;;;;;;;;IA/G8B,SA1BjB,OAAA,GACP,IAAA,EAAM,SAAA,EACN,OAAA,EAAS,cAAA,cACG,IAAA;;;;;;;;;aAUL,SAAA,GAAY,aAAA;;;;;;;;;;;;aAaZ,QAAA,GAAW,IAAA,EAAM,UAAA,CAAW,IAAA,MAAU,SAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+GtC,4BAAA;EAAA;IAA8D,OAAA;IAAA,SAAA;IAAA;EAAA,GAIxE,4BAAA,CAA6B,KAAA,CAAM,IAAA,IAAQ,SAAA"}
@@ -3,10 +3,22 @@ import { MessagePartChildren } from "./MessageParts.js";
3
3
  import { GROUPBY_MEMO_KEY, buildGroupTree } from "../../utils/groupParts.js";
4
4
  import { Fragment, useMemo } from "react";
5
5
  import { useAuiState } from "@assistant-ui/store";
6
- import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
6
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
7
  import { useShallow } from "zustand/shallow";
8
8
  //#region src/react/primitives/message/MessageGroupedParts.tsx
9
9
  const COMPLETE_STATUS = Object.freeze({ type: "complete" });
10
+ const shouldShowIndicator = (mode, parts, isRunning) => {
11
+ if (!isRunning) return false;
12
+ switch (mode) {
13
+ case "never": return false;
14
+ case "always": return true;
15
+ case "empty": return parts.length === 0;
16
+ case "no-text": {
17
+ const last = parts[parts.length - 1];
18
+ return last !== void 0 && last.type !== "text" && last.type !== "reasoning";
19
+ }
20
+ }
21
+ };
10
22
  /**
11
23
  * `children` placeholder passed for leaf-part renders. Leaf parts have no
12
24
  * inner subtree; rendering this sentinel signals the consumer wrote
@@ -60,15 +72,28 @@ const renderNode = (node, parts, render) => {
60
72
  * case "group-tool": return <ToolStack>{children}</ToolStack>;
61
73
  * case "text": return <MarkdownText />;
62
74
  * case "tool-call": return part.toolUI ?? <ToolFallback {...part} />;
75
+ * case "indicator": return <LoadingDots />;
63
76
  * default: return null;
64
77
  * }
65
78
  * }}
66
79
  * </MessagePrimitive.GroupedParts>
67
80
  * ```
68
81
  */
69
- const MessagePrimitiveGroupedParts = ({ groupBy, children }) => {
82
+ const MessagePrimitiveGroupedParts = ({ groupBy, indicator = "no-text", children }) => {
70
83
  const parts = useAuiState(useShallow((s) => s.message.parts));
71
- return /* @__PURE__ */ jsx(Fragment$1, { children: useMemo(() => buildGroupTree(parts.map((part) => groupBy(part) ?? [])), [parts, groupBy[GROUPBY_MEMO_KEY] ?? groupBy]).map((node) => renderNode(node, parts, children)) });
84
+ const toolUIs = useAuiState((s) => s.tools.toolUIs);
85
+ const isRunning = useAuiState((s) => indicator === "never" ? false : s.message.status?.type === "running");
86
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [useMemo(() => {
87
+ const context = { toolUIs };
88
+ return buildGroupTree(parts.map((part) => groupBy(part, context) ?? []));
89
+ }, [
90
+ parts,
91
+ groupBy[GROUPBY_MEMO_KEY] ?? groupBy,
92
+ toolUIs
93
+ ]).map((node) => renderNode(node, parts, children)), shouldShowIndicator(indicator, parts, isRunning) && children({
94
+ part: { type: "indicator" },
95
+ children: /* @__PURE__ */ jsx(PartChildrenSentinel, {})
96
+ })] });
72
97
  };
73
98
  MessagePrimitiveGroupedParts.displayName = "MessagePrimitive.GroupedParts";
74
99
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"MessageGroupedParts.js","names":[],"sources":["../../../../src/react/primitives/message/MessageGroupedParts.tsx"],"sourcesContent":["\"use client\";\n\nimport { Fragment, type FC, type ReactNode, useMemo } from \"react\";\nimport { useAuiState } from \"@assistant-ui/store\";\nimport { useShallow } from \"zustand/shallow\";\nimport type { PartState } from \"../../../store/scopes/part\";\nimport type {\n MessagePartStatus,\n ToolCallMessagePartStatus,\n} from \"../../../types/message\";\nimport {\n buildGroupTree,\n GROUPBY_MEMO_KEY,\n type GroupNode,\n} from \"../../utils/groupParts\";\nimport { MessagePartChildren, type EnrichedPartState } from \"./MessageParts\";\n\nexport namespace MessagePrimitiveGroupedParts {\n /**\n * A coalesced group of adjacent parts. Surfaced through the same\n * `{ part }` channel as a leaf {@link EnrichedPartState} so consumers\n * dispatch on a single `switch (part.type)`. `type` is the group key\n * (always `\"group-…\"`); `status` mirrors the last contained part.\n */\n export type GroupPart<TKey extends `group-${string}` = `group-${string}`> = {\n readonly type: TKey;\n readonly status: MessagePartStatus | ToolCallMessagePartStatus;\n readonly indices: readonly number[];\n };\n\n export type RenderInfo<TKey extends `group-${string}` = `group-${string}`> = {\n /**\n * Either a coalesced group ({@link GroupPart}, identified by a\n * `group-…` `type`) or a single enriched part. Use one switch over\n * `part.type` to handle both.\n */\n readonly part: GroupPart<TKey> | EnrichedPartState;\n /**\n * For group nodes: the recursively-rendered subtree (subgroups +\n * leaf parts). For leaf parts: a sentinel that throws when rendered\n * — accidental fall-through (`default: return children;`) errors\n * loudly instead of silently rendering nothing.\n */\n readonly children: ReactNode;\n };\n\n export type Props<TKey extends `group-${string}` = `group-${string}`> = {\n /**\n * Maps each part to a group-key path. Adjacent parts that share a\n * prefix coalesce into the same group. Return `[]` (or `null`) to\n * leave a part ungrouped.\n *\n * Group keys must start with `\"group-\"` so the renderer's\n * `switch (part.type)` can tell groups apart from real part types.\n *\n * **Prefer {@link groupPartByType}** for the common case of mapping by\n * `part.type` — it ships a stable memo fingerprint so the tree\n * survives unrelated re-renders. Use an inline function only when\n * the helper isn't expressive enough (e.g. branching on\n * `part.toolName` or part metadata).\n *\n * @example\n * ```tsx\n * import { groupPartByType } from \"@assistant-ui/react\";\n *\n * <MessagePrimitive.GroupedParts\n * groupBy={groupPartByType({\n * reasoning: [\"group-thought\", \"group-reasoning\"],\n * \"tool-call\": [\"group-thought\", \"group-tool\"],\n * })}\n * >\n * ```\n */\n readonly groupBy: (part: PartState) => readonly TKey[] | null;\n\n /**\n * Render function called once per group node and once per leaf part.\n * Switch on `part.type`: `\"group-…\"` cases wrap `children`; real\n * part types (`\"text\"`, `\"tool-call\"`, …) render the part directly.\n *\n * Leaf parts receive the same {@link EnrichedPartState} that\n * `<MessagePrimitive.Parts>` would produce (`toolUI`, `addResult`,\n * `resume`, `respondToApproval`, `dataRendererUI`).\n */\n readonly children: (info: RenderInfo<TKey>) => ReactNode;\n };\n}\n\nconst COMPLETE_STATUS: MessagePartStatus = Object.freeze({ type: \"complete\" });\n\n/**\n * `children` placeholder passed for leaf-part renders. Leaf parts have no\n * inner subtree; rendering this sentinel signals the consumer wrote\n * `default: return children;` and accidentally fell through for a part —\n * surface the bug loudly instead of silently rendering nothing.\n */\nconst PartChildrenSentinel: FC = () => {\n throw new Error(\n \"MessagePrimitive.GroupedParts: rendered `children` under a leaf \" +\n \"part. `children` is only meaningful for `group-…` cases — add a \" +\n \"matching case for the part type or return `null` to skip it.\",\n );\n};\n\nconst renderNode = <TKey extends `group-${string}`>(\n node: GroupNode,\n parts: readonly PartState[],\n render: (info: MessagePrimitiveGroupedParts.RenderInfo<TKey>) => ReactNode,\n): ReactNode => {\n if (node.type === \"part\") {\n // Key by absolute part index, not structural nodeKey — prevents zombie fiber subscriptions when parts reshape (#4051).\n return (\n <MessagePartChildren key={`part-${node.index}`} index={node.index}>\n {({ part }) => render({ part, children: <PartChildrenSentinel /> })}\n </MessagePartChildren>\n );\n }\n\n const status = parts[node.indices.at(-1)!]?.status ?? COMPLETE_STATUS;\n const groupPart: MessagePrimitiveGroupedParts.GroupPart<TKey> = {\n type: node.key as TKey,\n status,\n indices: node.indices,\n };\n\n return (\n <Fragment key={node.nodeKey}>\n {render({\n part: groupPart,\n children: (\n <>{node.children.map((child) => renderNode(child, parts, render))}</>\n ),\n })}\n </Fragment>\n );\n};\n\n/**\n * Groups adjacent message parts into a tree of coalesced runs and\n * renders each node — group or part — through a single `children`\n * function.\n *\n * The render function receives `{ part, children }` where `part.type`\n * is either a `\"group-…\"` literal (for a group, `children` is the\n * recursively-rendered subtree) or a real part type (`\"text\"`,\n * `\"tool-call\"`, …) for a leaf (`children` is a sentinel that throws\n * if rendered — use `part.type` to distinguish).\n *\n * @example\n * ```tsx\n * <MessagePrimitive.GroupedParts\n * groupBy={groupPartByType({\n * reasoning: [\"group-thought\", \"group-reasoning\"],\n * \"tool-call\": [\"group-thought\", \"group-tool\"],\n * })}\n * >\n * {({ part, children }) => {\n * switch (part.type) {\n * case \"group-thought\": return <Thought>{children}</Thought>;\n * case \"group-reasoning\": return <Reasoning>{children}</Reasoning>;\n * case \"group-tool\": return <ToolStack>{children}</ToolStack>;\n * case \"text\": return <MarkdownText />;\n * case \"tool-call\": return part.toolUI ?? <ToolFallback {...part} />;\n * default: return null;\n * }\n * }}\n * </MessagePrimitive.GroupedParts>\n * ```\n */\nexport const MessagePrimitiveGroupedParts = <TKey extends `group-${string}`>({\n groupBy,\n children,\n}: MessagePrimitiveGroupedParts.Props<TKey>): ReactNode => {\n const parts = useAuiState(useShallow((s) => s.message.parts));\n\n // Helpers like `groupPartByType` tag the function with `GROUPBY_MEMO_KEY`\n // (a stable string fingerprint of the helper config). When present,\n // memo on `[parts, memoKey]` so the tree survives unrelated renders.\n // For inline `groupBy`, fall back to recomputing each render — O(n)\n // and cheap.\n const memoKey = (groupBy as { [GROUPBY_MEMO_KEY]?: string })[\n GROUPBY_MEMO_KEY\n ];\n const memoDep = memoKey ?? groupBy;\n const tree = useMemo(\n () => buildGroupTree(parts.map((part) => groupBy(part) ?? [])),\n // oxlint-disable-next-line tap-hooks/exhaustive-deps -- groupBy is captured via memoDep (either its identity or the helper's memoKey fingerprint); listing it directly would defeat the helper-tagged memo path\n [parts, memoDep],\n );\n\n return <>{tree.map((node) => renderNode(node, parts, children))}</>;\n};\n\nMessagePrimitiveGroupedParts.displayName = \"MessagePrimitive.GroupedParts\";\n"],"mappings":";;;;;;;;AAwFA,MAAM,kBAAqC,OAAO,OAAO,EAAE,MAAM,WAAW,CAAC;;;;;;;AAQ7E,MAAM,6BAAiC;CACrC,MAAM,IAAI,MACR,8LAGF;AACF;AAEA,MAAM,cACJ,MACA,OACA,WACc;CACd,IAAI,KAAK,SAAS,QAEhB,OACE,oBAAC,qBAAD;EAAgD,OAAO,KAAK;aACxD,EAAE,WAAW,OAAO;GAAE;GAAM,UAAU,oBAAC,sBAAD,CAAuB,CAAA;EAAE,CAAC;CAC/C,GAFK,QAAQ,KAAK,OAElB;CAIzB,MAAM,SAAS,MAAM,KAAK,QAAQ,GAAG,EAAE,IAAK,UAAU;CAOtD,OACE,oBAAC,UAAD,EAAA,UACG,OAAO;EACN,MAAM;GARV,MAAM,KAAK;GACX;GACA,SAAS,KAAK;EAMI;EACd,UACE,oBAAA,YAAA,EAAA,UAAG,KAAK,SAAS,KAAK,UAAU,WAAW,OAAO,OAAO,MAAM,CAAC,EAAI,CAAA;CAExE,CAAC,EACO,GAPK,KAAK,OAOV;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,MAAa,gCAAgE,EAC3E,SACA,eACyD;CACzD,MAAM,QAAQ,YAAY,YAAY,MAAM,EAAE,QAAQ,KAAK,CAAC;CAiB5D,OAAO,oBAAA,YAAA,EAAA,UANM,cACL,eAAe,MAAM,KAAK,SAAS,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,GAE7D,CAAC,OAPc,QACf,qBAEyB,OAIV,CAGJ,EAAE,KAAK,SAAS,WAAW,MAAM,OAAO,QAAQ,CAAC,EAAI,CAAA;AACpE;AAEA,6BAA6B,cAAc"}
1
+ {"version":3,"file":"MessageGroupedParts.js","names":[],"sources":["../../../../src/react/primitives/message/MessageGroupedParts.tsx"],"sourcesContent":["\"use client\";\n\nimport { Fragment, type FC, type ReactNode, useMemo } from \"react\";\nimport { useAuiState } from \"@assistant-ui/store\";\nimport { useShallow } from \"zustand/shallow\";\nimport type { PartState } from \"../../../store/scopes/part\";\nimport type {\n MessagePartStatus,\n ToolCallMessagePartStatus,\n} from \"../../../types/message\";\nimport {\n buildGroupTree,\n GROUPBY_MEMO_KEY,\n type GroupByContext,\n type GroupNode,\n} from \"../../utils/groupParts\";\nimport { MessagePartChildren, type EnrichedPartState } from \"./MessageParts\";\n\nexport namespace MessagePrimitiveGroupedParts {\n /**\n * A coalesced group of adjacent parts. Surfaced through the same\n * `{ part }` channel as a leaf {@link EnrichedPartState} so consumers\n * dispatch on a single `switch (part.type)`. `type` is the group key\n * (always `\"group-…\"`); `status` mirrors the last contained part.\n */\n export type GroupPart<TKey extends `group-${string}` = `group-${string}`> = {\n readonly type: TKey;\n readonly status: MessagePartStatus | ToolCallMessagePartStatus;\n readonly indices: readonly number[];\n };\n\n /**\n * Synthetic trailing slot for a streaming/loading affordance (a\n * \"thinking…\" dot, etc.). Surfaced through the same `{ part }` channel\n * as groups and leaf parts so a single `switch (part.type)` renders it\n * via `case \"indicator\"`.\n *\n * It is only ever emitted while the message is running, so its presence\n * alone means \"render your loading UI here\" — there's no `status` to\n * branch on.\n */\n export type IndicatorPart = {\n readonly type: \"indicator\";\n };\n\n /**\n * When to emit the synthetic {@link IndicatorPart}. It is **only** emitted\n * while the message is running (streaming); the mode further restricts\n * which running states qualify:\n * - `\"never\"` — never.\n * - `\"empty\"` — only when the message has no parts yet.\n * - `\"no-text\"` (default) — when the last part isn't `text`/`reasoning`\n * (e.g. it ended on a tool call, so the assistant likely isn't done).\n * - `\"always\"` — whenever the message is running, regardless of parts.\n */\n export type IndicatorMode = \"never\" | \"empty\" | \"no-text\" | \"always\";\n\n export type RenderInfo<TKey extends `group-${string}` = `group-${string}`> = {\n /**\n * Either a coalesced group ({@link GroupPart}, identified by a\n * `group-…` `type`), a single enriched leaf part, or the synthetic\n * {@link IndicatorPart} (`type: \"indicator\"`). Use one switch over\n * `part.type` to handle all three.\n */\n readonly part: GroupPart<TKey> | EnrichedPartState | IndicatorPart;\n /**\n * For group nodes: the recursively-rendered subtree (subgroups +\n * leaf parts). For leaf parts: a sentinel that throws when rendered\n * — accidental fall-through (`default: return children;`) errors\n * loudly instead of silently rendering nothing.\n */\n readonly children: ReactNode;\n };\n\n export type Props<TKey extends `group-${string}` = `group-${string}`> = {\n /**\n * Maps each part to a group-key path. Adjacent parts that share a\n * prefix coalesce into the same group. Return `[]` (or `null`) to\n * leave a part ungrouped.\n *\n * Group keys must start with `\"group-\"` so the renderer's\n * `switch (part.type)` can tell groups apart from real part types.\n *\n * **Prefer {@link groupPartByType}** for the common case of mapping by\n * `part.type` — it ships a stable memo fingerprint so the tree\n * survives unrelated re-renders. Use an inline function only when\n * the helper isn't expressive enough (e.g. branching on\n * `part.toolName` or part metadata).\n *\n * The second argument is a {@link GroupByContext} carrying the tool-UI\n * registry, for grouping that depends on it (e.g. standalone tool calls).\n *\n * @example\n * ```tsx\n * import { groupPartByType } from \"@assistant-ui/react\";\n *\n * <MessagePrimitive.GroupedParts\n * groupBy={groupPartByType({\n * reasoning: [\"group-thought\", \"group-reasoning\"],\n * \"tool-call\": [\"group-thought\", \"group-tool\"],\n * })}\n * >\n * ```\n */\n readonly groupBy: (\n part: PartState,\n context: GroupByContext,\n ) => readonly TKey[] | null;\n\n /**\n * Controls emission of the synthetic {@link IndicatorPart} — a\n * trailing `{ part: { type: \"indicator\", status } }` render call you\n * handle with `case \"indicator\"` to show loading/status UI.\n *\n * @default \"no-text\"\n * @see IndicatorMode\n */\n readonly indicator?: IndicatorMode;\n\n /**\n * Render function called once per group node, once per leaf part, and\n * (when the `indicator` condition is met) once for the trailing\n * {@link IndicatorPart}. Switch on `part.type`: `\"group-…\"` cases wrap\n * `children`; real part types (`\"text\"`, `\"tool-call\"`, …) render the\n * part directly; `\"indicator\"` renders status/loading UI.\n *\n * Leaf parts receive the same {@link EnrichedPartState} that\n * `<MessagePrimitive.Parts>` would produce (`toolUI`, `addResult`,\n * `resume`, `respondToApproval`, `dataRendererUI`).\n */\n readonly children: (info: RenderInfo<TKey>) => ReactNode;\n };\n}\n\nconst COMPLETE_STATUS: MessagePartStatus = Object.freeze({ type: \"complete\" });\n\nconst shouldShowIndicator = (\n mode: MessagePrimitiveGroupedParts.IndicatorMode,\n parts: readonly PartState[],\n isRunning: boolean,\n): boolean => {\n // The indicator is a streaming affordance — never show it on a settled\n // message, whatever the mode.\n if (!isRunning) return false;\n\n switch (mode) {\n case \"never\":\n return false;\n case \"always\":\n return true;\n case \"empty\":\n return parts.length === 0;\n case \"no-text\": {\n const last = parts[parts.length - 1];\n return (\n last !== undefined && last.type !== \"text\" && last.type !== \"reasoning\"\n );\n }\n }\n};\n\n/**\n * `children` placeholder passed for leaf-part renders. Leaf parts have no\n * inner subtree; rendering this sentinel signals the consumer wrote\n * `default: return children;` and accidentally fell through for a part —\n * surface the bug loudly instead of silently rendering nothing.\n */\nconst PartChildrenSentinel: FC = () => {\n throw new Error(\n \"MessagePrimitive.GroupedParts: rendered `children` under a leaf \" +\n \"part. `children` is only meaningful for `group-…` cases — add a \" +\n \"matching case for the part type or return `null` to skip it.\",\n );\n};\n\nconst renderNode = <TKey extends `group-${string}`>(\n node: GroupNode,\n parts: readonly PartState[],\n render: (info: MessagePrimitiveGroupedParts.RenderInfo<TKey>) => ReactNode,\n): ReactNode => {\n if (node.type === \"part\") {\n // Key by absolute part index, not structural nodeKey — prevents zombie fiber subscriptions when parts reshape (#4051).\n return (\n <MessagePartChildren key={`part-${node.index}`} index={node.index}>\n {({ part }) => render({ part, children: <PartChildrenSentinel /> })}\n </MessagePartChildren>\n );\n }\n\n const status = parts[node.indices.at(-1)!]?.status ?? COMPLETE_STATUS;\n const groupPart: MessagePrimitiveGroupedParts.GroupPart<TKey> = {\n type: node.key as TKey,\n status,\n indices: node.indices,\n };\n\n return (\n <Fragment key={node.nodeKey}>\n {render({\n part: groupPart,\n children: (\n <>{node.children.map((child) => renderNode(child, parts, render))}</>\n ),\n })}\n </Fragment>\n );\n};\n\n/**\n * Groups adjacent message parts into a tree of coalesced runs and\n * renders each node — group or part — through a single `children`\n * function.\n *\n * The render function receives `{ part, children }` where `part.type`\n * is either a `\"group-…\"` literal (for a group, `children` is the\n * recursively-rendered subtree) or a real part type (`\"text\"`,\n * `\"tool-call\"`, …) for a leaf (`children` is a sentinel that throws\n * if rendered — use `part.type` to distinguish).\n *\n * @example\n * ```tsx\n * <MessagePrimitive.GroupedParts\n * groupBy={groupPartByType({\n * reasoning: [\"group-thought\", \"group-reasoning\"],\n * \"tool-call\": [\"group-thought\", \"group-tool\"],\n * })}\n * >\n * {({ part, children }) => {\n * switch (part.type) {\n * case \"group-thought\": return <Thought>{children}</Thought>;\n * case \"group-reasoning\": return <Reasoning>{children}</Reasoning>;\n * case \"group-tool\": return <ToolStack>{children}</ToolStack>;\n * case \"text\": return <MarkdownText />;\n * case \"tool-call\": return part.toolUI ?? <ToolFallback {...part} />;\n * case \"indicator\": return <LoadingDots />;\n * default: return null;\n * }\n * }}\n * </MessagePrimitive.GroupedParts>\n * ```\n */\nexport const MessagePrimitiveGroupedParts = <TKey extends `group-${string}`>({\n groupBy,\n indicator = \"no-text\",\n children,\n}: MessagePrimitiveGroupedParts.Props<TKey>): ReactNode => {\n const parts = useAuiState(useShallow((s) => s.message.parts));\n // Handed to `groupBy` as its `context` argument (see GroupByContext).\n const toolUIs = useAuiState((s) => s.tools.toolUIs);\n // Subscribe to a boolean, not the status object: the tree only needs to\n // re-render when running-ness flips, and `\"never\"` opts out entirely.\n const isRunning = useAuiState((s) =>\n indicator === \"never\" ? false : s.message.status?.type === \"running\",\n );\n\n // Helpers like `groupPartByType` tag the function with `GROUPBY_MEMO_KEY`\n // (a stable string fingerprint of the helper config). When present,\n // memo on `[parts, memoKey]` so the tree survives unrelated renders.\n // For inline `groupBy`, fall back to recomputing each render — O(n)\n // and cheap.\n const memoKey = (groupBy as { [GROUPBY_MEMO_KEY]?: string })[\n GROUPBY_MEMO_KEY\n ];\n const memoDep = memoKey ?? groupBy;\n const tree = useMemo(() => {\n const context: GroupByContext = { toolUIs };\n return buildGroupTree(parts.map((part) => groupBy(part, context) ?? []));\n // oxlint-disable-next-line tap-hooks/exhaustive-deps -- groupBy is captured via memoDep (either its identity or the helper's memoKey fingerprint); listing it directly would defeat the helper-tagged memo path\n }, [parts, memoDep, toolUIs]);\n\n return (\n <>\n {tree.map((node) => renderNode(node, parts, children))}\n {shouldShowIndicator(indicator, parts, isRunning) &&\n children({\n part: { type: \"indicator\" },\n children: <PartChildrenSentinel />,\n })}\n </>\n );\n};\n\nMessagePrimitiveGroupedParts.displayName = \"MessagePrimitive.GroupedParts\";\n"],"mappings":";;;;;;;;AAsIA,MAAM,kBAAqC,OAAO,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7E,MAAM,uBACJ,MACA,OACA,cACY;CAGZ,IAAI,CAAC,WAAW,OAAO;CAEvB,QAAQ,MAAR;EACE,KAAK,SACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,SACH,OAAO,MAAM,WAAW;EAC1B,KAAK,WAAW;GACd,MAAM,OAAO,MAAM,MAAM,SAAS;GAClC,OACE,SAAS,KAAA,KAAa,KAAK,SAAS,UAAU,KAAK,SAAS;EAEhE;CACF;AACF;;;;;;;AAQA,MAAM,6BAAiC;CACrC,MAAM,IAAI,MACR,8LAGF;AACF;AAEA,MAAM,cACJ,MACA,OACA,WACc;CACd,IAAI,KAAK,SAAS,QAEhB,OACE,oBAAC,qBAAD;EAAgD,OAAO,KAAK;aACxD,EAAE,WAAW,OAAO;GAAE;GAAM,UAAU,oBAAC,sBAAD,CAAuB,CAAA;EAAE,CAAC;CAC/C,GAFK,QAAQ,KAAK,OAElB;CAIzB,MAAM,SAAS,MAAM,KAAK,QAAQ,GAAG,EAAE,IAAK,UAAU;CAOtD,OACE,oBAAC,UAAD,EAAA,UACG,OAAO;EACN,MAAM;GARV,MAAM,KAAK;GACX;GACA,SAAS,KAAK;EAMI;EACd,UACE,oBAAA,YAAA,EAAA,UAAG,KAAK,SAAS,KAAK,UAAU,WAAW,OAAO,OAAO,MAAM,CAAC,EAAI,CAAA;CAExE,CAAC,EACO,GAPK,KAAK,OAOV;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAa,gCAAgE,EAC3E,SACA,YAAY,WACZ,eACyD;CACzD,MAAM,QAAQ,YAAY,YAAY,MAAM,EAAE,QAAQ,KAAK,CAAC;CAE5D,MAAM,UAAU,aAAa,MAAM,EAAE,MAAM,OAAO;CAGlD,MAAM,YAAY,aAAa,MAC7B,cAAc,UAAU,QAAQ,EAAE,QAAQ,QAAQ,SAAS,SAC7D;CAiBA,OACE,qBAAA,YAAA,EAAA,UAAA,CAPW,cAAc;EACzB,MAAM,UAA0B,EAAE,QAAQ;EAC1C,OAAO,eAAe,MAAM,KAAK,SAAS,QAAQ,MAAM,OAAO,KAAK,CAAC,CAAC,CAAC;CAEzE,GAAG;EAAC;EARa,QACf,qBAEyB;EAKP;CAAO,CAInB,EAAE,KAAK,SAAS,WAAW,MAAM,OAAO,QAAQ,CAAC,GACpD,oBAAoB,WAAW,OAAO,SAAS,KAC9C,SAAS;EACP,MAAM,EAAE,MAAM,YAAY;EAC1B,UAAU,oBAAC,sBAAD,CAAuB,CAAA;CACnC,CAAC,CACH,EAAA,CAAA;AAEN;AAEA,6BAA6B,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"MessageParts.d.ts","names":[],"sources":["../../../../src/react/primitives/message/MessageParts.tsx"],"mappings":";;;;;kBA6JiB,qBAAA;EAAA,KACV,UAAA;IADU,kDAGb,OAAA,GAAU,MAAA,SAAe,wBAAA,2BAHS;IAKlC,QAAA,GAAW,wBAAA;EAAA;EAAA,KAGR,cAAA;IAEK,6CAAR,KAAA,GAAQ,yBAAA,cAIC;IAFT,IAAA,GAAO,wBAAA,cAMA;IAJP,MAAA,GAAS,0BAAA,cAQF;IANP,KAAA,GAAQ,yBAAA,cAoBU;IAlBlB,IAAA,GAAO,wBAAA,cA+BgB;IA7BvB,cAAA,GAAiB,kCAAA,cAgCY;IA9B7B,IAAA,GAAO,UAAA,cAkCqB;IAhC5B,KAAA,GAAQ,yBAAA;IAyCgB;;;;;;;;IAhCxB,YAAA;MA+FsC,uDA5FhC,UAAA,EAAY,6BAAA,EAyGoC;MAvGhD,QAAA,GACI,aAAA;QAAgB,SAAA;QAAmB,KAAA;MAAA;IAAA;EAAA;EAAA,KAM1C,WAAA;IAxCQ,qDA2CP,OAAA,GACI,MAAA,SAAe,4BAAA,2BAvCvB;IA0CI,QAAA,GAAW,aAAA,CAAc,wBAAA;EAAA;IAxCtB,qDA4CH,QAAA,EAAU,aAAA,CAAc,wBAAA;EAAA;EAxC5B;;;;;;EAAA,KAiDG,kBAAA,GAAqB,cAAA;IA3CjB,mEA6CP,SAAA,GAAY,6BAAA,cA3CJ;IA6CR,KAAA,GAAQ,WAAA;IAjCF;;;;;;;;;IA4CN,SAAA,GAAY,aAAA,CACV,iBAAA;MAAoB,UAAA;MAAoB,QAAA;IAAA;IAzBtC;;;;;;;;;IAqCJ,cAAA,GAAiB,uBAAA;IAEjB,cAAA;EAAA;EAdsB;;;;;;;EAAA,KAwBnB,wBAAA,GAA2B,cAAA;IAMd;;;;;IAAhB,cAAA,EAAgB,aAAA;IAEhB,SAAA;IACA,KAAA;IACA,SAAA;IACA,cAAA;EAAA;EAAA,YAGU,KAAA;IAsBc;;;;;;;IAbpB,UAAA,GAAa,kBAAA,GAAqB,wBAAA;IA6D7B;;;;;;;IArDL,8BAAA;IACA,QAAA;EAAA;IA4D0C,8EAxD1C,QAAA,GAAW,KAAA;MAAS,IAAA,EAAM,iBAAA;IAAA,MAAwB,SAAA;IAClD,UAAA;IACA,8BAAA;EAAA;EAAA;AAAA;;;;;cA8CK,iBAAA;;;;;;;;;KAOe,iBAAA,KAAiB,SAAA;;;KACZ,iBAAA,KAAiB,SAAA;AAAA;AAAA,KAG7C,yBAAA;EACH,UAAA,EAAY,qBAAA,CAAsB,KAAK;AAAA;AAAA,cAG5B,oBAAA,EAAsB,EAAE,CAAC,yBAAA;AAAA,kBAkGrB,2BAAA;EAAA,KACH,KAAA;IACV,KAAA;IACA,UAAA,EAAY,qBAAA,CAAsB,KAAK;EAAA;AAAA;AAH3C;;;AAAA,cAUa,2BAAA,EAA6B,EAAE,CAAC,2BAAA,CAA4B,KAAA;;;;;;AAP9B;AAO3C;;;;;;KAgMY,iBAAA,IACP,OAAA,CAAQ,SAAA;EAAa,IAAA;AAAA;EADd,2EAGG,MAAA,EAAQ,SAAA;EAEjB,SAAA,EAAW,wBAAA,eAJZ;EAMC,MAAA,EAAQ,wBAAA,YAFG;EAIX,iBAAA,EAAmB,wBAAA;AAAA,MAEpB,OAAA,CAAQ,SAAA;EAAa,IAAA;AAAA;EAEK,oFAAhB,cAAA,EAAgB,SAAA;AAAA,KAE3B,OAAA,CAAQ,SAAA;EAAa,IAAA;AAAA;EAAwB,IAAA;AAAA;;;;;;;cAoGpC,qBAAA,EAAuB,EAAE,CAAC,qBAAA,CAAsB,KAAA"}
1
+ {"version":3,"file":"MessageParts.d.ts","names":[],"sources":["../../../../src/react/primitives/message/MessageParts.tsx"],"mappings":";;;;;kBA6JiB,qBAAA;EAAA,KACV,UAAA;IADU,kDAGb,OAAA,GAAU,MAAA,SAAe,wBAAA,2BAHS;IAKlC,QAAA,GAAW,wBAAA;EAAA;EAAA,KAGR,cAAA;IAEK,6CAAR,KAAA,GAAQ,yBAAA,cAIC;IAFT,IAAA,GAAO,wBAAA,cAMA;IAJP,MAAA,GAAS,0BAAA,cAQF;IANP,KAAA,GAAQ,yBAAA,cAoBU;IAlBlB,IAAA,GAAO,wBAAA,cA+BgB;IA7BvB,cAAA,GAAiB,kCAAA,cAgCY;IA9B7B,IAAA,GAAO,UAAA,cAkCqB;IAhC5B,KAAA,GAAQ,yBAAA;IAyCgB;;;;;;;;IAhCxB,YAAA;MA+FsC,uDA5FhC,UAAA,EAAY,6BAAA,EAyGoC;MAvGhD,QAAA,GACI,aAAA;QAAgB,SAAA;QAAmB,KAAA;MAAA;IAAA;EAAA;EAAA,KAM1C,WAAA;IAxCQ,qDA2CP,OAAA,GACI,MAAA,SAAe,4BAAA,2BAvCvB;IA0CI,QAAA,GAAW,aAAA,CAAc,wBAAA;EAAA;IAxCtB,qDA4CH,QAAA,EAAU,aAAA,CAAc,wBAAA;EAAA;EAxC5B;;;;;;EAAA,KAiDG,kBAAA,GAAqB,cAAA;IA3CjB,mEA6CP,SAAA,GAAY,6BAAA,cA3CJ;IA6CR,KAAA,GAAQ,WAAA;IAjCF;;;;;;;;;IA4CN,SAAA,GAAY,aAAA,CACV,iBAAA;MAAoB,UAAA;MAAoB,QAAA;IAAA;IAzBtC;;;;;;;;;IAqCJ,cAAA,GAAiB,uBAAA;IAEjB,cAAA;EAAA;EAdsB;;;;;;;EAAA,KAwBnB,wBAAA,GAA2B,cAAA;IAMd;;;;;IAAhB,cAAA,EAAgB,aAAA;IAEhB,SAAA;IACA,KAAA;IACA,SAAA;IACA,cAAA;EAAA;EAAA,YAGU,KAAA;IAsBc;;;;;;;IAbpB,UAAA,GAAa,kBAAA,GAAqB,wBAAA;IA2D7B;;;;;;;IAnDL,8BAAA;IACA,QAAA;EAAA;IA0D0C,8EAtD1C,QAAA,GAAW,KAAA;MAAS,IAAA,EAAM,iBAAA;IAAA,MAAwB,SAAA;IAClD,UAAA;IACA,8BAAA;EAAA;EAAA;AAAA;;;;;cA4CK,iBAAA;;;;;;;;;KAOe,iBAAA,KAAiB,SAAA;;;KACZ,iBAAA,KAAiB,SAAA;AAAA;AAAA,KAG7C,yBAAA;EACH,UAAA,EAAY,qBAAA,CAAsB,KAAK;AAAA;AAAA,cAG5B,oBAAA,EAAsB,EAAE,CAAC,yBAAA;AAAA,kBAkGrB,2BAAA;EAAA,KACH,KAAA;IACV,KAAA;IACA,UAAA,EAAY,qBAAA,CAAsB,KAAK;EAAA;AAAA;AAH3C;;;AAAA,cAUa,2BAAA,EAA6B,EAAE,CAAC,2BAAA,CAA4B,KAAA;;;;;;AAP9B;AAO3C;;;;;;KA+LY,iBAAA,IACP,OAAA,CAAQ,SAAA;EAAa,IAAA;AAAA;EADd,2EAGG,MAAA,EAAQ,SAAA;EAEjB,SAAA,EAAW,wBAAA,eAJZ;EAMC,MAAA,EAAQ,wBAAA,YAFG;EAIX,iBAAA,EAAmB,wBAAA;AAAA,MAEpB,OAAA,CAAQ,SAAA;EAAa,IAAA;AAAA;EAEK,oFAAhB,cAAA,EAAgB,SAAA;AAAA,KAE3B,OAAA,CAAQ,SAAA;EAAa,IAAA;AAAA;EAAwB,IAAA;AAAA;;;;;;;cAoGpC,qBAAA,EAAuB,EAAE,CAAC,qBAAA,CAAsB,KAAA"}
@@ -92,11 +92,7 @@ const useMessagePartsGroups = (useChainOfThought) => {
92
92
  }, [messageTypes, useChainOfThought]);
93
93
  };
94
94
  const ToolUIDisplay = ({ Fallback, ...props }) => {
95
- const Render = useAuiState((s) => {
96
- const Render = s.tools.tools[props.toolName] ?? Fallback;
97
- if (Array.isArray(Render)) return Render[0] ?? Fallback;
98
- return Render;
99
- });
95
+ const Render = useAuiState((s) => s.tools.toolUIs[props.toolName]?.[0]?.render ?? Fallback);
100
96
  if (!Render) return null;
101
97
  return /* @__PURE__ */ jsx(Render, { ...props });
102
98
  };
@@ -230,8 +226,7 @@ const QuoteRendererImpl = ({ Quote }) => {
230
226
  };
231
227
  const QuoteRenderer = memo(QuoteRendererImpl);
232
228
  function resolveToolRender(toolsState, part) {
233
- const entry = toolsState.tools[part.toolName];
234
- const named = Array.isArray(entry) ? entry[0] ?? null : entry ?? null;
229
+ const named = toolsState.toolUIs[part.toolName]?.[0]?.render ?? null;
235
230
  if (named) return named;
236
231
  if (isMcpAppUri(part.mcp?.app?.resourceUri) && toolsState.mcpApp) return toolsState.mcpApp.render;
237
232
  return null;