@assistant-ui/react 0.14.24 → 0.14.27
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/README.md +1 -1
- package/dist/augmentations.d.ts.map +1 -1
- package/dist/client/ExternalThread.d.ts +6 -4
- package/dist/client/ExternalThread.d.ts.map +1 -1
- package/dist/client/ExternalThread.js +2 -1
- package/dist/client/ExternalThread.js.map +1 -1
- package/dist/client/InMemoryThreadList.d.ts +0 -1
- package/dist/client/InMemoryThreadList.d.ts.map +1 -1
- package/dist/client/InMemoryThreadList.js +4 -1
- package/dist/client/InMemoryThreadList.js.map +1 -1
- package/dist/client/SingleThreadList.d.ts +0 -1
- package/dist/client/SingleThreadList.d.ts.map +1 -1
- package/dist/context/ReadonlyStore.d.ts +0 -1
- package/dist/context/ReadonlyStore.d.ts.map +1 -1
- package/dist/context/providers/MessageProvider.d.ts +0 -1
- package/dist/context/providers/MessageProvider.d.ts.map +1 -1
- package/dist/context/providers/ThreadViewportProvider.d.ts +0 -1
- package/dist/context/providers/ThreadViewportProvider.d.ts.map +1 -1
- package/dist/context/react/ThreadViewportContext.d.ts +15 -16
- package/dist/context/react/ThreadViewportContext.d.ts.map +1 -1
- package/dist/context/react/utils/createContextHook.d.ts +0 -1
- package/dist/context/react/utils/createContextHook.d.ts.map +1 -1
- package/dist/context/react/utils/createContextStoreHook.d.ts +2 -3
- package/dist/context/react/utils/createContextStoreHook.d.ts.map +1 -1
- package/dist/context/react/utils/createStateHookForRuntime.d.ts +0 -1
- package/dist/context/react/utils/createStateHookForRuntime.d.ts.map +1 -1
- package/dist/context/react/utils/ensureBinding.d.ts.map +1 -1
- package/dist/context/react/utils/useRuntimeState.d.ts +0 -1
- package/dist/context/react/utils/useRuntimeState.d.ts.map +1 -1
- package/dist/context/stores/ThreadViewport.d.ts +25 -15
- package/dist/context/stores/ThreadViewport.d.ts.map +1 -1
- package/dist/devtools/DevToolsHooks.d.ts +0 -1
- package/dist/devtools/DevToolsHooks.d.ts.map +1 -1
- package/dist/hooks/useMessageQuote.d.ts +0 -1
- package/dist/hooks/useMessageQuote.d.ts.map +1 -1
- package/dist/hooks/useMessageTiming.d.ts +0 -1
- package/dist/hooks/useMessageTiming.d.ts.map +1 -1
- package/dist/hooks/useToolCallElapsed.d.ts.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/internal.d.ts +0 -2
- package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts +0 -1
- package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts.map +1 -1
- package/dist/legacy-runtime/cloud/auiV0.d.ts +11 -2
- package/dist/legacy-runtime/cloud/auiV0.d.ts.map +1 -1
- package/dist/legacy-runtime/cloud/auiV0.js +31 -2
- package/dist/legacy-runtime/cloud/auiV0.js.map +1 -1
- package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.d.ts +1 -5
- package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.d.ts.map +1 -1
- package/dist/legacy-runtime/hooks/AssistantContext.d.ts +0 -1
- package/dist/legacy-runtime/hooks/AssistantContext.d.ts.map +1 -1
- package/dist/legacy-runtime/hooks/AttachmentContext.d.ts +0 -1
- package/dist/legacy-runtime/hooks/AttachmentContext.d.ts.map +1 -1
- package/dist/legacy-runtime/hooks/ComposerContext.d.ts +0 -1
- package/dist/legacy-runtime/hooks/ComposerContext.d.ts.map +1 -1
- package/dist/legacy-runtime/hooks/MessageContext.d.ts +0 -1
- package/dist/legacy-runtime/hooks/MessageContext.d.ts.map +1 -1
- package/dist/legacy-runtime/hooks/MessagePartContext.d.ts +0 -1
- package/dist/legacy-runtime/hooks/MessagePartContext.d.ts.map +1 -1
- package/dist/legacy-runtime/hooks/ThreadContext.d.ts +0 -1
- package/dist/legacy-runtime/hooks/ThreadContext.d.ts.map +1 -1
- package/dist/legacy-runtime/hooks/ThreadListItemContext.d.ts +0 -1
- package/dist/legacy-runtime/hooks/ThreadListItemContext.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.d.ts +0 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.d.ts +1 -4
- package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts +0 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts +0 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.d.ts +0 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.d.ts.map +1 -1
- package/dist/mcp-apps/McpAppRenderer.d.ts +12 -7
- package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/mcp-apps/McpAppRenderer.js +29 -7
- package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/mcp-apps/McpAppsRemoteHost.d.ts +0 -1
- package/dist/mcp-apps/McpAppsRemoteHost.d.ts.map +1 -1
- package/dist/mcp-apps/McpAppsRemoteHost.js +32 -1
- package/dist/mcp-apps/McpAppsRemoteHost.js.map +1 -1
- package/dist/mcp-apps/app-frame.d.ts +1 -12
- package/dist/mcp-apps/app-frame.d.ts.map +1 -1
- package/dist/mcp-apps/app-frame.js +1 -1
- package/dist/mcp-apps/app-frame.js.map +1 -1
- package/dist/mcp-apps/bridge.d.ts +0 -1
- package/dist/mcp-apps/bridge.d.ts.map +1 -1
- package/dist/mcp-apps/bridge.js +4 -3
- package/dist/mcp-apps/bridge.js.map +1 -1
- package/dist/mcp-apps/types.d.ts +10 -7
- package/dist/mcp-apps/types.d.ts.map +1 -1
- package/dist/mcp-apps/types.js.map +1 -1
- package/dist/mcp-apps/utils.d.ts +0 -1
- package/dist/mcp-apps/utils.d.ts.map +1 -1
- package/dist/model-context/frame/useAssistantFrameHost.d.ts +1 -6
- package/dist/model-context/frame/useAssistantFrameHost.d.ts.map +1 -1
- package/dist/model-context/makeAssistantVisible.d.ts +0 -1
- package/dist/model-context/makeAssistantVisible.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarCopy.d.ts +1 -4
- package/dist/primitives/actionBar/ActionBarCopy.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarEdit.d.ts +0 -1
- package/dist/primitives/actionBar/ActionBarEdit.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarExportMarkdown.d.ts +1 -5
- package/dist/primitives/actionBar/ActionBarExportMarkdown.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts +0 -1
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts +0 -1
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarInteractionContext.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarReload.d.ts +0 -1
- package/dist/primitives/actionBar/ActionBarReload.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarRoot.d.ts +0 -1
- package/dist/primitives/actionBar/ActionBarRoot.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarSpeak.d.ts +0 -1
- package/dist/primitives/actionBar/ActionBarSpeak.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts +0 -1
- package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts.map +1 -1
- package/dist/primitives/actionBar/useActionBarFloatStatus.d.ts +1 -6
- package/dist/primitives/actionBar/useActionBarFloatStatus.d.ts.map +1 -1
- package/dist/primitives/actionBar.d.ts +0 -2
- package/dist/primitives/actionBarMore/ActionBarMoreContent.d.ts +0 -1
- package/dist/primitives/actionBarMore/ActionBarMoreContent.d.ts.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreItem.d.ts +0 -1
- package/dist/primitives/actionBarMore/ActionBarMoreItem.d.ts.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreRoot.d.ts +0 -1
- package/dist/primitives/actionBarMore/ActionBarMoreRoot.d.ts.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreSeparator.d.ts +0 -1
- package/dist/primitives/actionBarMore/ActionBarMoreSeparator.d.ts.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreTrigger.d.ts +0 -1
- package/dist/primitives/actionBarMore/ActionBarMoreTrigger.d.ts.map +1 -1
- package/dist/primitives/actionBarMore/scope.d.ts +0 -1
- package/dist/primitives/actionBarMore/scope.d.ts.map +1 -1
- package/dist/primitives/actionBarMore.d.ts +0 -2
- package/dist/primitives/assistantModal/AssistantModalAnchor.d.ts +6 -4
- package/dist/primitives/assistantModal/AssistantModalAnchor.d.ts.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalAnchor.js +2 -2
- package/dist/primitives/assistantModal/AssistantModalAnchor.js.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalContent.d.ts +4 -2
- package/dist/primitives/assistantModal/AssistantModalContent.d.ts.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalContent.js +2 -1
- package/dist/primitives/assistantModal/AssistantModalContent.js.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalRoot.d.ts +0 -1
- package/dist/primitives/assistantModal/AssistantModalRoot.d.ts.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalTrigger.d.ts +6 -4
- package/dist/primitives/assistantModal/AssistantModalTrigger.d.ts.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalTrigger.js +2 -2
- package/dist/primitives/assistantModal/AssistantModalTrigger.js.map +1 -1
- package/dist/primitives/assistantModal/popoverRenderPrimitives.d.ts +14 -0
- package/dist/primitives/assistantModal/popoverRenderPrimitives.d.ts.map +1 -0
- package/dist/primitives/assistantModal/popoverRenderPrimitives.js +10 -0
- package/dist/primitives/assistantModal/popoverRenderPrimitives.js.map +1 -0
- package/dist/primitives/assistantModal/scope.d.ts +0 -1
- package/dist/primitives/assistantModal/scope.d.ts.map +1 -1
- package/dist/primitives/assistantModal.d.ts +0 -2
- package/dist/primitives/attachment/AttachmentName.d.ts +0 -1
- package/dist/primitives/attachment/AttachmentName.d.ts.map +1 -1
- package/dist/primitives/attachment/AttachmentRemove.d.ts +0 -1
- package/dist/primitives/attachment/AttachmentRemove.d.ts.map +1 -1
- package/dist/primitives/attachment/AttachmentRoot.d.ts +0 -1
- package/dist/primitives/attachment/AttachmentRoot.d.ts.map +1 -1
- package/dist/primitives/attachment/AttachmentThumb.d.ts +0 -1
- package/dist/primitives/attachment/AttachmentThumb.d.ts.map +1 -1
- package/dist/primitives/attachment.d.ts +0 -2
- package/dist/primitives/branchPicker/BranchPickerCount.d.ts +0 -1
- package/dist/primitives/branchPicker/BranchPickerCount.d.ts.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerNext.d.ts +0 -1
- package/dist/primitives/branchPicker/BranchPickerNext.d.ts.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerNumber.d.ts +0 -1
- package/dist/primitives/branchPicker/BranchPickerNumber.d.ts.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts +0 -1
- package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerRoot.d.ts +0 -1
- package/dist/primitives/branchPicker/BranchPickerRoot.d.ts.map +1 -1
- package/dist/primitives/branchPicker.d.ts +0 -2
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts +0 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts.map +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts +0 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts.map +1 -1
- package/dist/primitives/chainOfThought.d.ts +0 -2
- package/dist/primitives/composer/ComposerAddAttachment.d.ts +5 -6
- package/dist/primitives/composer/ComposerAddAttachment.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerAttachmentDropzone.d.ts +0 -1
- package/dist/primitives/composer/ComposerAttachmentDropzone.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerCancel.d.ts +0 -1
- package/dist/primitives/composer/ComposerCancel.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerCompactContext.d.ts +9 -0
- package/dist/primitives/composer/ComposerCompactContext.d.ts.map +1 -0
- package/dist/primitives/composer/ComposerCompactContext.js +11 -0
- package/dist/primitives/composer/ComposerCompactContext.js.map +1 -0
- package/dist/primitives/composer/ComposerDictate.d.ts +0 -1
- package/dist/primitives/composer/ComposerDictate.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerDictationTranscript.d.ts +0 -1
- package/dist/primitives/composer/ComposerDictationTranscript.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerInput.d.ts +0 -1
- package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerInput.js +17 -2
- package/dist/primitives/composer/ComposerInput.js.map +1 -1
- package/dist/primitives/composer/ComposerInputPluginContext.d.ts +4 -3
- package/dist/primitives/composer/ComposerInputPluginContext.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerQuote.d.ts +0 -1
- package/dist/primitives/composer/ComposerQuote.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerRoot.d.ts +22 -3
- package/dist/primitives/composer/ComposerRoot.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerRoot.js +63 -30
- package/dist/primitives/composer/ComposerRoot.js.map +1 -1
- package/dist/primitives/composer/ComposerSend.d.ts +0 -1
- package/dist/primitives/composer/ComposerSend.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerStopDictation.d.ts +0 -1
- package/dist/primitives/composer/ComposerStopDictation.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopover.d.ts +10 -5
- package/dist/primitives/composer/trigger/TriggerPopover.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverAction.d.ts +5 -3
- package/dist/primitives/composer/trigger/TriggerPopoverAction.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js +3 -2
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverBack.d.ts +0 -1
- package/dist/primitives/composer/trigger/TriggerPopoverBack.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts +0 -1
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.d.ts +3 -2
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts +0 -1
- package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverResource.d.ts +10 -6
- package/dist/primitives/composer/trigger/TriggerPopoverResource.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.d.ts +8 -5
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/index.d.ts +0 -1
- package/dist/primitives/composer/trigger/index.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/triggerDetectionResource.d.ts +5 -2
- package/dist/primitives/composer/trigger/triggerDetectionResource.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts +7 -4
- package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts +13 -7
- package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts +7 -4
- package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts.map +1 -1
- package/dist/primitives/composer/useComposerInputState.d.ts.map +1 -1
- package/dist/primitives/composer.d.ts +0 -2
- package/dist/primitives/dropdownMenuRenderPrimitives.d.ts +0 -1
- package/dist/primitives/dropdownMenuRenderPrimitives.d.ts.map +1 -1
- package/dist/primitives/error/ErrorMessage.d.ts +0 -1
- package/dist/primitives/error/ErrorMessage.d.ts.map +1 -1
- package/dist/primitives/error/ErrorRoot.d.ts +0 -1
- package/dist/primitives/error/ErrorRoot.d.ts.map +1 -1
- package/dist/primitives/error.d.ts +0 -2
- package/dist/primitives/message/MessageError.d.ts +0 -1
- package/dist/primitives/message/MessageError.d.ts.map +1 -1
- package/dist/primitives/message/MessageIf.d.ts +0 -1
- package/dist/primitives/message/MessageIf.d.ts.map +1 -1
- package/dist/primitives/message/MessageParts.d.ts +0 -1
- package/dist/primitives/message/MessageParts.d.ts.map +1 -1
- package/dist/primitives/message/MessagePartsGrouped.d.ts +25 -12
- package/dist/primitives/message/MessagePartsGrouped.d.ts.map +1 -1
- package/dist/primitives/message/MessageRoot.d.ts +0 -1
- package/dist/primitives/message/MessageRoot.d.ts.map +1 -1
- package/dist/primitives/message.d.ts +0 -2
- package/dist/primitives/messagePart/MessagePartImage.d.ts +0 -1
- package/dist/primitives/messagePart/MessagePartImage.d.ts.map +1 -1
- package/dist/primitives/messagePart/MessagePartText.d.ts +2 -1
- package/dist/primitives/messagePart/MessagePartText.d.ts.map +1 -1
- package/dist/primitives/messagePart/MessagePartText.js.map +1 -1
- package/dist/primitives/messagePart/useMessagePartData.d.ts +0 -1
- package/dist/primitives/messagePart/useMessagePartData.d.ts.map +1 -1
- package/dist/primitives/messagePart/useMessagePartFile.d.ts +0 -1
- package/dist/primitives/messagePart/useMessagePartFile.d.ts.map +1 -1
- package/dist/primitives/messagePart/useMessagePartImage.d.ts +0 -1
- package/dist/primitives/messagePart/useMessagePartImage.d.ts.map +1 -1
- package/dist/primitives/messagePart/useMessagePartReasoning.d.ts +0 -1
- package/dist/primitives/messagePart/useMessagePartReasoning.d.ts.map +1 -1
- package/dist/primitives/messagePart/useMessagePartSource.d.ts.map +1 -1
- package/dist/primitives/messagePart/useMessagePartText.d.ts +0 -1
- package/dist/primitives/messagePart/useMessagePartText.d.ts.map +1 -1
- package/dist/primitives/messagePart.d.ts +0 -2
- package/dist/primitives/queueItem/QueueItemRemove.d.ts +0 -1
- package/dist/primitives/queueItem/QueueItemRemove.d.ts.map +1 -1
- package/dist/primitives/queueItem/QueueItemSteer.d.ts +0 -1
- package/dist/primitives/queueItem/QueueItemSteer.d.ts.map +1 -1
- package/dist/primitives/queueItem/QueueItemText.d.ts +0 -1
- package/dist/primitives/queueItem/QueueItemText.d.ts.map +1 -1
- package/dist/primitives/queueItem.d.ts +0 -2
- package/dist/primitives/reasoning/useScrollLock.d.ts +0 -1
- package/dist/primitives/reasoning/useScrollLock.d.ts.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarQuote.d.ts +0 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarQuote.d.ts.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts +0 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +2 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js.map +1 -1
- package/dist/primitives/selectionToolbar.d.ts +0 -2
- package/dist/primitives/suggestion/SuggestionDescription.d.ts +0 -1
- package/dist/primitives/suggestion/SuggestionDescription.d.ts.map +1 -1
- package/dist/primitives/suggestion/SuggestionTitle.d.ts +0 -1
- package/dist/primitives/suggestion/SuggestionTitle.d.ts.map +1 -1
- package/dist/primitives/suggestion/SuggestionTrigger.d.ts +1 -5
- package/dist/primitives/suggestion/SuggestionTrigger.d.ts.map +1 -1
- package/dist/primitives/suggestion.d.ts +0 -2
- package/dist/primitives/thread/ThreadEmpty.d.ts +0 -1
- package/dist/primitives/thread/ThreadEmpty.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadIf.d.ts +0 -1
- package/dist/primitives/thread/ThreadIf.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadRoot.d.ts +0 -1
- package/dist/primitives/thread/ThreadRoot.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadScrollToBottom.d.ts +1 -4
- package/dist/primitives/thread/ThreadScrollToBottom.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadSuggestion.d.ts +13 -14
- package/dist/primitives/thread/ThreadSuggestion.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadViewport.d.ts +0 -1
- package/dist/primitives/thread/ThreadViewport.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadViewportFooter.d.ts +0 -1
- package/dist/primitives/thread/ThreadViewportFooter.d.ts.map +1 -1
- package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.d.ts +2 -11
- package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.d.ts.map +1 -1
- package/dist/primitives/thread/topAnchor/createReserveObservers.d.ts.map +1 -1
- package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.d.ts.map +1 -1
- package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts +1 -4
- package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts.map +1 -1
- package/dist/primitives/thread/topAnchor/topAnchorUtils.d.ts.map +1 -1
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.d.ts.map +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts +1 -7
- package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
- package/dist/primitives/thread.d.ts +0 -2
- package/dist/primitives/threadList/ThreadListLoadMore.d.ts +0 -1
- package/dist/primitives/threadList/ThreadListLoadMore.d.ts.map +1 -1
- package/dist/primitives/threadList/ThreadListNew.d.ts +0 -1
- package/dist/primitives/threadList/ThreadListNew.d.ts.map +1 -1
- package/dist/primitives/threadList/ThreadListRoot.d.ts +0 -1
- package/dist/primitives/threadList/ThreadListRoot.d.ts.map +1 -1
- package/dist/primitives/threadList/ThreadListRoot.js +10 -3
- package/dist/primitives/threadList/ThreadListRoot.js.map +1 -1
- package/dist/primitives/threadList.d.ts +0 -2
- package/dist/primitives/threadListFocusGroup.d.ts +25 -0
- package/dist/primitives/threadListFocusGroup.d.ts.map +1 -0
- package/dist/primitives/threadListFocusGroup.js +15 -0
- package/dist/primitives/threadListFocusGroup.js.map +1 -0
- package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts +0 -1
- package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts +0 -1
- package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts +0 -1
- package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemRoot.js +45 -27
- package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts +0 -1
- package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemTrigger.js +26 -2
- package/dist/primitives/threadListItem/ThreadListItemTrigger.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts +0 -1
- package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts.map +1 -1
- package/dist/primitives/threadListItem.d.ts +0 -2
- package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.d.ts +0 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.d.ts.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js +63 -38
- package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.d.ts +0 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.d.ts.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.d.ts +20 -4
- package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.d.ts.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js +95 -14
- package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.d.ts +0 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.d.ts.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.d.ts +0 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.d.ts.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js +38 -21
- package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js.map +1 -1
- package/dist/primitives/threadListItemMore/scope.d.ts +0 -1
- package/dist/primitives/threadListItemMore/scope.d.ts.map +1 -1
- package/dist/primitives/threadListItemMore.d.ts +0 -2
- package/dist/sandbox-host/SandboxHost.d.ts +1 -10
- package/dist/sandbox-host/SandboxHost.d.ts.map +1 -1
- package/dist/tests/remote-thread-list-test-helpers.d.ts +0 -1
- package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
- package/dist/unstable/useComposerInput.d.ts +2 -2
- package/dist/unstable/useComposerInput.d.ts.map +1 -1
- package/dist/unstable/useComposerInputHistory.d.ts +2 -2
- package/dist/unstable/useComposerInputHistory.d.ts.map +1 -1
- package/dist/unstable/useLiveCompletionAdapter.d.ts +4 -3
- package/dist/unstable/useLiveCompletionAdapter.d.ts.map +1 -1
- package/dist/unstable/useMentionAdapter.d.ts +19 -10
- package/dist/unstable/useMentionAdapter.d.ts.map +1 -1
- package/dist/unstable/useMessageStallDetection.d.ts +3 -1
- package/dist/unstable/useMessageStallDetection.d.ts.map +1 -1
- package/dist/unstable/useSlashCommandAdapter.d.ts +6 -4
- package/dist/unstable/useSlashCommandAdapter.d.ts.map +1 -1
- package/dist/utils/Primitive.d.ts +0 -1
- package/dist/utils/Primitive.d.ts.map +1 -1
- package/dist/utils/RequireAtLeastOne.d.ts +1 -1
- package/dist/utils/RequireAtLeastOne.d.ts.map +1 -1
- package/dist/utils/createActionButton.d.ts +0 -1
- package/dist/utils/createActionButton.d.ts.map +1 -1
- package/dist/utils/getSelectionMessageId.d.ts.map +1 -1
- package/dist/utils/getSelectionMessageId.js +32 -7
- package/dist/utils/getSelectionMessageId.js.map +1 -1
- package/dist/utils/hooks/useManagedRef.d.ts.map +1 -1
- package/dist/utils/hooks/useMediaQuery.d.ts.map +1 -1
- package/dist/utils/hooks/useMediaQuery.js +2 -2
- package/dist/utils/hooks/useMediaQuery.js.map +1 -1
- package/dist/utils/hooks/useOnResizeContent.d.ts.map +1 -1
- package/dist/utils/hooks/useOnScrollToBottom.d.ts.map +1 -1
- package/dist/utils/hooks/useSizeHandle.d.ts +0 -1
- package/dist/utils/hooks/useSizeHandle.d.ts.map +1 -1
- package/dist/utils/smooth/SmoothContext.d.ts +71 -72
- package/dist/utils/smooth/SmoothContext.d.ts.map +1 -1
- package/dist/utils/smooth/useSmooth.d.ts +4 -1
- package/dist/utils/smooth/useSmooth.d.ts.map +1 -1
- package/dist/utils/smooth/useSmooth.js +7 -1
- package/dist/utils/smooth/useSmooth.js.map +1 -1
- package/dist/utils/useToolArgsFieldStatus.d.ts.map +1 -1
- package/package.json +19 -17
- package/src/index.ts +3 -0
- package/src/legacy-runtime/cloud/auiV0.ts +72 -3
- package/src/mcp-apps/McpAppRenderer.test.tsx +141 -0
- package/src/mcp-apps/McpAppRenderer.tsx +48 -10
- package/src/mcp-apps/McpAppsRemoteHost.test.ts +126 -0
- package/src/mcp-apps/McpAppsRemoteHost.ts +40 -1
- package/src/mcp-apps/app-frame.tsx +3 -1
- package/src/mcp-apps/bridge.ts +1 -1
- package/src/mcp-apps/types.ts +16 -8
- package/src/primitives/assistantModal/AssistantModalAnchor.tsx +6 -8
- package/src/primitives/assistantModal/AssistantModalContent.tsx +5 -5
- package/src/primitives/assistantModal/AssistantModalTrigger.test.tsx +80 -0
- package/src/primitives/assistantModal/AssistantModalTrigger.tsx +6 -8
- package/src/primitives/assistantModal/popoverRenderPrimitives.ts +6 -0
- package/src/primitives/composer/ComposerCompactContext.tsx +13 -0
- package/src/primitives/composer/ComposerInput.tsx +35 -0
- package/src/primitives/composer/ComposerRoot.test.tsx +161 -0
- package/src/primitives/composer/ComposerRoot.tsx +37 -7
- package/src/primitives/messagePart/MessagePartText.tsx +1 -0
- package/src/primitives/threadList/ThreadListRoot.tsx +8 -1
- package/src/primitives/threadListFocusGroup.ts +24 -0
- package/src/primitives/threadListItem/ThreadListItemRoot.tsx +53 -5
- package/src/primitives/threadListItem/ThreadListItemTrigger.tsx +45 -0
- package/src/primitives/threadListItem/ThreadListKeyboardNav.test.tsx +141 -0
- package/src/primitives/threadListItemMore/ThreadListItemMoreContent.tsx +22 -1
- package/src/primitives/threadListItemMore/ThreadListItemMoreRoot.tsx +64 -3
- package/src/primitives/threadListItemMore/ThreadListItemMoreTrigger.tsx +29 -2
- package/src/tests/LocalThreadRuntimeCore.test.ts +4 -1
- package/src/tests/auiV0Encode.test.ts +134 -1
- package/src/tests/generative-ui.test.tsx +21 -1
- package/src/utils/getSelectionMessageId.test.ts +175 -0
- package/src/utils/getSelectionMessageId.ts +57 -6
- package/src/utils/hooks/useMediaQuery.ts +3 -2
- package/src/utils/smooth/useSmooth.test.tsx +26 -0
- package/src/utils/smooth/useSmooth.ts +7 -1
- package/dist/utils/json/is-json-equal.d.ts +0 -5
- package/dist/utils/json/is-json-equal.d.ts.map +0 -1
- package/dist/utils/json/is-json-equal.js +0 -26
- package/dist/utils/json/is-json-equal.js.map +0 -1
- package/dist/utils/json/is-json.d.ts +0 -10
- package/dist/utils/json/is-json.d.ts.map +0 -1
- package/dist/utils/json/is-json.js +0 -22
- package/dist/utils/json/is-json.js.map +0 -1
- package/src/primitives/threadListItem/ThreadListItemTrigger.ts +0 -23
- package/src/utils/json/is-json-equal.ts +0 -48
- package/src/utils/json/is-json.ts +0 -58
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { MessagePartState, ReasoningMessagePart, TextMessagePart } from "@assistant-ui/core";
|
|
2
|
-
|
|
3
2
|
//#region src/utils/smooth/useSmooth.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Tuning options for the smooth text streaming animation.
|
|
@@ -39,6 +38,10 @@ type SmoothOptions = {
|
|
|
39
38
|
* the reveal. Returns the part state with `text` replaced by the revealed
|
|
40
39
|
* prefix and `status` reporting `running` until the reveal catches up.
|
|
41
40
|
*
|
|
41
|
+
* The reveal auto-disables under `prefers-reduced-motion: reduce`,
|
|
42
|
+
* committing the full text immediately; this takes precedence over an
|
|
43
|
+
* explicit `smooth={true}`.
|
|
44
|
+
*
|
|
42
45
|
* @example
|
|
43
46
|
* ```tsx
|
|
44
47
|
* const { text, status } = useSmooth(useMessagePartText(), {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSmooth.d.ts","names":[],"sources":["../../../src/utils/smooth/useSmooth.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"useSmooth.d.ts","names":[],"sources":["../../../src/utils/smooth/useSmooth.ts"],"mappings":";;;;;KAkBY;;;;;;EAMV;;;;;;EAMA;;;;;EAKA;;;;;;;;EAQA;;;;;;;;;;;;;;;;;;;;;;cA0GW,YACX,OAAO,oBAAoB,kBAAkB,uBAC7C,mBAAkB,kBACjB,oBAAoB,kBAAkB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { writableStore } from "../../context/ReadonlyStore.js";
|
|
3
|
+
import { useMediaQuery } from "../hooks/useMediaQuery.js";
|
|
3
4
|
import { useSmoothStatusStore } from "./SmoothContext.js";
|
|
4
5
|
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
5
6
|
import { useEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
|
|
@@ -66,6 +67,10 @@ const positiveOr = (value, fallback) => value !== void 0 && value > 0 ? value :
|
|
|
66
67
|
* the reveal. Returns the part state with `text` replaced by the revealed
|
|
67
68
|
* prefix and `status` reporting `running` until the reveal catches up.
|
|
68
69
|
*
|
|
70
|
+
* The reveal auto-disables under `prefers-reduced-motion: reduce`,
|
|
71
|
+
* committing the full text immediately; this takes precedence over an
|
|
72
|
+
* explicit `smooth={true}`.
|
|
73
|
+
*
|
|
69
74
|
* @example
|
|
70
75
|
* ```tsx
|
|
71
76
|
* const { text, status } = useSmooth(useMessagePartText(), {
|
|
@@ -76,8 +81,9 @@ const positiveOr = (value, fallback) => value !== void 0 && value > 0 ? value :
|
|
|
76
81
|
*/
|
|
77
82
|
const useSmooth = (state, smooth = false) => {
|
|
78
83
|
const { text } = state;
|
|
84
|
+
const reduceMotion = useMediaQuery("(prefers-reduced-motion: reduce)");
|
|
79
85
|
const options = typeof smooth === "object" && smooth !== null ? smooth : void 0;
|
|
80
|
-
const enabled = smooth !== false && smooth !== null;
|
|
86
|
+
const enabled = smooth !== false && smooth !== null && !reduceMotion;
|
|
81
87
|
const drainMs = positiveOr(options?.drainMs, DEFAULT_DRAIN_MS);
|
|
82
88
|
const maxCharIntervalMs = positiveOr(options?.maxCharIntervalMs, DEFAULT_MAX_CHAR_INTERVAL_MS);
|
|
83
89
|
const maxCharsPerFrame = positiveOr(options?.maxCharsPerFrame, Infinity);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSmooth.js","names":["useEffect","useMemo","useRef","useState","useAui","useAuiState","MessagePartStatus","ReasoningMessagePart","TextMessagePart","MessagePartState","useCallbackRef","useSmoothStatusStore","writableStore","SmoothOptions","drainMs","maxCharIntervalMs","maxCharsPerFrame","minCommitMs","DEFAULT_DRAIN_MS","DEFAULT_MAX_CHAR_INTERVAL_MS","TextStreamAnimator","animationFrameId","lastUpdateTime","Date","now","lastCommitTime","targetText","Infinity","constructor","currentText","setText","newText","start","animate","stop","cancelAnimationFrame","currentTime","deltaTime","timeToConsume","remainingChars","length","baseTimePerChar","Math","min","frameLimit","charsToAdd","requestAnimationFrame","slice","isComplete","SMOOTH_STATUS","Object","freeze","type","positiveOr","value","fallback","undefined","useSmooth","state","smooth","text","options","enabled","displayedText","setDisplayedText","status","aui","part","prevPart","setPrevPart","startsWith","smoothStatusStore","optional","target","setState","animatorRef","animatorPartRef","partChanged","current"],"sources":["../../../src/utils/smooth/useSmooth.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport type {\n MessagePartStatus,\n ReasoningMessagePart,\n TextMessagePart,\n MessagePartState,\n} from \"@assistant-ui/core\";\nimport { useCallbackRef } from \"@radix-ui/react-use-callback-ref\";\nimport { useSmoothStatusStore } from \"./SmoothContext\";\nimport { writableStore } from \"../../context/ReadonlyStore\";\n\n/**\n * Tuning options for the smooth text streaming animation.\n */\nexport type SmoothOptions = {\n /**\n * Target time in milliseconds to drain the backlog of unrevealed\n * characters. Larger values reveal long backlogs more gradually.\n * @default 250\n */\n drainMs?: number | undefined;\n /**\n * Maximum time in milliseconds between revealed characters, i.e. the\n * slowest reveal rate when the backlog is short.\n * @default 5\n */\n maxCharIntervalMs?: number | undefined;\n /**\n * Maximum number of characters revealed per animation frame.\n * @default Infinity\n */\n maxCharsPerFrame?: number | undefined;\n /**\n * Minimum time in milliseconds between committed updates. The reveal keeps\n * advancing every frame, but the visible text (and the downstream re-render\n * and markdown re-parse it triggers) is committed at most once per interval.\n * The final frame always commits. `0` commits every frame.\n * @default 0\n */\n minCommitMs?: number | undefined;\n};\n\nconst DEFAULT_DRAIN_MS = 250;\nconst DEFAULT_MAX_CHAR_INTERVAL_MS = 5;\n\nclass TextStreamAnimator {\n private animationFrameId: number | null = null;\n private lastUpdateTime: number = Date.now();\n public lastCommitTime: number = 0;\n\n public targetText: string = \"\";\n public drainMs: number = DEFAULT_DRAIN_MS;\n public maxCharIntervalMs: number = DEFAULT_MAX_CHAR_INTERVAL_MS;\n public maxCharsPerFrame: number = Infinity;\n public minCommitMs: number = 0;\n\n constructor(\n public currentText: string,\n private setText: (newText: string) => void,\n ) {}\n\n start() {\n if (this.animationFrameId !== null) return;\n this.lastUpdateTime = Date.now();\n this.animate();\n }\n\n stop() {\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n }\n\n private animate = () => {\n const currentTime = Date.now();\n const deltaTime = currentTime - this.lastUpdateTime;\n let timeToConsume = deltaTime;\n\n const remainingChars = this.targetText.length - this.currentText.length;\n const baseTimePerChar = Math.min(\n this.maxCharIntervalMs,\n this.drainMs / remainingChars,\n );\n\n const frameLimit = Math.min(remainingChars, this.maxCharsPerFrame);\n let charsToAdd = 0;\n while (timeToConsume >= baseTimePerChar && charsToAdd < frameLimit) {\n charsToAdd++;\n timeToConsume -= baseTimePerChar;\n }\n // A cap-limited frame must not bank its surplus time, or the next\n // frame would burst past the cap.\n if (charsToAdd === frameLimit && frameLimit === this.maxCharsPerFrame) {\n timeToConsume = 0;\n }\n\n if (charsToAdd !== remainingChars) {\n this.animationFrameId = requestAnimationFrame(this.animate);\n } else {\n this.animationFrameId = null;\n }\n if (charsToAdd === 0) return;\n\n this.currentText = this.targetText.slice(\n 0,\n this.currentText.length + charsToAdd,\n );\n this.lastUpdateTime = currentTime - timeToConsume;\n\n const isComplete = charsToAdd === remainingChars;\n if (isComplete || currentTime - this.lastCommitTime >= this.minCommitMs) {\n this.lastCommitTime = currentTime;\n this.setText(this.currentText);\n }\n };\n}\n\nconst SMOOTH_STATUS: MessagePartStatus = Object.freeze({\n type: \"running\",\n});\n\nconst positiveOr = (value: number | undefined, fallback: number): number =>\n value !== undefined && value > 0 ? value : fallback;\n\n/**\n * Animates streamed message part text with a typewriter-style reveal.\n *\n * Takes the current part state and a `smooth` argument: `false` disables,\n * `true` uses the default rate, and a {@link SmoothOptions} object tunes\n * the reveal. Returns the part state with `text` replaced by the revealed\n * prefix and `status` reporting `running` until the reveal catches up.\n *\n * @example\n * ```tsx\n * const { text, status } = useSmooth(useMessagePartText(), {\n * drainMs: 500,\n * maxCharsPerFrame: 30,\n * });\n * ```\n */\nexport const useSmooth = (\n state: MessagePartState & (TextMessagePart | ReasoningMessagePart),\n smooth: boolean | SmoothOptions = false,\n): MessagePartState & (TextMessagePart | ReasoningMessagePart) => {\n const { text } = state;\n const options =\n typeof smooth === \"object\" && smooth !== null ? smooth : undefined;\n const enabled = smooth !== false && smooth !== null;\n const drainMs = positiveOr(options?.drainMs, DEFAULT_DRAIN_MS);\n const maxCharIntervalMs = positiveOr(\n options?.maxCharIntervalMs,\n DEFAULT_MAX_CHAR_INTERVAL_MS,\n );\n const maxCharsPerFrame = positiveOr(options?.maxCharsPerFrame, Infinity);\n const minCommitMs = positiveOr(options?.minCommitMs, 0);\n\n const [displayedText, setDisplayedText] = useState(\n state.status.type === \"running\" ? \"\" : text,\n );\n\n // Render-phase resync on part flip or text discontinuity, so the\n // first paint after a thread switch never shows the previous\n // part's text (#4051). `displayedText` is already a prefix of\n // `text` during normal streaming, so use it as the previous-text\n // reference instead of carrying separate state — avoids the\n // double render per streaming token. Read part identity through\n // `useAuiState` so we actually subscribe to its changes instead\n // of relying on a render-time proxy reference that may be stable\n // across thread swaps.\n const aui = useAui();\n const part = useAuiState(() => aui.part());\n const [prevPart, setPrevPart] = useState(part);\n if (part !== prevPart || !text.startsWith(displayedText)) {\n setPrevPart(part);\n setDisplayedText(state.status.type === \"running\" ? \"\" : text);\n }\n\n const smoothStatusStore = useSmoothStatusStore({ optional: true });\n const setText = useCallbackRef((text: string) => {\n setDisplayedText(text);\n if (smoothStatusStore) {\n const target =\n displayedText !== text || state.status.type === \"running\"\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n });\n\n // TODO this is hacky\n useEffect(() => {\n if (smoothStatusStore) {\n const target =\n enabled && (displayedText !== text || state.status.type === \"running\")\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n }, [smoothStatusStore, enabled, text, displayedText, state.status]);\n\n const [animatorRef] = useState<TextStreamAnimator>(\n new TextStreamAnimator(displayedText, setText),\n );\n\n useEffect(() => {\n animatorRef.drainMs = drainMs;\n animatorRef.maxCharIntervalMs = maxCharIntervalMs;\n animatorRef.maxCharsPerFrame = maxCharsPerFrame;\n animatorRef.minCommitMs = minCommitMs;\n }, [animatorRef, drainMs, maxCharIntervalMs, maxCharsPerFrame, minCommitMs]);\n\n const animatorPartRef = useRef(part);\n useEffect(() => {\n if (!enabled) {\n animatorRef.stop();\n return;\n }\n\n // Discontinuity: part flipped, or new text breaks continuation\n // of the animator's current target. Either case requires\n // resetting the cursor — without the part check, a new part\n // whose text happens to share a prefix with the previous target\n // would keep the stale cursor and flicker.\n const partChanged = animatorPartRef.current !== part;\n animatorPartRef.current = part;\n if (partChanged || !text.startsWith(animatorRef.targetText)) {\n if (state.status.type === \"running\") {\n animatorRef.currentText = \"\";\n animatorRef.targetText = text;\n animatorRef.lastCommitTime = 0;\n animatorRef.start();\n } else {\n animatorRef.currentText = text;\n animatorRef.targetText = text;\n animatorRef.stop();\n }\n return;\n }\n\n animatorRef.targetText = text;\n animatorRef.start();\n }, [animatorRef, enabled, text, state.status.type, part]);\n\n useEffect(() => {\n return () => {\n animatorRef.stop();\n };\n }, [animatorRef]);\n\n return useMemo(\n () =>\n enabled\n ? {\n ...state,\n text: displayedText,\n status: text === displayedText ? state.status : SMOOTH_STATUS,\n }\n : state,\n [enabled, displayedText, state, text],\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useSmooth.js","names":["useEffect","useMemo","useRef","useState","useAui","useAuiState","MessagePartStatus","ReasoningMessagePart","TextMessagePart","MessagePartState","useCallbackRef","useMediaQuery","useSmoothStatusStore","writableStore","SmoothOptions","drainMs","maxCharIntervalMs","maxCharsPerFrame","minCommitMs","DEFAULT_DRAIN_MS","DEFAULT_MAX_CHAR_INTERVAL_MS","TextStreamAnimator","animationFrameId","lastUpdateTime","Date","now","lastCommitTime","targetText","Infinity","constructor","currentText","setText","newText","start","animate","stop","cancelAnimationFrame","currentTime","deltaTime","timeToConsume","remainingChars","length","baseTimePerChar","Math","min","frameLimit","charsToAdd","requestAnimationFrame","slice","isComplete","SMOOTH_STATUS","Object","freeze","type","positiveOr","value","fallback","undefined","useSmooth","state","smooth","text","reduceMotion","options","enabled","displayedText","setDisplayedText","status","aui","part","prevPart","setPrevPart","startsWith","smoothStatusStore","optional","target","setState","animatorRef","animatorPartRef","partChanged","current"],"sources":["../../../src/utils/smooth/useSmooth.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport type {\n MessagePartStatus,\n ReasoningMessagePart,\n TextMessagePart,\n MessagePartState,\n} from \"@assistant-ui/core\";\nimport { useCallbackRef } from \"@radix-ui/react-use-callback-ref\";\nimport { useMediaQuery } from \"../hooks/useMediaQuery\";\nimport { useSmoothStatusStore } from \"./SmoothContext\";\nimport { writableStore } from \"../../context/ReadonlyStore\";\n\n/**\n * Tuning options for the smooth text streaming animation.\n */\nexport type SmoothOptions = {\n /**\n * Target time in milliseconds to drain the backlog of unrevealed\n * characters. Larger values reveal long backlogs more gradually.\n * @default 250\n */\n drainMs?: number | undefined;\n /**\n * Maximum time in milliseconds between revealed characters, i.e. the\n * slowest reveal rate when the backlog is short.\n * @default 5\n */\n maxCharIntervalMs?: number | undefined;\n /**\n * Maximum number of characters revealed per animation frame.\n * @default Infinity\n */\n maxCharsPerFrame?: number | undefined;\n /**\n * Minimum time in milliseconds between committed updates. The reveal keeps\n * advancing every frame, but the visible text (and the downstream re-render\n * and markdown re-parse it triggers) is committed at most once per interval.\n * The final frame always commits. `0` commits every frame.\n * @default 0\n */\n minCommitMs?: number | undefined;\n};\n\nconst DEFAULT_DRAIN_MS = 250;\nconst DEFAULT_MAX_CHAR_INTERVAL_MS = 5;\n\nclass TextStreamAnimator {\n private animationFrameId: number | null = null;\n private lastUpdateTime: number = Date.now();\n public lastCommitTime: number = 0;\n\n public targetText: string = \"\";\n public drainMs: number = DEFAULT_DRAIN_MS;\n public maxCharIntervalMs: number = DEFAULT_MAX_CHAR_INTERVAL_MS;\n public maxCharsPerFrame: number = Infinity;\n public minCommitMs: number = 0;\n\n constructor(\n public currentText: string,\n private setText: (newText: string) => void,\n ) {}\n\n start() {\n if (this.animationFrameId !== null) return;\n this.lastUpdateTime = Date.now();\n this.animate();\n }\n\n stop() {\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n }\n\n private animate = () => {\n const currentTime = Date.now();\n const deltaTime = currentTime - this.lastUpdateTime;\n let timeToConsume = deltaTime;\n\n const remainingChars = this.targetText.length - this.currentText.length;\n const baseTimePerChar = Math.min(\n this.maxCharIntervalMs,\n this.drainMs / remainingChars,\n );\n\n const frameLimit = Math.min(remainingChars, this.maxCharsPerFrame);\n let charsToAdd = 0;\n while (timeToConsume >= baseTimePerChar && charsToAdd < frameLimit) {\n charsToAdd++;\n timeToConsume -= baseTimePerChar;\n }\n // A cap-limited frame must not bank its surplus time, or the next\n // frame would burst past the cap.\n if (charsToAdd === frameLimit && frameLimit === this.maxCharsPerFrame) {\n timeToConsume = 0;\n }\n\n if (charsToAdd !== remainingChars) {\n this.animationFrameId = requestAnimationFrame(this.animate);\n } else {\n this.animationFrameId = null;\n }\n if (charsToAdd === 0) return;\n\n this.currentText = this.targetText.slice(\n 0,\n this.currentText.length + charsToAdd,\n );\n this.lastUpdateTime = currentTime - timeToConsume;\n\n const isComplete = charsToAdd === remainingChars;\n if (isComplete || currentTime - this.lastCommitTime >= this.minCommitMs) {\n this.lastCommitTime = currentTime;\n this.setText(this.currentText);\n }\n };\n}\n\nconst SMOOTH_STATUS: MessagePartStatus = Object.freeze({\n type: \"running\",\n});\n\nconst positiveOr = (value: number | undefined, fallback: number): number =>\n value !== undefined && value > 0 ? value : fallback;\n\n/**\n * Animates streamed message part text with a typewriter-style reveal.\n *\n * Takes the current part state and a `smooth` argument: `false` disables,\n * `true` uses the default rate, and a {@link SmoothOptions} object tunes\n * the reveal. Returns the part state with `text` replaced by the revealed\n * prefix and `status` reporting `running` until the reveal catches up.\n *\n * The reveal auto-disables under `prefers-reduced-motion: reduce`,\n * committing the full text immediately; this takes precedence over an\n * explicit `smooth={true}`.\n *\n * @example\n * ```tsx\n * const { text, status } = useSmooth(useMessagePartText(), {\n * drainMs: 500,\n * maxCharsPerFrame: 30,\n * });\n * ```\n */\nexport const useSmooth = (\n state: MessagePartState & (TextMessagePart | ReasoningMessagePart),\n smooth: boolean | SmoothOptions = false,\n): MessagePartState & (TextMessagePart | ReasoningMessagePart) => {\n const { text } = state;\n const reduceMotion = useMediaQuery(\"(prefers-reduced-motion: reduce)\");\n const options =\n typeof smooth === \"object\" && smooth !== null ? smooth : undefined;\n const enabled = smooth !== false && smooth !== null && !reduceMotion;\n const drainMs = positiveOr(options?.drainMs, DEFAULT_DRAIN_MS);\n const maxCharIntervalMs = positiveOr(\n options?.maxCharIntervalMs,\n DEFAULT_MAX_CHAR_INTERVAL_MS,\n );\n const maxCharsPerFrame = positiveOr(options?.maxCharsPerFrame, Infinity);\n const minCommitMs = positiveOr(options?.minCommitMs, 0);\n\n const [displayedText, setDisplayedText] = useState(\n state.status.type === \"running\" ? \"\" : text,\n );\n\n // Render-phase resync on part flip or text discontinuity, so the\n // first paint after a thread switch never shows the previous\n // part's text (#4051). `displayedText` is already a prefix of\n // `text` during normal streaming, so use it as the previous-text\n // reference instead of carrying separate state — avoids the\n // double render per streaming token. Read part identity through\n // `useAuiState` so we actually subscribe to its changes instead\n // of relying on a render-time proxy reference that may be stable\n // across thread swaps.\n const aui = useAui();\n const part = useAuiState(() => aui.part());\n const [prevPart, setPrevPart] = useState(part);\n if (part !== prevPart || !text.startsWith(displayedText)) {\n setPrevPart(part);\n setDisplayedText(state.status.type === \"running\" ? \"\" : text);\n }\n\n const smoothStatusStore = useSmoothStatusStore({ optional: true });\n const setText = useCallbackRef((text: string) => {\n setDisplayedText(text);\n if (smoothStatusStore) {\n const target =\n displayedText !== text || state.status.type === \"running\"\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n });\n\n // TODO this is hacky\n useEffect(() => {\n if (smoothStatusStore) {\n const target =\n enabled && (displayedText !== text || state.status.type === \"running\")\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n }, [smoothStatusStore, enabled, text, displayedText, state.status]);\n\n const [animatorRef] = useState<TextStreamAnimator>(\n new TextStreamAnimator(displayedText, setText),\n );\n\n useEffect(() => {\n animatorRef.drainMs = drainMs;\n animatorRef.maxCharIntervalMs = maxCharIntervalMs;\n animatorRef.maxCharsPerFrame = maxCharsPerFrame;\n animatorRef.minCommitMs = minCommitMs;\n }, [animatorRef, drainMs, maxCharIntervalMs, maxCharsPerFrame, minCommitMs]);\n\n const animatorPartRef = useRef(part);\n useEffect(() => {\n if (!enabled) {\n animatorRef.stop();\n return;\n }\n\n // Discontinuity: part flipped, or new text breaks continuation\n // of the animator's current target. Either case requires\n // resetting the cursor — without the part check, a new part\n // whose text happens to share a prefix with the previous target\n // would keep the stale cursor and flicker.\n const partChanged = animatorPartRef.current !== part;\n animatorPartRef.current = part;\n if (partChanged || !text.startsWith(animatorRef.targetText)) {\n if (state.status.type === \"running\") {\n animatorRef.currentText = \"\";\n animatorRef.targetText = text;\n animatorRef.lastCommitTime = 0;\n animatorRef.start();\n } else {\n animatorRef.currentText = text;\n animatorRef.targetText = text;\n animatorRef.stop();\n }\n return;\n }\n\n animatorRef.targetText = text;\n animatorRef.start();\n }, [animatorRef, enabled, text, state.status.type, part]);\n\n useEffect(() => {\n return () => {\n animatorRef.stop();\n };\n }, [animatorRef]);\n\n return useMemo(\n () =>\n enabled\n ? {\n ...state,\n text: displayedText,\n status: text === displayedText ? state.status : SMOOTH_STATUS,\n }\n : state,\n [enabled, displayedText, state, text],\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useToolArgsFieldStatus.d.ts","names":[],"sources":["../../src/utils/useToolArgsFieldStatus.ts"],"mappings":";cAKa,
|
|
1
|
+
{"version":3,"file":"useToolArgsFieldStatus.d.ts","names":[],"sources":["../../src/utils/useToolArgsFieldStatus.ts"],"mappings":";cAKa,yBAA0B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.27",
|
|
4
4
|
"description": "Open-source TypeScript/React library for building production-grade AI chat experiences",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -55,21 +55,23 @@
|
|
|
55
55
|
],
|
|
56
56
|
"sideEffects": false,
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@assistant-ui/core": "^0.2.
|
|
59
|
-
"@assistant-ui/store": "^0.2.
|
|
60
|
-
"@assistant-ui/tap": "^0.9.
|
|
61
|
-
"@radix-ui/primitive": "^1.1.
|
|
58
|
+
"@assistant-ui/core": "^0.2.21",
|
|
59
|
+
"@assistant-ui/store": "^0.2.20",
|
|
60
|
+
"@assistant-ui/tap": "^0.9.4",
|
|
61
|
+
"@radix-ui/primitive": "^1.1.5",
|
|
62
|
+
"@radix-ui/react-collection": "^1.1.12",
|
|
62
63
|
"@radix-ui/react-compose-refs": "^1.1.3",
|
|
63
|
-
"@radix-ui/react-context": "^1.
|
|
64
|
-
"@radix-ui/react-primitive": "^2.1.
|
|
64
|
+
"@radix-ui/react-context": "^1.2.0",
|
|
65
|
+
"@radix-ui/react-primitive": "^2.1.7",
|
|
65
66
|
"@radix-ui/react-use-callback-ref": "^1.1.2",
|
|
66
|
-
"@radix-ui/react-use-
|
|
67
|
-
"
|
|
68
|
-
"assistant-
|
|
69
|
-
"
|
|
70
|
-
"
|
|
67
|
+
"@radix-ui/react-use-controllable-state": "^1.2.3",
|
|
68
|
+
"@radix-ui/react-use-escape-keydown": "^1.1.3",
|
|
69
|
+
"assistant-cloud": "^0.1.35",
|
|
70
|
+
"assistant-stream": "^0.3.26",
|
|
71
|
+
"nanoid": "^6.0.0",
|
|
72
|
+
"radix-ui": "^1.6.2",
|
|
71
73
|
"react-textarea-autosize": "^8.5.9",
|
|
72
|
-
"safe-content-frame": "^0.0.
|
|
74
|
+
"safe-content-frame": "^0.0.23",
|
|
73
75
|
"zod": "^4.4.3",
|
|
74
76
|
"zustand": "^5.0.14"
|
|
75
77
|
},
|
|
@@ -90,15 +92,15 @@
|
|
|
90
92
|
"devDependencies": {
|
|
91
93
|
"@testing-library/react": "^16.3.2",
|
|
92
94
|
"@types/json-schema": "^7.0.15",
|
|
93
|
-
"@types/node": "^26.
|
|
95
|
+
"@types/node": "^26.1.1",
|
|
94
96
|
"@types/react": "^19.2.17",
|
|
95
97
|
"@types/react-dom": "^19.2.3",
|
|
96
98
|
"jsdom": "^29.1.1",
|
|
97
99
|
"react": "^19.2.7",
|
|
98
100
|
"react-dom": "^19.2.7",
|
|
99
|
-
"vitest": "^4.1.
|
|
100
|
-
"@assistant-ui/vite": "0.0.
|
|
101
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
101
|
+
"vitest": "^4.1.10",
|
|
102
|
+
"@assistant-ui/vite": "0.0.9",
|
|
103
|
+
"@assistant-ui/x-buildutils": "0.0.18"
|
|
102
104
|
},
|
|
103
105
|
"publishConfig": {
|
|
104
106
|
"access": "public",
|
package/src/index.ts
CHANGED
|
@@ -209,7 +209,9 @@ export {
|
|
|
209
209
|
providerTool,
|
|
210
210
|
type ProviderToolConfig,
|
|
211
211
|
defineMcpToolkit,
|
|
212
|
+
type McpToolkitEntry,
|
|
212
213
|
type McpToolkitDefinition,
|
|
214
|
+
type McpToolkitToolConfig,
|
|
213
215
|
Tools,
|
|
214
216
|
DataRenderers,
|
|
215
217
|
Interactables,
|
|
@@ -337,6 +339,7 @@ export type {
|
|
|
337
339
|
AppendMessage,
|
|
338
340
|
TextMessagePart,
|
|
339
341
|
ReasoningMessagePart,
|
|
342
|
+
PartProviderMetadata,
|
|
340
343
|
SourceProviderMetadata,
|
|
341
344
|
SourceMessagePart,
|
|
342
345
|
ImageMessagePart,
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
CompleteAttachment,
|
|
3
|
+
DataMessagePart,
|
|
4
|
+
FileMessagePart,
|
|
5
|
+
ImageMessagePart,
|
|
2
6
|
MessageStatus,
|
|
3
7
|
SourceProviderMetadata,
|
|
4
8
|
ThreadMessage,
|
|
9
|
+
TextMessagePart,
|
|
10
|
+
Unstable_AudioMessagePart,
|
|
5
11
|
} from "@assistant-ui/core";
|
|
6
12
|
import { fromThreadMessageLike } from "../runtime-cores/external-store/ThreadMessageLike";
|
|
7
13
|
import type { CloudMessage } from "assistant-cloud";
|
|
8
|
-
import { isJSONValue } from "
|
|
14
|
+
import { isJSONValue } from "@assistant-ui/core/internal";
|
|
9
15
|
import type {
|
|
10
16
|
ReadonlyJSONObject,
|
|
11
17
|
ReadonlyJSONValue,
|
|
@@ -65,10 +71,27 @@ type AuiV0MessagePart =
|
|
|
65
71
|
readonly filename?: string;
|
|
66
72
|
};
|
|
67
73
|
|
|
74
|
+
type AuiV0AttachmentPart =
|
|
75
|
+
| TextMessagePart
|
|
76
|
+
| ImageMessagePart
|
|
77
|
+
| FileMessagePart
|
|
78
|
+
| Unstable_AudioMessagePart
|
|
79
|
+
| DataMessagePart<ReadonlyJSONValue>;
|
|
80
|
+
|
|
81
|
+
type AuiV0Attachment = {
|
|
82
|
+
readonly id: string;
|
|
83
|
+
readonly type: CompleteAttachment["type"];
|
|
84
|
+
readonly name: string;
|
|
85
|
+
readonly contentType?: string;
|
|
86
|
+
readonly status: CompleteAttachment["status"];
|
|
87
|
+
readonly content: readonly AuiV0AttachmentPart[];
|
|
88
|
+
};
|
|
89
|
+
|
|
68
90
|
type AuiV0Message = {
|
|
69
91
|
readonly role: "assistant" | "user" | "system";
|
|
70
92
|
readonly status?: MessageStatus;
|
|
71
93
|
readonly content: readonly AuiV0MessagePart[];
|
|
94
|
+
readonly attachments?: readonly AuiV0Attachment[];
|
|
72
95
|
readonly metadata: {
|
|
73
96
|
readonly unstable_state?: ReadonlyJSONValue;
|
|
74
97
|
readonly unstable_annotations: readonly ReadonlyJSONValue[];
|
|
@@ -83,14 +106,59 @@ type AuiV0Message = {
|
|
|
83
106
|
};
|
|
84
107
|
};
|
|
85
108
|
|
|
109
|
+
const encodeAttachmentPart = (
|
|
110
|
+
part: CompleteAttachment["content"][number],
|
|
111
|
+
): AuiV0AttachmentPart => {
|
|
112
|
+
const type = part.type;
|
|
113
|
+
switch (type) {
|
|
114
|
+
case "text":
|
|
115
|
+
case "image":
|
|
116
|
+
case "file":
|
|
117
|
+
case "audio":
|
|
118
|
+
return part;
|
|
119
|
+
|
|
120
|
+
case "data": {
|
|
121
|
+
if (!isJSONValue(part.data)) {
|
|
122
|
+
console.warn(`attachment data is not JSON! ${JSON.stringify(part)}`);
|
|
123
|
+
}
|
|
124
|
+
return { ...part, data: part.data as ReadonlyJSONValue };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
default: {
|
|
128
|
+
const unhandledType: never = type;
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Attachment part type not supported by aui/v0: ${unhandledType}`,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const encodeAttachments = (
|
|
137
|
+
message: ThreadMessage,
|
|
138
|
+
): readonly AuiV0Attachment[] | undefined => {
|
|
139
|
+
if (message.role !== "user" || message.attachments.length === 0) {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return message.attachments.map(
|
|
144
|
+
({ id, type, name, contentType, status, content }) => ({
|
|
145
|
+
id,
|
|
146
|
+
type,
|
|
147
|
+
name,
|
|
148
|
+
status,
|
|
149
|
+
...(contentType != null ? { contentType } : undefined),
|
|
150
|
+
content: content.map(encodeAttachmentPart),
|
|
151
|
+
}),
|
|
152
|
+
);
|
|
153
|
+
};
|
|
154
|
+
|
|
86
155
|
export function auiV0Encode(message: ThreadMessage): AuiV0Message {
|
|
87
|
-
// TODO attachments are currently intentionally ignored
|
|
88
156
|
// info: ID and createdAt are ignored (we use the server value instead)
|
|
89
|
-
|
|
90
157
|
const status: MessageStatus | undefined =
|
|
91
158
|
message.status?.type === "running"
|
|
92
159
|
? { type: "incomplete", reason: "cancelled" }
|
|
93
160
|
: message.status;
|
|
161
|
+
const attachments = encodeAttachments(message);
|
|
94
162
|
|
|
95
163
|
return {
|
|
96
164
|
role: message.role,
|
|
@@ -172,6 +240,7 @@ export function auiV0Encode(message: ThreadMessage): AuiV0Message {
|
|
|
172
240
|
}),
|
|
173
241
|
metadata: message.metadata as AuiV0Message["metadata"],
|
|
174
242
|
...(status ? { status } : undefined),
|
|
243
|
+
...(attachments ? { attachments } : undefined),
|
|
175
244
|
};
|
|
176
245
|
}
|
|
177
246
|
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { render, waitFor } from "@testing-library/react";
|
|
3
|
+
import { resource, useResource } from "@assistant-ui/tap";
|
|
4
|
+
import type { ToolCallMessagePartProps } from "@assistant-ui/core/react";
|
|
5
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
import type { McpAppBridgeHandlers, McpAppsHost } from "./types";
|
|
7
|
+
|
|
8
|
+
const { framePropsMock } = vi.hoisted(() => ({ framePropsMock: vi.fn() }));
|
|
9
|
+
|
|
10
|
+
vi.mock("@assistant-ui/store", async (importOriginal) => ({
|
|
11
|
+
...(await importOriginal()),
|
|
12
|
+
useAui: () => ({
|
|
13
|
+
thread: () => ({ append: vi.fn() }),
|
|
14
|
+
}),
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
vi.mock("./app-frame", () => ({
|
|
18
|
+
McpAppFrame: (props: unknown) => {
|
|
19
|
+
framePropsMock(props);
|
|
20
|
+
return null;
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
import { McpAppRenderer } from "./McpAppRenderer";
|
|
25
|
+
|
|
26
|
+
const useHost = ({ host }: { host: McpAppsHost }) => host;
|
|
27
|
+
const Host = resource(useHost);
|
|
28
|
+
|
|
29
|
+
const createPart = (serverId?: string): ToolCallMessagePartProps => ({
|
|
30
|
+
type: "tool-call",
|
|
31
|
+
toolCallId: "call-1",
|
|
32
|
+
toolName: "search",
|
|
33
|
+
args: {},
|
|
34
|
+
argsText: "{}",
|
|
35
|
+
status: { type: "complete" },
|
|
36
|
+
mcp: {
|
|
37
|
+
app: {
|
|
38
|
+
resourceUri: "ui://example/search",
|
|
39
|
+
...(serverId !== undefined ? { serverId } : {}),
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
addResult: vi.fn(),
|
|
43
|
+
resume: vi.fn(),
|
|
44
|
+
respondToApproval: vi.fn(),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
function Harness({ host, serverId }: { host: McpAppsHost; serverId?: string }) {
|
|
48
|
+
const renderer = useResource(
|
|
49
|
+
McpAppRenderer({
|
|
50
|
+
host: Host({ host }),
|
|
51
|
+
}),
|
|
52
|
+
);
|
|
53
|
+
const Renderer = renderer.render;
|
|
54
|
+
return <Renderer {...createPart(serverId)} />;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
describe("McpAppRenderer", () => {
|
|
58
|
+
beforeEach(() => {
|
|
59
|
+
framePropsMock.mockReset();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("injects serverId into loadResource and reloads when it changes", async () => {
|
|
63
|
+
const loadResource = vi.fn(async ({ uri }: { uri: string }) => ({
|
|
64
|
+
uri,
|
|
65
|
+
mimeType: "text/html;profile=mcp-app" as const,
|
|
66
|
+
html: "",
|
|
67
|
+
}));
|
|
68
|
+
const host: McpAppsHost = {
|
|
69
|
+
loadResource,
|
|
70
|
+
callTool: vi.fn(),
|
|
71
|
+
readResource: vi.fn(),
|
|
72
|
+
listResources: vi.fn(),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const view = render(<Harness host={host} serverId="server-a" />);
|
|
76
|
+
await waitFor(() =>
|
|
77
|
+
expect(loadResource).toHaveBeenCalledWith({
|
|
78
|
+
uri: "ui://example/search",
|
|
79
|
+
serverId: "server-a",
|
|
80
|
+
}),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
view.rerender(<Harness host={host} serverId="server-b" />);
|
|
84
|
+
await waitFor(() => expect(loadResource).toHaveBeenCalledTimes(2));
|
|
85
|
+
expect(loadResource).toHaveBeenLastCalledWith({
|
|
86
|
+
uri: "ui://example/search",
|
|
87
|
+
serverId: "server-b",
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("gives the renderer serverId precedence in listResources", async () => {
|
|
92
|
+
const listResources = vi.fn();
|
|
93
|
+
const host: McpAppsHost = {
|
|
94
|
+
loadResource: vi.fn(async ({ uri }) => ({
|
|
95
|
+
uri,
|
|
96
|
+
mimeType: "text/html;profile=mcp-app" as const,
|
|
97
|
+
html: "",
|
|
98
|
+
})),
|
|
99
|
+
callTool: vi.fn(),
|
|
100
|
+
readResource: vi.fn(),
|
|
101
|
+
listResources,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
render(<Harness host={host} serverId="host-server" />);
|
|
105
|
+
await waitFor(() => expect(framePropsMock).toHaveBeenCalled());
|
|
106
|
+
const handlers = framePropsMock.mock.lastCall?.[0]
|
|
107
|
+
.handlers as McpAppBridgeHandlers;
|
|
108
|
+
|
|
109
|
+
await handlers.listResources?.({
|
|
110
|
+
cursor: "next",
|
|
111
|
+
serverId: "widget-server",
|
|
112
|
+
});
|
|
113
|
+
expect(listResources).toHaveBeenCalledWith({
|
|
114
|
+
cursor: "next",
|
|
115
|
+
serverId: "host-server",
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("passes listResources params through unchanged without serverId", async () => {
|
|
120
|
+
const listResources = vi.fn();
|
|
121
|
+
const host: McpAppsHost = {
|
|
122
|
+
loadResource: vi.fn(async ({ uri }) => ({
|
|
123
|
+
uri,
|
|
124
|
+
mimeType: "text/html;profile=mcp-app" as const,
|
|
125
|
+
html: "",
|
|
126
|
+
})),
|
|
127
|
+
callTool: vi.fn(),
|
|
128
|
+
readResource: vi.fn(),
|
|
129
|
+
listResources,
|
|
130
|
+
};
|
|
131
|
+
const params = { cursor: "next" };
|
|
132
|
+
|
|
133
|
+
render(<Harness host={host} />);
|
|
134
|
+
await waitFor(() => expect(framePropsMock).toHaveBeenCalled());
|
|
135
|
+
const handlers = framePropsMock.mock.lastCall?.[0]
|
|
136
|
+
.handlers as McpAppBridgeHandlers;
|
|
137
|
+
|
|
138
|
+
await handlers.listResources?.(params);
|
|
139
|
+
expect(listResources).toHaveBeenCalledWith(params);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -26,6 +26,7 @@ import type {
|
|
|
26
26
|
McpAppsHost,
|
|
27
27
|
} from "./types";
|
|
28
28
|
import { getMcpAppFromToolPart } from "./utils";
|
|
29
|
+
import { isRecord } from "@assistant-ui/core/internal";
|
|
29
30
|
|
|
30
31
|
export type McpAppRendererOptions = {
|
|
31
32
|
/**
|
|
@@ -55,6 +56,7 @@ export type McpAppRendererOptions = {
|
|
|
55
56
|
|
|
56
57
|
type LoadedResourceState = {
|
|
57
58
|
resourceUri: string;
|
|
59
|
+
serverId?: string;
|
|
58
60
|
resource?: McpAppResource;
|
|
59
61
|
error?: Error;
|
|
60
62
|
};
|
|
@@ -100,7 +102,11 @@ function InlineRenderer({
|
|
|
100
102
|
const aui = useAui();
|
|
101
103
|
const app = getMcpAppFromToolPart(part);
|
|
102
104
|
const cachedAppRef = useRef<McpAppMetadata | undefined>(undefined);
|
|
103
|
-
if (
|
|
105
|
+
if (
|
|
106
|
+
app != null &&
|
|
107
|
+
(cachedAppRef.current?.resourceUri !== app.resourceUri ||
|
|
108
|
+
cachedAppRef.current?.serverId !== app.serverId)
|
|
109
|
+
) {
|
|
104
110
|
cachedAppRef.current = app;
|
|
105
111
|
}
|
|
106
112
|
const appForRender = app ?? cachedAppRef.current;
|
|
@@ -108,21 +114,37 @@ function InlineRenderer({
|
|
|
108
114
|
const [loadedResource, setLoadedResource] = useState<LoadedResourceState>();
|
|
109
115
|
|
|
110
116
|
const resourceUri = appForRender?.resourceUri;
|
|
117
|
+
const serverId = appForRender?.serverId;
|
|
118
|
+
const serverIdRef = useRef<string | undefined>(undefined);
|
|
119
|
+
serverIdRef.current = serverId;
|
|
111
120
|
useEffect(() => {
|
|
112
121
|
if (appForRender == null || resourceUri == null) return;
|
|
113
122
|
let cancelled = false;
|
|
114
123
|
const targetUri = resourceUri;
|
|
124
|
+
const targetServerId = serverId;
|
|
115
125
|
|
|
116
126
|
internalsRef.current.host
|
|
117
|
-
.loadResource({
|
|
127
|
+
.loadResource({
|
|
128
|
+
uri: targetUri,
|
|
129
|
+
...(targetServerId ? { serverId: targetServerId } : {}),
|
|
130
|
+
})
|
|
118
131
|
.then((res) => {
|
|
119
132
|
if (!cancelled)
|
|
120
|
-
setLoadedResource({
|
|
133
|
+
setLoadedResource({
|
|
134
|
+
resourceUri: targetUri,
|
|
135
|
+
...(targetServerId !== undefined
|
|
136
|
+
? { serverId: targetServerId }
|
|
137
|
+
: {}),
|
|
138
|
+
resource: res,
|
|
139
|
+
});
|
|
121
140
|
})
|
|
122
141
|
.catch((error: unknown) => {
|
|
123
142
|
if (!cancelled) {
|
|
124
143
|
setLoadedResource({
|
|
125
144
|
resourceUri: targetUri,
|
|
145
|
+
...(targetServerId !== undefined
|
|
146
|
+
? { serverId: targetServerId }
|
|
147
|
+
: {}),
|
|
126
148
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
127
149
|
});
|
|
128
150
|
}
|
|
@@ -131,8 +153,8 @@ function InlineRenderer({
|
|
|
131
153
|
return () => {
|
|
132
154
|
cancelled = true;
|
|
133
155
|
};
|
|
134
|
-
// oxlint-disable-next-line react/exhaustive-deps -- re-fetch only when URI changes; appForRender identity is unstable and internalsRef is a stable ref
|
|
135
|
-
}, [resourceUri]);
|
|
156
|
+
// oxlint-disable-next-line react/exhaustive-deps -- re-fetch only when URI or server identity changes; appForRender identity is unstable and internalsRef is a stable ref
|
|
157
|
+
}, [resourceUri, serverId]);
|
|
136
158
|
|
|
137
159
|
const bridgeHandlers = useMemo<McpAppBridgeHandlers>(
|
|
138
160
|
() => ({
|
|
@@ -143,16 +165,32 @@ function InlineRenderer({
|
|
|
143
165
|
aui.thread().append({ content: [{ type: "text", text }] });
|
|
144
166
|
return { ok: true };
|
|
145
167
|
},
|
|
146
|
-
callTool: (params) =>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
168
|
+
callTool: (params) =>
|
|
169
|
+
internalsRef.current.host.callTool({
|
|
170
|
+
...params,
|
|
171
|
+
...(serverIdRef.current ? { serverId: serverIdRef.current } : {}),
|
|
172
|
+
}),
|
|
173
|
+
readResource: (params) =>
|
|
174
|
+
internalsRef.current.host.readResource({
|
|
175
|
+
...params,
|
|
176
|
+
...(serverIdRef.current ? { serverId: serverIdRef.current } : {}),
|
|
177
|
+
}),
|
|
178
|
+
listResources: (params) => {
|
|
179
|
+
if (!serverIdRef.current) {
|
|
180
|
+
return internalsRef.current.host.listResources(params);
|
|
181
|
+
}
|
|
182
|
+
return internalsRef.current.host.listResources({
|
|
183
|
+
...(isRecord(params) ? params : {}),
|
|
184
|
+
serverId: serverIdRef.current,
|
|
185
|
+
});
|
|
186
|
+
},
|
|
150
187
|
}),
|
|
151
188
|
[aui, internalsRef],
|
|
152
189
|
);
|
|
153
190
|
|
|
154
191
|
const loadedResourceForApp =
|
|
155
|
-
loadedResource?.resourceUri === appForRender?.resourceUri
|
|
192
|
+
loadedResource?.resourceUri === appForRender?.resourceUri &&
|
|
193
|
+
loadedResource?.serverId === appForRender?.serverId
|
|
156
194
|
? loadedResource
|
|
157
195
|
: undefined;
|
|
158
196
|
const appResource = loadedResourceForApp?.resource;
|