@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.
- package/dist/adapters/attachment.d.ts.map +1 -1
- package/dist/adapters/speech.d.ts.map +1 -1
- package/dist/adapters/speech.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/duplicate-detection.d.ts.map +1 -1
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +2 -2
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/frame/provider.d.ts.map +1 -1
- package/dist/model-context/frame/provider.js.map +1 -1
- package/dist/model-context/registry.d.ts.map +1 -1
- package/dist/model-context/tool.d.ts.map +1 -1
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +26 -15
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/index.d.ts +6 -3
- package/dist/react/index.js +4 -1
- package/dist/react/model-context/define-toolkit.d.ts +20 -0
- package/dist/react/model-context/define-toolkit.d.ts.map +1 -0
- package/dist/react/model-context/define-toolkit.js +21 -0
- package/dist/react/model-context/define-toolkit.js.map +1 -0
- package/dist/react/model-context/hitl.d.ts +19 -0
- package/dist/react/model-context/hitl.d.ts.map +1 -0
- package/dist/react/model-context/hitl.js +22 -0
- package/dist/react/model-context/hitl.js.map +1 -0
- package/dist/react/model-context/toolbox.d.ts +29 -2
- package/dist/react/model-context/toolbox.d.ts.map +1 -1
- package/dist/react/model-context/toolbox.js +18 -0
- package/dist/react/model-context/toolbox.js.map +1 -0
- package/dist/react/model-context/useAssistantTool.d.ts.map +1 -1
- package/dist/react/model-context/useAssistantTool.js +6 -3
- package/dist/react/model-context/useAssistantTool.js.map +1 -1
- package/dist/react/model-context/useAssistantToolUI.d.ts +6 -0
- package/dist/react/model-context/useAssistantToolUI.d.ts.map +1 -1
- package/dist/react/model-context/useAssistantToolUI.js +4 -2
- package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
- package/dist/react/model-context/useInlineRender.js.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.d.ts +49 -7
- package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.js +28 -3
- package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
- package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageParts.js +2 -7
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
- package/dist/react/runtimes/RuntimeAdapterProvider.js +6 -5
- package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
- package/dist/react/runtimes/external-message-converter.js +1 -0
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreSharedOptions.d.ts +7 -0
- package/dist/react/runtimes/useExternalStoreSharedOptions.d.ts.map +1 -0
- package/dist/react/runtimes/useExternalStoreSharedOptions.js +21 -0
- package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -0
- package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useLocalRuntime.js.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
- package/dist/react/types/scopes/tools.d.ts +19 -2
- package/dist/react/types/scopes/tools.d.ts.map +1 -1
- package/dist/react/utils/groupParts.d.ts +32 -11
- package/dist/react/utils/groupParts.d.ts.map +1 -1
- package/dist/react/utils/groupParts.js +13 -6
- package/dist/react/utils/groupParts.js.map +1 -1
- package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
- package/dist/runtime/api/attachment-runtime.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/base/base-assistant-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.d.ts +9 -1
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +34 -14
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/thread-message-like.d.ts +1 -0
- package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
- package/dist/runtime/utils/thread-message-like.js +2 -1
- package/dist/runtime/utils/thread-message-like.js.map +1 -1
- package/dist/runtimes/external-store/external-store-shared-options.d.ts +8 -0
- package/dist/runtimes/external-store/external-store-shared-options.d.ts.map +1 -0
- package/dist/runtimes/external-store/external-store-shared-options.js +11 -0
- package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -0
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +0 -2
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +12 -23
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/external-store/thread-message-converter.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
- package/dist/types/message.d.ts +6 -0
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js.map +1 -1
- package/dist/utils/composite-context-provider.d.ts.map +1 -1
- package/dist/utils/id.d.ts +1 -3
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +1 -4
- package/dist/utils/id.js.map +1 -1
- package/package.json +10 -10
- package/src/adapters/speech.ts +0 -1
- package/src/index.ts +2 -0
- package/src/internal.ts +0 -2
- package/src/model-context/frame/host.ts +0 -1
- package/src/model-context/frame/provider.ts +0 -1
- package/src/react/client/Interactables.ts +0 -1
- package/src/react/client/Tools.ts +50 -25
- package/src/react/index.ts +10 -2
- package/src/react/model-context/define-toolkit.test.ts +13 -0
- package/src/react/model-context/define-toolkit.ts +23 -0
- package/src/react/model-context/hitl.ts +22 -0
- package/src/react/model-context/toolbox.ts +46 -1
- package/src/react/model-context/useAssistantTool.ts +8 -3
- package/src/react/model-context/useAssistantToolUI.ts +9 -2
- package/src/react/model-context/useInlineRender.ts +0 -1
- package/src/react/primitives/message/MessageGroupedParts.tsx +101 -12
- package/src/react/primitives/message/MessageParts.tsx +4 -7
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +0 -3
- package/src/react/runtimes/RuntimeAdapterProvider.tsx +12 -7
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +0 -3
- package/src/react/runtimes/external-message-converter.ts +4 -0
- package/src/react/runtimes/useExternalStoreSharedOptions.ts +23 -0
- package/src/react/runtimes/useLocalRuntime.ts +0 -10
- package/src/react/runtimes/useRemoteThreadListRuntime.ts +0 -6
- package/src/react/types/scopes/tools.ts +20 -1
- package/src/react/utils/groupParts.ts +49 -18
- package/src/runtime/utils/message-repository.ts +57 -16
- package/src/runtime/utils/thread-message-like.ts +2 -0
- package/src/runtimes/external-store/external-store-shared-options.ts +18 -0
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +18 -33
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +0 -1
- package/src/tests/MessageRepository.test.ts +83 -52
- package/src/tests/OptimisticState-list-race.test.ts +0 -4
- package/src/tests/external-store-thread-runtime-core.test.ts +105 -73
- package/src/tests/groupParts.test.ts +70 -0
- package/src/tests/remote-thread-list-isLoading.test.ts +0 -5
- package/src/types/message.ts +6 -0
- package/src/utils/id.ts +0 -4
package/dist/react/index.js
CHANGED
|
@@ -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":"
|
|
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":";;;;;;;
|
|
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":"
|
|
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
|
|
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":";;;;;;;;;;;;
|
|
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
|
|
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`)
|
|
23
|
-
* `
|
|
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
|
|
64
|
-
*
|
|
65
|
-
*
|
|
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":"
|
|
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
|
-
|
|
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;
|
|
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
|
|
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;
|