@assistant-ui/react 0.14.18 → 0.14.19
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/client/ExternalThread.d.ts +3 -2
- package/dist/client/ExternalThread.d.ts.map +1 -1
- package/dist/client/ExternalThread.js +721 -256
- package/dist/client/ExternalThread.js.map +1 -1
- package/dist/client/InMemoryThreadList.d.ts.map +1 -1
- package/dist/client/InMemoryThreadList.js +292 -108
- package/dist/client/InMemoryThreadList.js.map +1 -1
- package/dist/client/SingleThreadList.js +139 -53
- package/dist/client/SingleThreadList.js.map +1 -1
- package/dist/context/ReadonlyStore.js.map +1 -1
- package/dist/context/providers/MessageProvider.js +38 -5
- package/dist/context/providers/MessageProvider.js.map +1 -1
- package/dist/context/providers/ThreadViewportProvider.js +76 -20
- package/dist/context/providers/ThreadViewportProvider.js.map +1 -1
- package/dist/context/react/ThreadViewportContext.js.map +1 -1
- package/dist/context/react/utils/createContextHook.js.map +1 -1
- package/dist/context/react/utils/createContextStoreHook.js +17 -2
- package/dist/context/react/utils/createContextStoreHook.js.map +1 -1
- package/dist/context/react/utils/createStateHookForRuntime.js.map +1 -1
- package/dist/context/react/utils/ensureBinding.js.map +1 -1
- package/dist/context/react/utils/useRuntimeState.js +18 -2
- package/dist/context/react/utils/useRuntimeState.js.map +1 -1
- package/dist/context/stores/ThreadViewport.js.map +1 -1
- package/dist/devtools/DevToolsHooks.js.map +1 -1
- package/dist/hooks/useMessageQuote.js.map +1 -1
- package/dist/hooks/useMessageTiming.js +4 -1
- package/dist/hooks/useMessageTiming.js.map +1 -1
- package/dist/hooks/useToolCallElapsed.d.ts +23 -0
- package/dist/hooks/useToolCallElapsed.d.ts.map +1 -0
- package/dist/hooks/useToolCallElapsed.js +72 -0
- package/dist/hooks/useToolCallElapsed.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -1
- package/dist/internal.js.map +1 -1
- package/dist/legacy-runtime/AssistantRuntimeProvider.js +46 -10
- package/dist/legacy-runtime/AssistantRuntimeProvider.js.map +1 -1
- package/dist/legacy-runtime/cloud/auiV0.js.map +1 -1
- package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.js +27 -6
- package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.js.map +1 -1
- package/dist/legacy-runtime/hooks/AssistantContext.js +13 -2
- package/dist/legacy-runtime/hooks/AssistantContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/AttachmentContext.js +9 -1
- package/dist/legacy-runtime/hooks/AttachmentContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/ComposerContext.js +9 -1
- package/dist/legacy-runtime/hooks/ComposerContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/MessageContext.js +12 -2
- package/dist/legacy-runtime/hooks/MessageContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/MessagePartContext.js +9 -1
- package/dist/legacy-runtime/hooks/MessagePartContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/ThreadContext.js +33 -5
- package/dist/legacy-runtime/hooks/ThreadContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/ThreadListItemContext.js +9 -1
- package/dist/legacy-runtime/hooks/ThreadListItemContext.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.js +3 -3
- package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.js +71 -31
- package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +24 -16
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.js +17 -12
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.js +17 -3
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.js.map +1 -1
- package/dist/mcp-apps/McpAppRenderer.js +6 -6
- package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/mcp-apps/McpAppsRemoteHost.js +3 -3
- package/dist/mcp-apps/McpAppsRemoteHost.js.map +1 -1
- package/dist/mcp-apps/app-frame.js +33 -14
- package/dist/mcp-apps/app-frame.js.map +1 -1
- package/dist/mcp-apps/bridge.js.map +1 -1
- package/dist/mcp-apps/types.js.map +1 -1
- package/dist/mcp-apps/utils.js.map +1 -1
- package/dist/model-context/frame/useAssistantFrameHost.js +32 -14
- package/dist/model-context/frame/useAssistantFrameHost.js.map +1 -1
- package/dist/model-context/makeAssistantVisible.js +64 -26
- package/dist/model-context/makeAssistantVisible.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarCopy.js +94 -20
- package/dist/primitives/actionBar/ActionBarCopy.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarEdit.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarExportMarkdown.js +105 -37
- package/dist/primitives/actionBar/ActionBarExportMarkdown.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +60 -11
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +60 -11
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarInteractionContext.js +3 -1
- package/dist/primitives/actionBar/ActionBarInteractionContext.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarReload.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarRoot.js +84 -25
- package/dist/primitives/actionBar/ActionBarRoot.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarSpeak.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarStopSpeaking.js +45 -14
- package/dist/primitives/actionBar/ActionBarStopSpeaking.js.map +1 -1
- package/dist/primitives/actionBar/useActionBarFloatStatus.js +22 -10
- package/dist/primitives/actionBar/useActionBarFloatStatus.js.map +1 -1
- package/dist/primitives/actionBar.js.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreContent.js +44 -7
- package/dist/primitives/actionBarMore/ActionBarMoreContent.js.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreItem.js +28 -6
- package/dist/primitives/actionBarMore/ActionBarMoreItem.js.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreRoot.js +103 -36
- package/dist/primitives/actionBarMore/ActionBarMoreRoot.js.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreSeparator.js +28 -6
- package/dist/primitives/actionBarMore/ActionBarMoreSeparator.js.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreTrigger.js +28 -6
- package/dist/primitives/actionBarMore/ActionBarMoreTrigger.js.map +1 -1
- package/dist/primitives/actionBarMore/scope.js.map +1 -1
- package/dist/primitives/actionBarMore.js.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalAnchor.js +27 -6
- package/dist/primitives/assistantModal/AssistantModalAnchor.js.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalContent.js +71 -10
- package/dist/primitives/assistantModal/AssistantModalContent.js.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalRoot.js +93 -26
- package/dist/primitives/assistantModal/AssistantModalRoot.js.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalTrigger.js +27 -6
- package/dist/primitives/assistantModal/AssistantModalTrigger.js.map +1 -1
- package/dist/primitives/assistantModal/scope.js.map +1 -1
- package/dist/primitives/assistantModal.js.map +1 -1
- package/dist/primitives/attachment/AttachmentName.js +13 -1
- package/dist/primitives/attachment/AttachmentName.js.map +1 -1
- package/dist/primitives/attachment/AttachmentRemove.js +11 -4
- package/dist/primitives/attachment/AttachmentRemove.js.map +1 -1
- package/dist/primitives/attachment/AttachmentRoot.js +13 -4
- package/dist/primitives/attachment/AttachmentRoot.js.map +1 -1
- package/dist/primitives/attachment/AttachmentThumb.js +20 -9
- package/dist/primitives/attachment/AttachmentThumb.js.map +1 -1
- package/dist/primitives/attachment.js.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerCount.js +14 -2
- package/dist/primitives/branchPicker/BranchPickerCount.js.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerNext.js.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerNumber.js +14 -2
- package/dist/primitives/branchPicker/BranchPickerNumber.js.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerPrevious.js.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerRoot.js +34 -6
- package/dist/primitives/branchPicker/BranchPickerRoot.js.map +1 -1
- package/dist/primitives/branchPicker.js.map +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +16 -5
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtRoot.js +13 -4
- package/dist/primitives/chainOfThought/ChainOfThoughtRoot.js.map +1 -1
- package/dist/primitives/chainOfThought.js.map +1 -1
- package/dist/primitives/composer/ComposerAddAttachment.js +37 -24
- package/dist/primitives/composer/ComposerAddAttachment.js.map +1 -1
- package/dist/primitives/composer/ComposerAttachmentDropzone.js +124 -49
- package/dist/primitives/composer/ComposerAttachmentDropzone.js.map +1 -1
- package/dist/primitives/composer/ComposerCancel.js.map +1 -1
- package/dist/primitives/composer/ComposerDictate.js.map +1 -1
- package/dist/primitives/composer/ComposerDictationTranscript.js +32 -7
- package/dist/primitives/composer/ComposerDictationTranscript.js.map +1 -1
- package/dist/primitives/composer/ComposerInput.js +26 -26
- package/dist/primitives/composer/ComposerInput.js.map +1 -1
- package/dist/primitives/composer/ComposerInputPluginContext.js +71 -25
- package/dist/primitives/composer/ComposerInputPluginContext.js.map +1 -1
- package/dist/primitives/composer/ComposerQuote.js +92 -23
- package/dist/primitives/composer/ComposerQuote.js.map +1 -1
- package/dist/primitives/composer/ComposerRoot.js +45 -11
- package/dist/primitives/composer/ComposerRoot.js.map +1 -1
- package/dist/primitives/composer/ComposerSend.js +9 -2
- package/dist/primitives/composer/ComposerSend.js.map +1 -1
- package/dist/primitives/composer/ComposerStopDictation.js +15 -5
- package/dist/primitives/composer/ComposerStopDictation.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopover.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopover.js +215 -75
- package/dist/primitives/composer/trigger/TriggerPopover.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverBack.js +35 -7
- package/dist/primitives/composer/trigger/TriggerPopoverBack.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.js +134 -28
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverItems.js +132 -28
- package/dist/primitives/composer/trigger/TriggerPopoverItems.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverResource.js +124 -52
- package/dist/primitives/composer/trigger/TriggerPopoverResource.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js +181 -78
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js.map +1 -1
- package/dist/primitives/composer/trigger/detectTrigger.js.map +1 -1
- package/dist/primitives/composer/trigger/index.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerDetectionResource.js +28 -14
- package/dist/primitives/composer/trigger/triggerDetectionResource.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerKeyboardResource.js +115 -58
- package/dist/primitives/composer/trigger/triggerKeyboardResource.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerNavigationResource.js +202 -70
- package/dist/primitives/composer/trigger/triggerNavigationResource.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerSelectionResource.js +49 -13
- package/dist/primitives/composer/trigger/triggerSelectionResource.js.map +1 -1
- package/dist/primitives/composer.js.map +1 -1
- package/dist/primitives/dropdownMenuRenderPrimitives.js.map +1 -1
- package/dist/primitives/error/ErrorMessage.js +28 -6
- package/dist/primitives/error/ErrorMessage.js.map +1 -1
- package/dist/primitives/error/ErrorRoot.js +14 -5
- package/dist/primitives/error/ErrorRoot.js.map +1 -1
- package/dist/primitives/error.js.map +1 -1
- package/dist/primitives/message/MessageError.js +2 -1
- package/dist/primitives/message/MessageError.js.map +1 -1
- package/dist/primitives/message/MessageIf.js +50 -20
- package/dist/primitives/message/MessageIf.js.map +1 -1
- package/dist/primitives/message/MessageParts.js +41 -7
- package/dist/primitives/message/MessageParts.js.map +1 -1
- package/dist/primitives/message/MessagePartsGrouped.js +399 -94
- package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
- package/dist/primitives/message/MessageRoot.js +197 -65
- package/dist/primitives/message/MessageRoot.js.map +1 -1
- package/dist/primitives/message.js.map +1 -1
- package/dist/primitives/messagePart/MessagePartImage.js +15 -5
- package/dist/primitives/messagePart/MessagePartImage.js.map +1 -1
- package/dist/primitives/messagePart/MessagePartText.js +35 -7
- package/dist/primitives/messagePart/MessagePartText.js.map +1 -1
- package/dist/primitives/messagePart/useMessagePartData.js +5 -4
- package/dist/primitives/messagePart/useMessagePartData.js.map +1 -1
- package/dist/primitives/messagePart/useMessagePartFile.js +5 -4
- package/dist/primitives/messagePart/useMessagePartFile.js.map +1 -1
- package/dist/primitives/messagePart/useMessagePartImage.js +5 -4
- package/dist/primitives/messagePart/useMessagePartImage.js.map +1 -1
- package/dist/primitives/messagePart/useMessagePartReasoning.js +5 -4
- package/dist/primitives/messagePart/useMessagePartReasoning.js.map +1 -1
- package/dist/primitives/messagePart/useMessagePartSource.js +5 -4
- package/dist/primitives/messagePart/useMessagePartSource.js.map +1 -1
- package/dist/primitives/messagePart/useMessagePartText.js +5 -4
- package/dist/primitives/messagePart/useMessagePartText.js.map +1 -1
- package/dist/primitives/messagePart.js.map +1 -1
- package/dist/primitives/queueItem/QueueItemRemove.js +11 -4
- package/dist/primitives/queueItem/QueueItemRemove.js.map +1 -1
- package/dist/primitives/queueItem/QueueItemSteer.js +11 -4
- package/dist/primitives/queueItem/QueueItemSteer.js.map +1 -1
- package/dist/primitives/queueItem/QueueItemText.js +20 -6
- package/dist/primitives/queueItem/QueueItemText.js.map +1 -1
- package/dist/primitives/queueItem.js.map +1 -1
- package/dist/primitives/reasoning/useScrollLock.js +61 -43
- package/dist/primitives/reasoning/useScrollLock.js.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js +56 -16
- package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +120 -59
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js.map +1 -1
- package/dist/primitives/selectionToolbar.js.map +1 -1
- package/dist/primitives/suggestion/SuggestionDescription.js +20 -6
- package/dist/primitives/suggestion/SuggestionDescription.js.map +1 -1
- package/dist/primitives/suggestion/SuggestionTitle.js +20 -6
- package/dist/primitives/suggestion/SuggestionTitle.js.map +1 -1
- package/dist/primitives/suggestion/SuggestionTrigger.js +39 -26
- package/dist/primitives/suggestion/SuggestionTrigger.js.map +1 -1
- package/dist/primitives/suggestion.js.map +1 -1
- package/dist/primitives/thread/ThreadEmpty.js +6 -2
- package/dist/primitives/thread/ThreadEmpty.js.map +1 -1
- package/dist/primitives/thread/ThreadIf.js +32 -10
- package/dist/primitives/thread/ThreadIf.js.map +1 -1
- package/dist/primitives/thread/ThreadRoot.js +13 -4
- package/dist/primitives/thread/ThreadRoot.js.map +1 -1
- package/dist/primitives/thread/ThreadScrollToBottom.js +24 -6
- package/dist/primitives/thread/ThreadScrollToBottom.js.map +1 -1
- package/dist/primitives/thread/ThreadSuggestion.js +18 -6
- package/dist/primitives/thread/ThreadSuggestion.js.map +1 -1
- package/dist/primitives/thread/ThreadViewport.js +185 -47
- package/dist/primitives/thread/ThreadViewport.js.map +1 -1
- package/dist/primitives/thread/ThreadViewportFooter.js +22 -9
- package/dist/primitives/thread/ThreadViewportFooter.js.map +1 -1
- package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.js.map +1 -1
- package/dist/primitives/thread/topAnchor/createReserveObservers.js.map +1 -1
- package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js.map +1 -1
- package/dist/primitives/thread/topAnchor/topAnchorTurn.js.map +1 -1
- package/dist/primitives/thread/topAnchor/topAnchorUtils.js.map +1 -1
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js +19 -4
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js.map +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.js +16 -16
- package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
- package/dist/primitives/thread.js.map +1 -1
- package/dist/primitives/threadList/ThreadListLoadMore.js.map +1 -1
- package/dist/primitives/threadList/ThreadListNew.js +53 -11
- package/dist/primitives/threadList/ThreadListNew.js.map +1 -1
- package/dist/primitives/threadList/ThreadListRoot.js +13 -4
- package/dist/primitives/threadList/ThreadListRoot.js.map +1 -1
- package/dist/primitives/threadList.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemArchive.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemDelete.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemRoot.js +26 -7
- package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemTrigger.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemUnarchive.js.map +1 -1
- package/dist/primitives/threadListItem.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js +44 -7
- package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.js +28 -6
- package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js +25 -5
- package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.js +28 -6
- package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js +28 -6
- package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js.map +1 -1
- package/dist/primitives/threadListItemMore/scope.js.map +1 -1
- package/dist/primitives/threadListItemMore.js.map +1 -1
- package/dist/sandbox-host/SandboxHost.js.map +1 -1
- package/dist/tests/remote-thread-list-test-helpers.js.map +1 -1
- package/dist/tests/setup.js.map +1 -1
- package/dist/unstable/useComposerInputHistory.js.map +1 -1
- package/dist/unstable/useMentionAdapter.js.map +1 -1
- package/dist/unstable/useMessageStallDetection.d.ts +29 -0
- package/dist/unstable/useMessageStallDetection.d.ts.map +1 -0
- package/dist/unstable/useMessageStallDetection.js +69 -0
- package/dist/unstable/useMessageStallDetection.js.map +1 -0
- package/dist/unstable/useSlashCommandAdapter.js.map +1 -1
- package/dist/utils/Primitive.js +57 -12
- package/dist/utils/Primitive.js.map +1 -1
- package/dist/utils/createActionButton.js +23 -7
- package/dist/utils/createActionButton.js.map +1 -1
- package/dist/utils/getSelectionMessageId.js.map +1 -1
- package/dist/utils/hooks/useManagedRef.js +16 -8
- package/dist/utils/hooks/useManagedRef.js.map +1 -1
- package/dist/utils/hooks/useMediaQuery.js +25 -10
- package/dist/utils/hooks/useMediaQuery.js.map +1 -1
- package/dist/utils/hooks/useOnResizeContent.js +29 -19
- package/dist/utils/hooks/useOnResizeContent.js.map +1 -1
- package/dist/utils/hooks/useOnScrollToBottom.js +20 -4
- package/dist/utils/hooks/useOnScrollToBottom.js.map +1 -1
- package/dist/utils/hooks/useSizeHandle.js +23 -15
- package/dist/utils/hooks/useSizeHandle.js.map +1 -1
- package/dist/utils/json/is-json-equal.js.map +1 -1
- package/dist/utils/json/is-json.js.map +1 -1
- package/dist/utils/smooth/SmoothContext.js +41 -11
- package/dist/utils/smooth/SmoothContext.js.map +1 -1
- package/dist/utils/smooth/useSmooth.js +5 -5
- package/dist/utils/smooth/useSmooth.js.map +1 -1
- package/dist/utils/useToolArgsFieldStatus.d.ts +2 -2
- package/dist/utils/useToolArgsFieldStatus.d.ts.map +1 -1
- package/dist/utils/useToolArgsFieldStatus.js +13 -5
- package/dist/utils/useToolArgsFieldStatus.js.map +1 -1
- package/package.json +6 -6
- package/src/client/ExternalThread.ts +81 -52
- package/src/client/InMemoryThreadList.ts +12 -14
- package/src/hooks/useToolCallElapsed.ts +52 -0
- package/src/index.ts +11 -0
- package/src/primitives/composer/trigger/TriggerPopover.tsx +4 -5
- package/src/tests/toolCallTiming.test.tsx +221 -0
- package/src/unstable/useMessageStallDetection.ts +91 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replayBoundaryStream.js","names":[],"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport const REPLAY_CONTENT_LENGTH_HEADER = \"Aui-Replay-Content-Length\";\n\ntype ReplayBoundaryStreamOptions = {\n setReplaying: (value: boolean) => void;\n waitForRender: () => Promise<void>;\n};\n\nexport const useReplayRenderWait = () => {\n const [renderTicket, setRenderTicket] = useState(0);\n const mountedRef = useRef(true);\n const nextTicketRef = useRef(0);\n const waitersRef = useRef<Array<{ ticket: number; resolve: () => void }>>([]);\n\n const resolveWaiters = useCallback((committedTicket?: number) => {\n const pendingWaiters = [];\n\n for (const waiter of waitersRef.current) {\n if (committedTicket === undefined || waiter.ticket <= committedTicket) {\n waiter.resolve();\n } else {\n pendingWaiters.push(waiter);\n }\n }\n\n waitersRef.current = pendingWaiters;\n }, []);\n\n useEffect(() => {\n mountedRef.current = true;\n resolveWaiters(renderTicket);\n }, [renderTicket, resolveWaiters]);\n\n useEffect(\n () => () => {\n mountedRef.current = false;\n resolveWaiters();\n },\n [resolveWaiters],\n );\n\n return useCallback(\n () =>\n new Promise<void>((resolve) => {\n setTimeout(() => {\n if (!mountedRef.current) {\n resolve();\n return;\n }\n\n const ticket = nextTicketRef.current + 1;\n nextTicketRef.current = ticket;\n waitersRef.current.push({ ticket, resolve });\n setRenderTicket(ticket);\n }, 0);\n }),\n [],\n );\n};\n\nconst parseReplayContentLength = (headers: Headers): number => {\n const raw = headers.get(REPLAY_CONTENT_LENGTH_HEADER);\n if (raw == null) return 0;\n\n const boundary = Number(raw);\n return Number.isSafeInteger(boundary) && boundary > 0 ? boundary : 0;\n};\n\n// Gates replay bytes until isReplaying:true renders, then releases live bytes after isReplaying:false renders.\nexport const createReplayBoundaryStream = async (\n response: Response,\n {\n setReplaying,\n waitForRender: waitForReplayRender,\n }: ReplayBoundaryStreamOptions,\n): Promise<ReadableStream<Uint8Array>> => {\n const body = response.body as ReadableStream<Uint8Array>;\n const replayContentLength = parseReplayContentLength(response.headers);\n\n if (replayContentLength <= 0) {\n return body;\n }\n\n setReplaying(true);\n await waitForReplayRender();\n\n const reader = body.getReader();\n let bytesForwarded = 0;\n let replayFinished = false;\n\n const finishReplay = async () => {\n if (replayFinished) return;\n replayFinished = true;\n\n // Let replay bytes drain before rendering live mode, then render live mode before releasing live bytes.\n await waitForReplayRender();\n setReplaying(false);\n await waitForReplayRender();\n };\n\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n const { done, value } = await reader.read();\n\n if (done) {\n await finishReplay();\n controller.close();\n return;\n }\n\n if (replayFinished) {\n controller.enqueue(value);\n return;\n }\n\n const nextBytesForwarded = bytesForwarded + value.byteLength;\n\n if (nextBytesForwarded < replayContentLength) {\n bytesForwarded = nextBytesForwarded;\n controller.enqueue(value);\n return;\n }\n\n if (nextBytesForwarded === replayContentLength) {\n controller.enqueue(value);\n await finishReplay();\n return;\n }\n\n const replayBytesInChunk = replayContentLength - bytesForwarded;\n\n controller.enqueue(value.subarray(0, replayBytesInChunk));\n await finishReplay();\n controller.enqueue(value.subarray(replayBytesInChunk));\n },\n async cancel(reason) {\n const wasFinished = replayFinished;\n replayFinished = true;\n if (!wasFinished) setReplaying(false);\n await reader.cancel(reason);\n },\n });\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"replayBoundaryStream.js","names":["c","_c","useCallback","useEffect","useRef","useState","REPLAY_CONTENT_LENGTH_HEADER","ReplayBoundaryStreamOptions","setReplaying","value","waitForRender","Promise","useReplayRenderWait","$","renderTicket","setRenderTicket","mountedRef","nextTicketRef","t0","Symbol","for","waitersRef","t1","committedTicket","pendingWaiters","waiter","current","undefined","ticket","resolve","push","resolveWaiters","t2","t3","t4","t5","t6","setTimeout","parseReplayContentLength","headers","Headers","raw","get","boundary","Number","isSafeInteger","createReplayBoundaryStream","response","Response","waitForReplayRender","ReadableStream","Uint8Array","body","replayContentLength","reader","getReader","bytesForwarded","replayFinished","finishReplay","pull","controller","done","read","close","enqueue","nextBytesForwarded","byteLength","replayBytesInChunk","subarray","cancel","reason","wasFinished"],"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport const REPLAY_CONTENT_LENGTH_HEADER = \"Aui-Replay-Content-Length\";\n\ntype ReplayBoundaryStreamOptions = {\n setReplaying: (value: boolean) => void;\n waitForRender: () => Promise<void>;\n};\n\nexport const useReplayRenderWait = () => {\n const [renderTicket, setRenderTicket] = useState(0);\n const mountedRef = useRef(true);\n const nextTicketRef = useRef(0);\n const waitersRef = useRef<Array<{ ticket: number; resolve: () => void }>>([]);\n\n const resolveWaiters = useCallback((committedTicket?: number) => {\n const pendingWaiters = [];\n\n for (const waiter of waitersRef.current) {\n if (committedTicket === undefined || waiter.ticket <= committedTicket) {\n waiter.resolve();\n } else {\n pendingWaiters.push(waiter);\n }\n }\n\n waitersRef.current = pendingWaiters;\n }, []);\n\n useEffect(() => {\n mountedRef.current = true;\n resolveWaiters(renderTicket);\n }, [renderTicket, resolveWaiters]);\n\n useEffect(\n () => () => {\n mountedRef.current = false;\n resolveWaiters();\n },\n [resolveWaiters],\n );\n\n return useCallback(\n () =>\n new Promise<void>((resolve) => {\n setTimeout(() => {\n if (!mountedRef.current) {\n resolve();\n return;\n }\n\n const ticket = nextTicketRef.current + 1;\n nextTicketRef.current = ticket;\n waitersRef.current.push({ ticket, resolve });\n setRenderTicket(ticket);\n }, 0);\n }),\n [],\n );\n};\n\nconst parseReplayContentLength = (headers: Headers): number => {\n const raw = headers.get(REPLAY_CONTENT_LENGTH_HEADER);\n if (raw == null) return 0;\n\n const boundary = Number(raw);\n return Number.isSafeInteger(boundary) && boundary > 0 ? boundary : 0;\n};\n\n// Gates replay bytes until isReplaying:true renders, then releases live bytes after isReplaying:false renders.\nexport const createReplayBoundaryStream = async (\n response: Response,\n {\n setReplaying,\n waitForRender: waitForReplayRender,\n }: ReplayBoundaryStreamOptions,\n): Promise<ReadableStream<Uint8Array>> => {\n const body = response.body as ReadableStream<Uint8Array>;\n const replayContentLength = parseReplayContentLength(response.headers);\n\n if (replayContentLength <= 0) {\n return body;\n }\n\n setReplaying(true);\n await waitForReplayRender();\n\n const reader = body.getReader();\n let bytesForwarded = 0;\n let replayFinished = false;\n\n const finishReplay = async () => {\n if (replayFinished) return;\n replayFinished = true;\n\n // Let replay bytes drain before rendering live mode, then render live mode before releasing live bytes.\n await waitForReplayRender();\n setReplaying(false);\n await waitForReplayRender();\n };\n\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n const { done, value } = await reader.read();\n\n if (done) {\n await finishReplay();\n controller.close();\n return;\n }\n\n if (replayFinished) {\n controller.enqueue(value);\n return;\n }\n\n const nextBytesForwarded = bytesForwarded + value.byteLength;\n\n if (nextBytesForwarded < replayContentLength) {\n bytesForwarded = nextBytesForwarded;\n controller.enqueue(value);\n return;\n }\n\n if (nextBytesForwarded === replayContentLength) {\n controller.enqueue(value);\n await finishReplay();\n return;\n }\n\n const replayBytesInChunk = replayContentLength - bytesForwarded;\n\n controller.enqueue(value.subarray(0, replayBytesInChunk));\n await finishReplay();\n controller.enqueue(value.subarray(replayBytesInChunk));\n },\n async cancel(reason) {\n const wasFinished = replayFinished;\n replayFinished = true;\n if (!wasFinished) setReplaying(false);\n await reader.cancel(reason);\n },\n });\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runManager.js","names":[],"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/runManager.ts"],"sourcesContent":["import { useCallback, useRef, useState } from \"react\";\nimport { useLatestRef } from \"./useLatestRef\";\n\nexport type RunManager = Readonly<{\n isRunning: boolean;\n schedule: () => void;\n cancel: () => void;\n}>;\n\nexport function useRunManager(config: {\n onRun: (signal: AbortSignal) => Promise<void>;\n onFinish?: (() => void) | undefined;\n onCancel?: (() => void) | undefined;\n onError?: ((error: Error) => void | Promise<void>) | undefined;\n}): RunManager {\n const [isRunning, setIsRunning] = useState(false);\n const stateRef = useRef({\n pending: false,\n abortController: null as AbortController | null,\n });\n const onRunRef = useLatestRef(config.onRun);\n const onFinishRef = useLatestRef(config.onFinish);\n const onCancelRef = useLatestRef(config.onCancel);\n const onErrorRef = useLatestRef(config.onError);\n\n const startRun = useCallback(() => {\n setIsRunning(true);\n stateRef.current.pending = false;\n const ac = new AbortController();\n stateRef.current.abortController = ac;\n\n queueMicrotask(async () => {\n try {\n await onRunRef.current(ac.signal);\n } catch (error) {\n stateRef.current.pending = false;\n if (ac.signal.aborted) {\n onCancelRef.current?.();\n } else {\n await onErrorRef.current?.(error as Error);\n }\n } finally {\n onFinishRef.current?.();\n if (stateRef.current.pending) {\n startRun();\n } else {\n setIsRunning(false);\n stateRef.current.abortController = null;\n }\n }\n });\n }, [onRunRef, onFinishRef, onErrorRef, onCancelRef]);\n\n const schedule = useCallback(() => {\n if (stateRef.current.abortController) {\n // Coalesce multiple schedules while running into a single follow-up run.\n stateRef.current.pending = true;\n return;\n }\n startRun();\n }, [startRun]);\n\n const cancel = useCallback(() => {\n stateRef.current.pending = false;\n stateRef.current.abortController?.abort();\n }, []);\n\n return {\n isRunning,\n schedule,\n cancel,\n };\n}\n"],"mappings":";;;AASA,
|
|
1
|
+
{"version":3,"file":"runManager.js","names":["useCallback","useRef","useState","useLatestRef","RunManager","Readonly","isRunning","schedule","cancel","useRunManager","config","onRun","signal","AbortSignal","Promise","onFinish","onCancel","onError","error","Error","setIsRunning","stateRef","pending","abortController","AbortController","onRunRef","onFinishRef","onCancelRef","onErrorRef","startRun","current","ac","queueMicrotask","aborted","abort"],"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/runManager.ts"],"sourcesContent":["import { useCallback, useRef, useState } from \"react\";\nimport { useLatestRef } from \"./useLatestRef\";\n\nexport type RunManager = Readonly<{\n isRunning: boolean;\n schedule: () => void;\n cancel: () => void;\n}>;\n\nexport function useRunManager(config: {\n onRun: (signal: AbortSignal) => Promise<void>;\n onFinish?: (() => void) | undefined;\n onCancel?: (() => void) | undefined;\n onError?: ((error: Error) => void | Promise<void>) | undefined;\n}): RunManager {\n const [isRunning, setIsRunning] = useState(false);\n const stateRef = useRef({\n pending: false,\n abortController: null as AbortController | null,\n });\n const onRunRef = useLatestRef(config.onRun);\n const onFinishRef = useLatestRef(config.onFinish);\n const onCancelRef = useLatestRef(config.onCancel);\n const onErrorRef = useLatestRef(config.onError);\n\n const startRun = useCallback(() => {\n setIsRunning(true);\n stateRef.current.pending = false;\n const ac = new AbortController();\n stateRef.current.abortController = ac;\n\n queueMicrotask(async () => {\n try {\n await onRunRef.current(ac.signal);\n } catch (error) {\n stateRef.current.pending = false;\n if (ac.signal.aborted) {\n onCancelRef.current?.();\n } else {\n await onErrorRef.current?.(error as Error);\n }\n } finally {\n onFinishRef.current?.();\n if (stateRef.current.pending) {\n startRun();\n } else {\n setIsRunning(false);\n stateRef.current.abortController = null;\n }\n }\n });\n }, [onRunRef, onFinishRef, onErrorRef, onCancelRef]);\n\n const schedule = useCallback(() => {\n if (stateRef.current.abortController) {\n // Coalesce multiple schedules while running into a single follow-up run.\n stateRef.current.pending = true;\n return;\n }\n startRun();\n }, [startRun]);\n\n const cancel = useCallback(() => {\n stateRef.current.pending = false;\n stateRef.current.abortController?.abort();\n }, []);\n\n return {\n isRunning,\n schedule,\n cancel,\n };\n}\n"],"mappings":";;;AASA,SAAgBS,cAAcC,QAKf;CACb,MAAM,CAACJ,WAAWc,gBAAgBlB,SAAS,KAAK;CAChD,MAAMmB,WAAWpB,OAAO;EACtBqB,SAAS;EACTC,iBAAiB;CACnB,CAAC;CACD,MAAME,WAAWtB,aAAaO,OAAOC,KAAK;CAC1C,MAAMe,cAAcvB,aAAaO,OAAOK,QAAQ;CAChD,MAAMY,cAAcxB,aAAaO,OAAOM,QAAQ;CAChD,MAAMY,aAAazB,aAAaO,OAAOO,OAAO;CAE9C,MAAMY,WAAW7B,kBAAkB;EACjCoB,aAAa,IAAI;EACjBC,SAASS,QAAQR,UAAU;EAC3B,MAAMS,KAAK,IAAIP,gBAAgB;EAC/BH,SAASS,QAAQP,kBAAkBQ;EAEnCC,eAAe,YAAY;GACzB,IAAI;IACF,MAAMP,SAASK,QAAQC,GAAGnB,MAAM;GAClC,SAASM,OAAO;IACdG,SAASS,QAAQR,UAAU;IAC3B,IAAIS,GAAGnB,OAAOqB,SACZN,YAAYG,UAAU;SAEtB,MAAMF,WAAWE,UAAUZ,KAAc;GAE7C,UAAU;IACRQ,YAAYI,UAAU;IACtB,IAAIT,SAASS,QAAQR,SACnBO,SAAS;SACJ;KACLT,aAAa,KAAK;KAClBC,SAASS,QAAQP,kBAAkB;IACrC;GACF;EACF,CAAC;CACH,GAAG;EAACE;EAAUC;EAAaE;EAAYD;CAAW,CAAC;CAgBnD,OAAO;EACLrB;EACAC,UAhBeP,kBAAkB;GACjC,IAAIqB,SAASS,QAAQP,iBAAiB;IAEpCF,SAASS,QAAQR,UAAU;IAC3B;GACF;GACAO,SAAS;EACX,GAAG,CAACA,QAAQ,CASVtB;EACAC,QARaR,kBAAkB;GAC/BqB,SAASS,QAAQR,UAAU;GAC3BD,SAASS,QAAQP,iBAAiBW,MAAM;EAC1C,GAAG,CAAA,CAKD1B;CACF;AACF"}
|
package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js
CHANGED
|
@@ -6,6 +6,7 @@ import { createReplayBoundaryStream, useReplayRenderWait } from "./replayBoundar
|
|
|
6
6
|
import { useRunManager } from "./runManager.js";
|
|
7
7
|
import { useConvertedState } from "./useConvertedState.js";
|
|
8
8
|
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
9
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
9
10
|
import { InMemoryThreadListAdapter, createRequestHeaders } from "@assistant-ui/core";
|
|
10
11
|
import { asAsyncIterableStream } from "assistant-stream/utils";
|
|
11
12
|
import { useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
|
|
@@ -39,11 +40,18 @@ const asAssistantTransportExtras = (extras) => {
|
|
|
39
40
|
return extras;
|
|
40
41
|
};
|
|
41
42
|
const useAssistantTransportSendCommand = () => {
|
|
43
|
+
const $ = c(2);
|
|
42
44
|
const aui = useAui();
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
let t0;
|
|
46
|
+
if ($[0] !== aui) {
|
|
47
|
+
t0 = (command) => {
|
|
48
|
+
const extras = aui.thread().getState().extras;
|
|
49
|
+
asAssistantTransportExtras(extras).sendCommand(command);
|
|
50
|
+
};
|
|
51
|
+
$[0] = aui;
|
|
52
|
+
$[1] = t0;
|
|
53
|
+
} else t0 = $[1];
|
|
54
|
+
return t0;
|
|
47
55
|
};
|
|
48
56
|
function useAssistantTransportState(selector = (t) => t) {
|
|
49
57
|
return useAuiState((s) => selector(asAssistantTransportExtras(s.thread.extras).state));
|
|
@@ -128,13 +136,13 @@ const useAssistantTransportThreadRuntime = (options) => {
|
|
|
128
136
|
}
|
|
129
137
|
});
|
|
130
138
|
},
|
|
131
|
-
onError: async (
|
|
139
|
+
onError: async (error_0) => {
|
|
132
140
|
setIsReplaying(false);
|
|
133
141
|
const inTransitCmds = [...commandQueue.state.inTransit];
|
|
134
142
|
const queuedCmds = [...commandQueue.state.queued];
|
|
135
143
|
commandQueue.reset();
|
|
136
144
|
try {
|
|
137
|
-
await options.onError?.(
|
|
145
|
+
await options.onError?.(error_0, {
|
|
138
146
|
commands: inTransitCmds,
|
|
139
147
|
updateState: (updater) => {
|
|
140
148
|
agentStateRef.current = updater(agentStateRef.current);
|
|
@@ -148,7 +156,7 @@ const useAssistantTransportThreadRuntime = (options) => {
|
|
|
148
156
|
agentStateRef.current = updater(agentStateRef.current);
|
|
149
157
|
rerender((prev) => prev + 1);
|
|
150
158
|
},
|
|
151
|
-
error
|
|
159
|
+
error: error_0
|
|
152
160
|
});
|
|
153
161
|
}
|
|
154
162
|
}
|
|
@@ -173,13 +181,13 @@ const useAssistantTransportThreadRuntime = (options) => {
|
|
|
173
181
|
},
|
|
174
182
|
onNew: async (message) => {
|
|
175
183
|
parentIdRef.current = message.parentId;
|
|
176
|
-
const
|
|
177
|
-
commandQueue.enqueue(
|
|
184
|
+
const command_0 = convertAppendMessageToCommand(message);
|
|
185
|
+
commandQueue.enqueue(command_0);
|
|
178
186
|
},
|
|
179
|
-
...options.capabilities?.edit && { onEdit: async (
|
|
180
|
-
parentIdRef.current =
|
|
181
|
-
const
|
|
182
|
-
commandQueue.enqueue(
|
|
187
|
+
...options.capabilities?.edit && { onEdit: async (message_0) => {
|
|
188
|
+
parentIdRef.current = message_0.parentId;
|
|
189
|
+
const command_1 = convertAppendMessageToCommand(message_0);
|
|
190
|
+
commandQueue.enqueue(command_1);
|
|
183
191
|
} },
|
|
184
192
|
onCancel: async () => {
|
|
185
193
|
runManager.cancel();
|
|
@@ -190,7 +198,7 @@ const useAssistantTransportThreadRuntime = (options) => {
|
|
|
190
198
|
runManager.schedule();
|
|
191
199
|
},
|
|
192
200
|
onAddToolResult: async (toolOptions) => {
|
|
193
|
-
const
|
|
201
|
+
const command_2 = {
|
|
194
202
|
type: "add-tool-result",
|
|
195
203
|
toolCallId: toolOptions.toolCallId,
|
|
196
204
|
result: toolOptions.result,
|
|
@@ -199,11 +207,11 @@ const useAssistantTransportThreadRuntime = (options) => {
|
|
|
199
207
|
...toolOptions.artifact && { artifact: toolOptions.artifact },
|
|
200
208
|
...toolOptions.modelContent !== void 0 && { modelContent: toolOptions.modelContent }
|
|
201
209
|
};
|
|
202
|
-
commandQueue.enqueue(
|
|
210
|
+
commandQueue.enqueue(command_2);
|
|
203
211
|
},
|
|
204
212
|
onLoadExternalState: async (state) => {
|
|
205
213
|
agentStateRef.current = state;
|
|
206
|
-
rerender((
|
|
214
|
+
rerender((prev_0) => prev_0 + 1);
|
|
207
215
|
}
|
|
208
216
|
});
|
|
209
217
|
return runtime;
|
package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssistantTransportRuntime.js","names":["createInitialMessage"],"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport type { AppendMessage } from \"@assistant-ui/core\";\nimport {\n type ReadonlyJSONObject,\n type ReadonlyJSONValue,\n asAsyncIterableStream,\n} from \"assistant-stream/utils\";\nimport { useExternalStoreRuntime } from \"../external-store/useExternalStoreRuntime\";\nimport type { AssistantRuntime } from \"../../runtime/AssistantRuntime\";\nimport type { AddToolResultOptions } from \"@assistant-ui/core\";\nimport { useMemo, useRef, useState } from \"react\";\nimport {\n AssistantMessageAccumulator,\n DataStreamDecoder,\n AssistantTransportDecoder,\n unstable_createInitialMessage as createInitialMessage,\n toToolsJSONSchema,\n} from \"assistant-stream\";\nimport type {\n AssistantTransportOptions,\n AddMessageCommand,\n AddToolResultCommand,\n UserMessagePart,\n QueuedCommand,\n AssistantTransportCommand,\n SendCommandsRequestBody,\n} from \"./types\";\nimport { useCommandQueue } from \"./commandQueue\";\nimport {\n createReplayBoundaryStream,\n useReplayRenderWait,\n} from \"./replayBoundaryStream\";\nimport { useRunManager } from \"./runManager\";\nimport { useConvertedState } from \"./useConvertedState\";\nimport type { ToolExecutionStatus } from \"@assistant-ui/core\";\nimport { createRequestHeaders } from \"@assistant-ui/core\";\nimport { useRemoteThreadListRuntime } from \"../remote-thread-list/useRemoteThreadListRuntime\";\nimport { InMemoryThreadListAdapter } from \"@assistant-ui/core\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport type { UserExternalState } from \"../../../augmentations\";\n\nconst convertAppendMessageToCommand = (\n message: AppendMessage,\n): AddMessageCommand => {\n if (message.role !== \"user\")\n throw new Error(\"Only user messages are supported\");\n\n const parts: UserMessagePart[] = [];\n const content = [\n ...message.content,\n ...(message.attachments?.flatMap((a) => a.content) ?? []),\n ];\n for (const contentPart of content) {\n if (contentPart.type === \"text\") {\n parts.push({ type: \"text\", text: contentPart.text });\n } else if (contentPart.type === \"image\") {\n parts.push({ type: \"image\", image: contentPart.image });\n }\n }\n\n return {\n type: \"add-message\",\n message: {\n role: \"user\",\n parts,\n },\n parentId: message.parentId,\n sourceId: message.sourceId,\n };\n};\n\nconst symbolAssistantTransportExtras = Symbol(\"assistant-transport-extras\");\ntype AssistantTransportExtras = {\n [symbolAssistantTransportExtras]: true;\n sendCommand: (command: AssistantTransportCommand) => void;\n state: UserExternalState;\n};\n\nconst asAssistantTransportExtras = (\n extras: unknown,\n): AssistantTransportExtras => {\n if (\n typeof extras !== \"object\" ||\n extras == null ||\n !(symbolAssistantTransportExtras in extras)\n )\n throw new Error(\n \"This method can only be called when you are using useAssistantTransportRuntime\",\n );\n\n return extras as AssistantTransportExtras;\n};\n\nexport const useAssistantTransportSendCommand = () => {\n const aui = useAui();\n\n return (command: AssistantTransportCommand) => {\n const extras = aui.thread().getState().extras;\n const transportExtras = asAssistantTransportExtras(extras);\n transportExtras.sendCommand(command);\n };\n};\n\nexport function useAssistantTransportState(): UserExternalState;\nexport function useAssistantTransportState<T>(\n selector: (state: UserExternalState) => T,\n): T;\nexport function useAssistantTransportState<T>(\n selector: (state: UserExternalState) => T = (t) => t as T,\n): T | UserExternalState {\n return useAuiState((s) =>\n selector(asAssistantTransportExtras(s.thread.extras).state),\n );\n}\n\nconst useAssistantTransportThreadRuntime = <T>(\n options: AssistantTransportOptions<T>,\n): AssistantRuntime => {\n const agentStateRef = useRef(options.initialState);\n const [, rerender] = useState(0);\n const resumeFlagRef = useRef(false);\n const [isReplaying, setIsReplaying] = useState(false);\n const waitForReplayRender = useReplayRenderWait();\n const parentIdRef = useRef<string | null | undefined>(undefined);\n const commandQueue = useCommandQueue({\n onQueue: () => runManager.schedule(),\n });\n\n const threadId = useAuiState((s) => s.threadListItem.remoteId);\n\n const runManager = useRunManager({\n onRun: async (signal: AbortSignal) => {\n const isResume = resumeFlagRef.current;\n resumeFlagRef.current = false;\n setIsReplaying(false);\n const commands: QueuedCommand[] = isResume ? [] : commandQueue.flush();\n if (commands.length === 0 && !isResume)\n throw new Error(\"No commands to send\");\n\n const headers = await createRequestHeaders(options.headers);\n const bodyValue =\n typeof options.body === \"function\"\n ? await options.body()\n : options.body;\n const context = runtime.thread.getModelContext();\n\n let requestBody: Record<string, unknown> = {\n commands,\n state: agentStateRef.current,\n system: context.system,\n tools: context.tools ? toToolsJSONSchema(context.tools) : undefined,\n threadId,\n ...(parentIdRef.current !== undefined && {\n parentId: parentIdRef.current,\n }),\n // nested (new format, aligned with AssistantChatTransport)\n callSettings: context.callSettings,\n config: context.config,\n // @deprecated spread at top level — use nested `callSettings`/`config` instead. Will be removed in a future version.\n ...context.callSettings,\n ...context.config,\n ...(bodyValue ?? {}),\n };\n\n if (options.prepareSendCommandsRequest) {\n requestBody = await options.prepareSendCommandsRequest(\n requestBody as SendCommandsRequestBody,\n );\n }\n\n const response = await fetch(\n isResume ? options.resumeApi! : options.api,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(requestBody),\n signal,\n },\n );\n\n options.onResponse?.(response);\n\n if (!response.ok) {\n throw new Error(`Status ${response.status}: ${await response.text()}`);\n }\n\n if (!response.body) {\n throw new Error(\"Response body is null\");\n }\n\n const body = await createReplayBoundaryStream(response, {\n setReplaying: setIsReplaying,\n waitForRender: waitForReplayRender,\n });\n\n // Select decoder based on protocol option\n const protocol = options.protocol ?? \"data-stream\";\n const decoder =\n protocol === \"assistant-transport\"\n ? new AssistantTransportDecoder()\n : new DataStreamDecoder();\n\n let err: string | undefined;\n const stream = body.pipeThrough(decoder).pipeThrough(\n new AssistantMessageAccumulator({\n initialMessage: createInitialMessage({\n unstable_state:\n (agentStateRef.current as ReadonlyJSONValue) ?? null,\n }),\n throttle: isResume,\n onError: (error) => {\n err = error;\n },\n }),\n );\n\n let markedDelivered = false;\n\n for await (const chunk of asAsyncIterableStream(stream)) {\n if (chunk.metadata.unstable_state === agentStateRef.current) continue;\n\n if (!markedDelivered) {\n commandQueue.markDelivered();\n markedDelivered = true;\n }\n\n agentStateRef.current = chunk.metadata.unstable_state as T;\n rerender((prev) => prev + 1);\n }\n\n if (err) {\n throw new Error(err);\n }\n },\n onFinish: options.onFinish,\n onCancel: () => {\n setIsReplaying(false);\n const cmds = [\n ...commandQueue.state.inTransit,\n ...commandQueue.state.queued,\n ];\n\n commandQueue.reset();\n\n options.onCancel?.({\n commands: cmds,\n updateState: (updater) => {\n agentStateRef.current = updater(agentStateRef.current);\n rerender((prev) => prev + 1);\n },\n });\n },\n onError: async (error) => {\n setIsReplaying(false);\n const inTransitCmds = [...commandQueue.state.inTransit];\n const queuedCmds = [...commandQueue.state.queued];\n\n commandQueue.reset();\n\n try {\n await options.onError?.(error as Error, {\n commands: inTransitCmds,\n updateState: (updater) => {\n agentStateRef.current = updater(agentStateRef.current);\n rerender((prev) => prev + 1);\n },\n });\n } finally {\n options.onCancel?.({\n commands: queuedCmds,\n updateState: (updater) => {\n agentStateRef.current = updater(agentStateRef.current);\n rerender((prev) => prev + 1);\n },\n error: error as Error,\n });\n }\n },\n });\n\n // Tool execution status state\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n\n // Reactive conversion of agent state + connection metadata → UI state\n const pendingCommands = useMemo(\n () => [...commandQueue.state.inTransit, ...commandQueue.state.queued],\n [commandQueue.state],\n );\n const converted = useConvertedState(\n options.converter,\n agentStateRef.current,\n pendingCommands,\n runManager.isRunning,\n toolStatuses,\n );\n\n // Create runtime\n const runtime = useExternalStoreRuntime({\n messages: converted.messages,\n state: converted.state,\n isRunning: converted.isRunning,\n isLoading: isReplaying,\n adapters: options.adapters,\n unstable_enableToolInvocations: true,\n setToolStatuses,\n extras: {\n [symbolAssistantTransportExtras]: true,\n sendCommand: (command: AssistantTransportCommand) => {\n commandQueue.enqueue(command);\n },\n state: agentStateRef.current as UserExternalState,\n } satisfies AssistantTransportExtras,\n onNew: async (message: AppendMessage): Promise<void> => {\n parentIdRef.current = message.parentId;\n const command = convertAppendMessageToCommand(message);\n commandQueue.enqueue(command);\n },\n ...(options.capabilities?.edit && {\n onEdit: async (message: AppendMessage): Promise<void> => {\n parentIdRef.current = message.parentId;\n const command = convertAppendMessageToCommand(message);\n commandQueue.enqueue(command);\n },\n }),\n onCancel: async () => {\n runManager.cancel();\n },\n onResume: async () => {\n if (!options.resumeApi)\n throw new Error(\"Must pass resumeApi to options to resume runs\");\n\n resumeFlagRef.current = true;\n runManager.schedule();\n },\n onAddToolResult: async (\n toolOptions: AddToolResultOptions,\n ): Promise<void> => {\n const command: AddToolResultCommand = {\n type: \"add-tool-result\",\n toolCallId: toolOptions.toolCallId,\n result: toolOptions.result as ReadonlyJSONObject,\n toolName: toolOptions.toolName,\n isError: toolOptions.isError,\n ...(toolOptions.artifact && { artifact: toolOptions.artifact }),\n ...(toolOptions.modelContent !== undefined && {\n modelContent: toolOptions.modelContent,\n }),\n };\n\n commandQueue.enqueue(command);\n },\n onLoadExternalState: async (state) => {\n agentStateRef.current = state as T;\n rerender((prev) => prev + 1);\n },\n });\n\n return runtime;\n};\n\n/**\n * @alpha This is an experimental API that is subject to change.\n */\nexport const useAssistantTransportRuntime = <T>(\n options: AssistantTransportOptions<T>,\n): AssistantRuntime => {\n const runtime = useRemoteThreadListRuntime({\n runtimeHook: function RuntimeHook() {\n return useAssistantTransportThreadRuntime(options);\n },\n adapter: new InMemoryThreadListAdapter(),\n allowNesting: true,\n });\n return runtime;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAssistantTransportRuntime.js","names":["c","_c","AppendMessage","ReadonlyJSONObject","ReadonlyJSONValue","asAsyncIterableStream","useExternalStoreRuntime","AssistantRuntime","AddToolResultOptions","useMemo","useRef","useState","AssistantMessageAccumulator","DataStreamDecoder","AssistantTransportDecoder","unstable_createInitialMessage","createInitialMessage","toToolsJSONSchema","AssistantTransportOptions","AddMessageCommand","AddToolResultCommand","UserMessagePart","QueuedCommand","AssistantTransportCommand","SendCommandsRequestBody","useCommandQueue","createReplayBoundaryStream","useReplayRenderWait","useRunManager","useConvertedState","ToolExecutionStatus","createRequestHeaders","useRemoteThreadListRuntime","InMemoryThreadListAdapter","useAui","useAuiState","UserExternalState","convertAppendMessageToCommand","message","role","Error","parts","content","attachments","flatMap","a","contentPart","type","push","text","image","parentId","sourceId","symbolAssistantTransportExtras","Symbol","AssistantTransportExtras","sendCommand","command","state","asAssistantTransportExtras","extras","useAssistantTransportSendCommand","$","aui","t0","thread","getState","transportExtras","useAssistantTransportState","selector","T","t","s","useAssistantTransportThreadRuntime","options","agentStateRef","initialState","rerender","resumeFlagRef","isReplaying","setIsReplaying","waitForReplayRender","parentIdRef","undefined","commandQueue","onQueue","runManager","schedule","threadId","threadListItem","remoteId","onRun","signal","AbortSignal","isResume","current","commands","flush","length","headers","bodyValue","body","context","runtime","getModelContext","requestBody","Record","system","tools","callSettings","config","prepareSendCommandsRequest","response","fetch","resumeApi","api","method","JSON","stringify","onResponse","ok","status","setReplaying","waitForRender","protocol","decoder","err","stream","pipeThrough","initialMessage","unstable_state","throttle","onError","error","markedDelivered","chunk","metadata","markDelivered","prev","onFinish","onCancel","cmds","inTransit","queued","reset","updateState","updater","inTransitCmds","queuedCmds","toolStatuses","setToolStatuses","pendingCommands","converted","converter","isRunning","messages","isLoading","adapters","unstable_enableToolInvocations","enqueue","onNew","Promise","capabilities","edit","onEdit","cancel","onResume","onAddToolResult","toolOptions","toolCallId","result","toolName","isError","artifact","modelContent","onLoadExternalState","useAssistantTransportRuntime","runtimeHook","RuntimeHook","adapter","allowNesting"],"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport type { AppendMessage } from \"@assistant-ui/core\";\nimport {\n type ReadonlyJSONObject,\n type ReadonlyJSONValue,\n asAsyncIterableStream,\n} from \"assistant-stream/utils\";\nimport { useExternalStoreRuntime } from \"../external-store/useExternalStoreRuntime\";\nimport type { AssistantRuntime } from \"../../runtime/AssistantRuntime\";\nimport type { AddToolResultOptions } from \"@assistant-ui/core\";\nimport { useMemo, useRef, useState } from \"react\";\nimport {\n AssistantMessageAccumulator,\n DataStreamDecoder,\n AssistantTransportDecoder,\n unstable_createInitialMessage as createInitialMessage,\n toToolsJSONSchema,\n} from \"assistant-stream\";\nimport type {\n AssistantTransportOptions,\n AddMessageCommand,\n AddToolResultCommand,\n UserMessagePart,\n QueuedCommand,\n AssistantTransportCommand,\n SendCommandsRequestBody,\n} from \"./types\";\nimport { useCommandQueue } from \"./commandQueue\";\nimport {\n createReplayBoundaryStream,\n useReplayRenderWait,\n} from \"./replayBoundaryStream\";\nimport { useRunManager } from \"./runManager\";\nimport { useConvertedState } from \"./useConvertedState\";\nimport type { ToolExecutionStatus } from \"@assistant-ui/core\";\nimport { createRequestHeaders } from \"@assistant-ui/core\";\nimport { useRemoteThreadListRuntime } from \"../remote-thread-list/useRemoteThreadListRuntime\";\nimport { InMemoryThreadListAdapter } from \"@assistant-ui/core\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport type { UserExternalState } from \"../../../augmentations\";\n\nconst convertAppendMessageToCommand = (\n message: AppendMessage,\n): AddMessageCommand => {\n if (message.role !== \"user\")\n throw new Error(\"Only user messages are supported\");\n\n const parts: UserMessagePart[] = [];\n const content = [\n ...message.content,\n ...(message.attachments?.flatMap((a) => a.content) ?? []),\n ];\n for (const contentPart of content) {\n if (contentPart.type === \"text\") {\n parts.push({ type: \"text\", text: contentPart.text });\n } else if (contentPart.type === \"image\") {\n parts.push({ type: \"image\", image: contentPart.image });\n }\n }\n\n return {\n type: \"add-message\",\n message: {\n role: \"user\",\n parts,\n },\n parentId: message.parentId,\n sourceId: message.sourceId,\n };\n};\n\nconst symbolAssistantTransportExtras = Symbol(\"assistant-transport-extras\");\ntype AssistantTransportExtras = {\n [symbolAssistantTransportExtras]: true;\n sendCommand: (command: AssistantTransportCommand) => void;\n state: UserExternalState;\n};\n\nconst asAssistantTransportExtras = (\n extras: unknown,\n): AssistantTransportExtras => {\n if (\n typeof extras !== \"object\" ||\n extras == null ||\n !(symbolAssistantTransportExtras in extras)\n )\n throw new Error(\n \"This method can only be called when you are using useAssistantTransportRuntime\",\n );\n\n return extras as AssistantTransportExtras;\n};\n\nexport const useAssistantTransportSendCommand = () => {\n const aui = useAui();\n\n return (command: AssistantTransportCommand) => {\n const extras = aui.thread().getState().extras;\n const transportExtras = asAssistantTransportExtras(extras);\n transportExtras.sendCommand(command);\n };\n};\n\nexport function useAssistantTransportState(): UserExternalState;\nexport function useAssistantTransportState<T>(\n selector: (state: UserExternalState) => T,\n): T;\nexport function useAssistantTransportState<T>(\n selector: (state: UserExternalState) => T = (t) => t as T,\n): T | UserExternalState {\n return useAuiState((s) =>\n selector(asAssistantTransportExtras(s.thread.extras).state),\n );\n}\n\nconst useAssistantTransportThreadRuntime = <T>(\n options: AssistantTransportOptions<T>,\n): AssistantRuntime => {\n const agentStateRef = useRef(options.initialState);\n const [, rerender] = useState(0);\n const resumeFlagRef = useRef(false);\n const [isReplaying, setIsReplaying] = useState(false);\n const waitForReplayRender = useReplayRenderWait();\n const parentIdRef = useRef<string | null | undefined>(undefined);\n const commandQueue = useCommandQueue({\n onQueue: () => runManager.schedule(),\n });\n\n const threadId = useAuiState((s) => s.threadListItem.remoteId);\n\n const runManager = useRunManager({\n onRun: async (signal: AbortSignal) => {\n const isResume = resumeFlagRef.current;\n resumeFlagRef.current = false;\n setIsReplaying(false);\n const commands: QueuedCommand[] = isResume ? [] : commandQueue.flush();\n if (commands.length === 0 && !isResume)\n throw new Error(\"No commands to send\");\n\n const headers = await createRequestHeaders(options.headers);\n const bodyValue =\n typeof options.body === \"function\"\n ? await options.body()\n : options.body;\n const context = runtime.thread.getModelContext();\n\n let requestBody: Record<string, unknown> = {\n commands,\n state: agentStateRef.current,\n system: context.system,\n tools: context.tools ? toToolsJSONSchema(context.tools) : undefined,\n threadId,\n ...(parentIdRef.current !== undefined && {\n parentId: parentIdRef.current,\n }),\n // nested (new format, aligned with AssistantChatTransport)\n callSettings: context.callSettings,\n config: context.config,\n // @deprecated spread at top level — use nested `callSettings`/`config` instead. Will be removed in a future version.\n ...context.callSettings,\n ...context.config,\n ...(bodyValue ?? {}),\n };\n\n if (options.prepareSendCommandsRequest) {\n requestBody = await options.prepareSendCommandsRequest(\n requestBody as SendCommandsRequestBody,\n );\n }\n\n const response = await fetch(\n isResume ? options.resumeApi! : options.api,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(requestBody),\n signal,\n },\n );\n\n options.onResponse?.(response);\n\n if (!response.ok) {\n throw new Error(`Status ${response.status}: ${await response.text()}`);\n }\n\n if (!response.body) {\n throw new Error(\"Response body is null\");\n }\n\n const body = await createReplayBoundaryStream(response, {\n setReplaying: setIsReplaying,\n waitForRender: waitForReplayRender,\n });\n\n // Select decoder based on protocol option\n const protocol = options.protocol ?? \"data-stream\";\n const decoder =\n protocol === \"assistant-transport\"\n ? new AssistantTransportDecoder()\n : new DataStreamDecoder();\n\n let err: string | undefined;\n const stream = body.pipeThrough(decoder).pipeThrough(\n new AssistantMessageAccumulator({\n initialMessage: createInitialMessage({\n unstable_state:\n (agentStateRef.current as ReadonlyJSONValue) ?? null,\n }),\n throttle: isResume,\n onError: (error) => {\n err = error;\n },\n }),\n );\n\n let markedDelivered = false;\n\n for await (const chunk of asAsyncIterableStream(stream)) {\n if (chunk.metadata.unstable_state === agentStateRef.current) continue;\n\n if (!markedDelivered) {\n commandQueue.markDelivered();\n markedDelivered = true;\n }\n\n agentStateRef.current = chunk.metadata.unstable_state as T;\n rerender((prev) => prev + 1);\n }\n\n if (err) {\n throw new Error(err);\n }\n },\n onFinish: options.onFinish,\n onCancel: () => {\n setIsReplaying(false);\n const cmds = [\n ...commandQueue.state.inTransit,\n ...commandQueue.state.queued,\n ];\n\n commandQueue.reset();\n\n options.onCancel?.({\n commands: cmds,\n updateState: (updater) => {\n agentStateRef.current = updater(agentStateRef.current);\n rerender((prev) => prev + 1);\n },\n });\n },\n onError: async (error) => {\n setIsReplaying(false);\n const inTransitCmds = [...commandQueue.state.inTransit];\n const queuedCmds = [...commandQueue.state.queued];\n\n commandQueue.reset();\n\n try {\n await options.onError?.(error as Error, {\n commands: inTransitCmds,\n updateState: (updater) => {\n agentStateRef.current = updater(agentStateRef.current);\n rerender((prev) => prev + 1);\n },\n });\n } finally {\n options.onCancel?.({\n commands: queuedCmds,\n updateState: (updater) => {\n agentStateRef.current = updater(agentStateRef.current);\n rerender((prev) => prev + 1);\n },\n error: error as Error,\n });\n }\n },\n });\n\n // Tool execution status state\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n\n // Reactive conversion of agent state + connection metadata → UI state\n const pendingCommands = useMemo(\n () => [...commandQueue.state.inTransit, ...commandQueue.state.queued],\n [commandQueue.state],\n );\n const converted = useConvertedState(\n options.converter,\n agentStateRef.current,\n pendingCommands,\n runManager.isRunning,\n toolStatuses,\n );\n\n // Create runtime\n const runtime = useExternalStoreRuntime({\n messages: converted.messages,\n state: converted.state,\n isRunning: converted.isRunning,\n isLoading: isReplaying,\n adapters: options.adapters,\n unstable_enableToolInvocations: true,\n setToolStatuses,\n extras: {\n [symbolAssistantTransportExtras]: true,\n sendCommand: (command: AssistantTransportCommand) => {\n commandQueue.enqueue(command);\n },\n state: agentStateRef.current as UserExternalState,\n } satisfies AssistantTransportExtras,\n onNew: async (message: AppendMessage): Promise<void> => {\n parentIdRef.current = message.parentId;\n const command = convertAppendMessageToCommand(message);\n commandQueue.enqueue(command);\n },\n ...(options.capabilities?.edit && {\n onEdit: async (message: AppendMessage): Promise<void> => {\n parentIdRef.current = message.parentId;\n const command = convertAppendMessageToCommand(message);\n commandQueue.enqueue(command);\n },\n }),\n onCancel: async () => {\n runManager.cancel();\n },\n onResume: async () => {\n if (!options.resumeApi)\n throw new Error(\"Must pass resumeApi to options to resume runs\");\n\n resumeFlagRef.current = true;\n runManager.schedule();\n },\n onAddToolResult: async (\n toolOptions: AddToolResultOptions,\n ): Promise<void> => {\n const command: AddToolResultCommand = {\n type: \"add-tool-result\",\n toolCallId: toolOptions.toolCallId,\n result: toolOptions.result as ReadonlyJSONObject,\n toolName: toolOptions.toolName,\n isError: toolOptions.isError,\n ...(toolOptions.artifact && { artifact: toolOptions.artifact }),\n ...(toolOptions.modelContent !== undefined && {\n modelContent: toolOptions.modelContent,\n }),\n };\n\n commandQueue.enqueue(command);\n },\n onLoadExternalState: async (state) => {\n agentStateRef.current = state as T;\n rerender((prev) => prev + 1);\n },\n });\n\n return runtime;\n};\n\n/**\n * @alpha This is an experimental API that is subject to change.\n */\nexport const useAssistantTransportRuntime = <T>(\n options: AssistantTransportOptions<T>,\n): AssistantRuntime => {\n const runtime = useRemoteThreadListRuntime({\n runtimeHook: function RuntimeHook() {\n return useAssistantTransportThreadRuntime(options);\n },\n adapter: new InMemoryThreadListAdapter(),\n allowNesting: true,\n });\n return runtime;\n};\n"],"mappings":"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"}
|
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
2
2
|
//#region src/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.ts
|
|
3
3
|
function useConvertedState(converter, agentState, pendingCommands, isSending, toolStatuses) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
const $ = c(6);
|
|
5
|
+
let t0;
|
|
6
|
+
if ($[0] !== agentState || $[1] !== converter || $[2] !== isSending || $[3] !== pendingCommands || $[4] !== toolStatuses) {
|
|
7
|
+
t0 = converter(agentState, {
|
|
8
|
+
pendingCommands,
|
|
9
|
+
isSending,
|
|
10
|
+
toolStatuses
|
|
11
|
+
});
|
|
12
|
+
$[0] = agentState;
|
|
13
|
+
$[1] = converter;
|
|
14
|
+
$[2] = isSending;
|
|
15
|
+
$[3] = pendingCommands;
|
|
16
|
+
$[4] = toolStatuses;
|
|
17
|
+
$[5] = t0;
|
|
18
|
+
} else t0 = $[5];
|
|
19
|
+
return t0;
|
|
15
20
|
}
|
|
16
21
|
//#endregion
|
|
17
22
|
export { useConvertedState };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useConvertedState.js","names":[],"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport type {\n AssistantTransportCommand,\n AssistantTransportState,\n AssistantTransportStateConverter,\n} from \"./types\";\nimport type { ToolExecutionStatus } from \"@assistant-ui/core\";\n\nexport function useConvertedState<T>(\n converter: AssistantTransportStateConverter<T>,\n agentState: T,\n pendingCommands: AssistantTransportCommand[],\n isSending: boolean,\n toolStatuses: Record<string, ToolExecutionStatus>,\n): AssistantTransportState {\n return useMemo(\n () => converter(agentState, { pendingCommands, isSending, toolStatuses }),\n [converter, agentState, pendingCommands, isSending, toolStatuses],\n );\n}\n"],"mappings":";;AAQA,
|
|
1
|
+
{"version":3,"file":"useConvertedState.js","names":["useMemo","AssistantTransportCommand","AssistantTransportState","AssistantTransportStateConverter","ToolExecutionStatus","useConvertedState","converter","agentState","pendingCommands","isSending","toolStatuses","$","_c","t0"],"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport type {\n AssistantTransportCommand,\n AssistantTransportState,\n AssistantTransportStateConverter,\n} from \"./types\";\nimport type { ToolExecutionStatus } from \"@assistant-ui/core\";\n\nexport function useConvertedState<T>(\n converter: AssistantTransportStateConverter<T>,\n agentState: T,\n pendingCommands: AssistantTransportCommand[],\n isSending: boolean,\n toolStatuses: Record<string, ToolExecutionStatus>,\n): AssistantTransportState {\n return useMemo(\n () => converter(agentState, { pendingCommands, isSending, toolStatuses }),\n [converter, agentState, pendingCommands, isSending, toolStatuses],\n );\n}\n"],"mappings":";;AAQA,SAAOK,kBAAAC,WAAAC,YAAAC,iBAAAC,WAAAC,cAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAA,IAAAC;CAAA,IAAAF,EAAA,OAAAJ,cAAAI,EAAA,OAAAL,aAAAK,EAAA,OAAAF,aAAAE,EAAA,OAAAH,mBAAAG,EAAA,OAAAD,cAAA;EAQGG,KAAAP,UAAUC,YAAY;GAAAC;GAAAC;GAAAC;EAA2C,CAAC;EAACC,EAAA,KAAAJ;EAAAI,EAAA,KAAAL;EAAAK,EAAA,KAAAF;EAAAE,EAAA,KAAAH;EAAAG,EAAA,KAAAD;EAAAC,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAAA,OAAnEE;AAAmE"}
|
|
@@ -1,10 +1,24 @@
|
|
|
1
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
1
2
|
import { useEffect, useRef } from "@assistant-ui/tap/react-shim";
|
|
2
3
|
//#region src/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.ts
|
|
3
4
|
function useLatestRef(value) {
|
|
5
|
+
const $ = c(3);
|
|
4
6
|
const ref = useRef(value);
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
let t0;
|
|
8
|
+
let t1;
|
|
9
|
+
if ($[0] !== value) {
|
|
10
|
+
t0 = () => {
|
|
11
|
+
ref.current = value;
|
|
12
|
+
};
|
|
13
|
+
t1 = [value];
|
|
14
|
+
$[0] = value;
|
|
15
|
+
$[1] = t0;
|
|
16
|
+
$[2] = t1;
|
|
17
|
+
} else {
|
|
18
|
+
t0 = $[1];
|
|
19
|
+
t1 = $[2];
|
|
20
|
+
}
|
|
21
|
+
useEffect(t0, t1);
|
|
8
22
|
return ref;
|
|
9
23
|
}
|
|
10
24
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLatestRef.js","names":[],"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\n\nexport function useLatestRef<T>(value: T) {\n const ref = useRef(value);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref as { current: T };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"useLatestRef.js","names":["useEffect","useRef","useLatestRef","value","$","_c","ref","t0","t1","current","T"],"sources":["../../../../src/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\n\nexport function useLatestRef<T>(value: T) {\n const ref = useRef(value);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref as { current: T };\n}\n"],"mappings":";;;AAEA,SAAOE,aAAAC,OAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CACL,MAAAC,MAAYL,OAAOE,KAAK;CAAE,IAAAI;CAAA,IAAAC;CAAA,IAAAJ,EAAA,OAAAD,OAAA;EAChBI,WAAA;GACRD,IAAGG,UAAWN;EAAH;EACVK,KAAA,CAACL,KAAK;EAACC,EAAA,KAAAD;EAAAC,EAAA,KAAAG;EAAAH,EAAA,KAAAI;CAAA,OAAA;EAAAD,KAAAH,EAAA;EAAAI,KAAAJ,EAAA;CAAA;CAFVJ,UAAUO,IAEPC,EAAO;CAAC,OACJF;AAAqB"}
|
|
@@ -63,19 +63,19 @@ function InlineRenderer({ part, internalsRef, optionsRef }) {
|
|
|
63
63
|
}] });
|
|
64
64
|
return { ok: true };
|
|
65
65
|
},
|
|
66
|
-
callTool: (
|
|
67
|
-
readResource: (
|
|
68
|
-
listResources: (
|
|
66
|
+
callTool: (params_0) => internalsRef.current.host.callTool(params_0),
|
|
67
|
+
readResource: (params_1) => internalsRef.current.host.readResource(params_1),
|
|
68
|
+
listResources: (params_2) => internalsRef.current.host.listResources(params_2)
|
|
69
69
|
}), [aui, internalsRef]);
|
|
70
70
|
const loadedResourceForApp = loadedResource?.resourceUri === appForRender?.resourceUri ? loadedResource : void 0;
|
|
71
71
|
const appResource = loadedResourceForApp?.resource;
|
|
72
|
-
const
|
|
72
|
+
const error_0 = loadedResourceForApp?.error;
|
|
73
73
|
const fallback = opts.fallback ?? null;
|
|
74
74
|
if (appForRender == null) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
|
|
75
|
-
if (
|
|
75
|
+
if (error_0 != null) {
|
|
76
76
|
const errorFallback = opts.errorFallback;
|
|
77
77
|
if (errorFallback === void 0) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
|
|
78
|
-
if (typeof errorFallback === "function") return /* @__PURE__ */ jsx(Fragment, { children: errorFallback(
|
|
78
|
+
if (typeof errorFallback === "function") return /* @__PURE__ */ jsx(Fragment, { children: errorFallback(error_0) });
|
|
79
79
|
return /* @__PURE__ */ jsx(Fragment, { children: errorFallback });
|
|
80
80
|
}
|
|
81
81
|
if (appResource == null) return /* @__PURE__ */ jsx(Fragment, { children: opts.loadingFallback ?? fallback });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpAppRenderer.js","names":[],"sources":["../../src/mcp-apps/McpAppRenderer.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type MutableRefObject,\n type ReactNode,\n} from \"react\";\nimport type { McpAppMetadata } from \"@assistant-ui/core\";\nimport type {\n ToolCallMessagePartComponent,\n ToolCallMessagePartProps,\n} from \"@assistant-ui/core/react\";\nimport { useAui } from \"@assistant-ui/store\";\n\nimport { useResource, resource, type ResourceElement } from \"@assistant-ui/tap\";\nimport { McpAppFrame } from \"./app-frame\";\nimport type {\n McpAppBridgeHandlers,\n McpAppHostContext,\n McpAppHostInfo,\n McpAppResource,\n McpAppSandboxConfig,\n McpAppsHost,\n} from \"./types\";\nimport { getMcpAppFromToolPart } from \"./utils\";\n\nexport type McpAppRendererOptions = {\n /**\n * Provides the data-plane operations the widget can request\n * (`loadResource`, `callTool`, `readResource`, `listResources`). Use\n * `McpAppsRemoteHost({ url })` for the default HTTP-route convention.\n */\n host: ResourceElement<McpAppsHost>;\n /** Sandbox + container styling. Passes through to SafeContentFrame. */\n sandbox?: McpAppSandboxConfig;\n /**\n * Upper bound (in pixels) applied to the widget-driven auto-resize height.\n * Defaults to 800.\n */\n maxHeight?: number;\n /** Identifies the host to the widget in the `ui/initialize` response. */\n hostInfo?: McpAppHostInfo;\n /** Delivered to the widget on initialize and pushed via `notifications/host_context/changed` on change. */\n hostContext?: McpAppHostContext;\n /** Rendered when no MCP app is on the part, or while load is in flight / failed (unless overridden). */\n fallback?: ReactNode;\n /** Rendered while the resource is loading. Defaults to `fallback`. */\n loadingFallback?: ReactNode;\n /** Rendered when the resource load rejects. Defaults to `fallback`. */\n errorFallback?: ReactNode | ((error: Error) => ReactNode);\n};\n\ntype LoadedResourceState = {\n resourceUri: string;\n resource?: McpAppResource;\n error?: Error;\n};\n\nfunction getInput(part: {\n status: { type: string };\n argsText: string;\n args: unknown;\n}): unknown {\n if (\n part.status.type === \"running\" &&\n (part.argsText === \"\" || part.argsText === \"{}\")\n ) {\n return undefined;\n }\n return part.args;\n}\n\nconst defaultOpenLink = ({ url }: { url: string }) => {\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n};\n\nfunction extractSendMessageText(params: unknown): string | undefined {\n if (typeof params === \"string\") return params;\n if (!params || typeof params !== \"object\") return undefined;\n const obj = params as Record<string, unknown>;\n if (typeof obj[\"prompt\"] === \"string\") return obj[\"prompt\"];\n if (typeof obj[\"text\"] === \"string\") return obj[\"text\"];\n if (typeof obj[\"message\"] === \"string\") return obj[\"message\"];\n return undefined;\n}\n\nfunction InlineRenderer({\n part,\n internalsRef,\n optionsRef,\n}: {\n part: ToolCallMessagePartProps;\n internalsRef: MutableRefObject<{ host: McpAppsHost }>;\n optionsRef: MutableRefObject<McpAppRendererOptions>;\n}) {\n const opts = optionsRef.current;\n const aui = useAui();\n const app = getMcpAppFromToolPart(part);\n const cachedAppRef = useRef<McpAppMetadata | undefined>(undefined);\n if (app != null && cachedAppRef.current?.resourceUri !== app.resourceUri) {\n cachedAppRef.current = app;\n }\n const appForRender = app ?? cachedAppRef.current;\n\n const [loadedResource, setLoadedResource] = useState<LoadedResourceState>();\n\n const resourceUri = appForRender?.resourceUri;\n useEffect(() => {\n if (appForRender == null || resourceUri == null) return;\n let cancelled = false;\n const targetUri = resourceUri;\n\n internalsRef.current.host\n .loadResource({ uri: targetUri })\n .then((res) => {\n if (!cancelled)\n setLoadedResource({ resourceUri: targetUri, resource: res });\n })\n .catch((error: unknown) => {\n if (!cancelled) {\n setLoadedResource({\n resourceUri: targetUri,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n });\n\n return () => {\n cancelled = true;\n };\n // oxlint-disable-next-line react/exhaustive-deps -- re-fetch only when URI changes; appForRender identity is unstable and internalsRef is a stable ref\n }, [resourceUri]);\n\n const bridgeHandlers = useMemo<McpAppBridgeHandlers>(\n () => ({\n openLink: defaultOpenLink,\n sendMessage: (params) => {\n const text = extractSendMessageText(params);\n if (!text) return { ok: false, reason: \"unrecognised params shape\" };\n aui.thread().append({ content: [{ type: \"text\", text }] });\n return { ok: true };\n },\n callTool: (params) => internalsRef.current.host.callTool(params),\n readResource: (params) => internalsRef.current.host.readResource(params),\n listResources: (params) =>\n internalsRef.current.host.listResources(params),\n }),\n [aui, internalsRef],\n );\n\n const loadedResourceForApp =\n loadedResource?.resourceUri === appForRender?.resourceUri\n ? loadedResource\n : undefined;\n const appResource = loadedResourceForApp?.resource;\n const error = loadedResourceForApp?.error;\n\n const fallback = opts.fallback ?? null;\n if (appForRender == null) {\n return <>{fallback}</>;\n }\n if (error != null) {\n const errorFallback = opts.errorFallback;\n if (errorFallback === undefined) return <>{fallback}</>;\n if (typeof errorFallback === \"function\") return <>{errorFallback(error)}</>;\n return <>{errorFallback}</>;\n }\n if (appResource == null) {\n return <>{opts.loadingFallback ?? fallback}</>;\n }\n\n return (\n <McpAppFrame\n app={appForRender}\n resource={appResource}\n input={getInput(part)}\n output={part.result}\n sandbox={opts.sandbox}\n handlers={bridgeHandlers}\n hostInfo={opts.hostInfo}\n hostContext={opts.hostContext}\n maxHeight={opts.maxHeight}\n />\n );\n}\n\n/**\n * Creates a tool-call renderer for MCP Apps embedded in assistant messages.\n *\n * Compose this into the `Tools` resource through its `mcpApp` option. When a\n * tool-call part carries `mcp.app` metadata for a `ui://` resource, the\n * renderer loads that resource from the configured host and displays it in a\n * sandboxed frame.\n */\nconst useMcpAppRenderer = (\n options: McpAppRendererOptions,\n): { readonly render: ToolCallMessagePartComponent } => {\n const host = useResource(options.host);\n\n const optionsRef = useRef<McpAppRendererOptions>(options);\n optionsRef.current = options;\n\n const internalsRef = useRef<{ host: McpAppsHost }>({ host });\n internalsRef.current = { host };\n\n const render = useMemo((): ToolCallMessagePartComponent => {\n const Render: ToolCallMessagePartComponent = (props) => (\n <InlineRenderer\n part={props}\n internalsRef={internalsRef}\n optionsRef={optionsRef}\n />\n );\n Render.displayName = \"McpAppRenderer\";\n return Render;\n }, []);\n\n return { render };\n};\n\nexport const McpAppRenderer = resource(useMcpAppRenderer);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"McpAppRenderer.js","names":["useEffect","useMemo","useRef","useState","MutableRefObject","ReactNode","McpAppMetadata","ToolCallMessagePartComponent","ToolCallMessagePartProps","useAui","useResource","resource","ResourceElement","McpAppFrame","McpAppBridgeHandlers","McpAppHostContext","McpAppHostInfo","McpAppResource","McpAppSandboxConfig","McpAppsHost","getMcpAppFromToolPart","McpAppRendererOptions","host","sandbox","maxHeight","hostInfo","hostContext","fallback","loadingFallback","errorFallback","error","Error","LoadedResourceState","resourceUri","getInput","part","status","type","argsText","args","undefined","defaultOpenLink","url","window","open","extractSendMessageText","params","obj","Record","InlineRenderer","internalsRef","optionsRef","opts","current","aui","app","cachedAppRef","appForRender","loadedResource","setLoadedResource","cancelled","targetUri","loadResource","uri","then","res","catch","String","bridgeHandlers","openLink","sendMessage","text","ok","reason","thread","append","content","callTool","readResource","listResources","loadedResourceForApp","appResource","result","useMcpAppRenderer","options","render","Render","props","displayName","McpAppRenderer"],"sources":["../../src/mcp-apps/McpAppRenderer.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type MutableRefObject,\n type ReactNode,\n} from \"react\";\nimport type { McpAppMetadata } from \"@assistant-ui/core\";\nimport type {\n ToolCallMessagePartComponent,\n ToolCallMessagePartProps,\n} from \"@assistant-ui/core/react\";\nimport { useAui } from \"@assistant-ui/store\";\n\nimport { useResource, resource, type ResourceElement } from \"@assistant-ui/tap\";\nimport { McpAppFrame } from \"./app-frame\";\nimport type {\n McpAppBridgeHandlers,\n McpAppHostContext,\n McpAppHostInfo,\n McpAppResource,\n McpAppSandboxConfig,\n McpAppsHost,\n} from \"./types\";\nimport { getMcpAppFromToolPart } from \"./utils\";\n\nexport type McpAppRendererOptions = {\n /**\n * Provides the data-plane operations the widget can request\n * (`loadResource`, `callTool`, `readResource`, `listResources`). Use\n * `McpAppsRemoteHost({ url })` for the default HTTP-route convention.\n */\n host: ResourceElement<McpAppsHost>;\n /** Sandbox + container styling. Passes through to SafeContentFrame. */\n sandbox?: McpAppSandboxConfig;\n /**\n * Upper bound (in pixels) applied to the widget-driven auto-resize height.\n * Defaults to 800.\n */\n maxHeight?: number;\n /** Identifies the host to the widget in the `ui/initialize` response. */\n hostInfo?: McpAppHostInfo;\n /** Delivered to the widget on initialize and pushed via `notifications/host_context/changed` on change. */\n hostContext?: McpAppHostContext;\n /** Rendered when no MCP app is on the part, or while load is in flight / failed (unless overridden). */\n fallback?: ReactNode;\n /** Rendered while the resource is loading. Defaults to `fallback`. */\n loadingFallback?: ReactNode;\n /** Rendered when the resource load rejects. Defaults to `fallback`. */\n errorFallback?: ReactNode | ((error: Error) => ReactNode);\n};\n\ntype LoadedResourceState = {\n resourceUri: string;\n resource?: McpAppResource;\n error?: Error;\n};\n\nfunction getInput(part: {\n status: { type: string };\n argsText: string;\n args: unknown;\n}): unknown {\n if (\n part.status.type === \"running\" &&\n (part.argsText === \"\" || part.argsText === \"{}\")\n ) {\n return undefined;\n }\n return part.args;\n}\n\nconst defaultOpenLink = ({ url }: { url: string }) => {\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n};\n\nfunction extractSendMessageText(params: unknown): string | undefined {\n if (typeof params === \"string\") return params;\n if (!params || typeof params !== \"object\") return undefined;\n const obj = params as Record<string, unknown>;\n if (typeof obj[\"prompt\"] === \"string\") return obj[\"prompt\"];\n if (typeof obj[\"text\"] === \"string\") return obj[\"text\"];\n if (typeof obj[\"message\"] === \"string\") return obj[\"message\"];\n return undefined;\n}\n\nfunction InlineRenderer({\n part,\n internalsRef,\n optionsRef,\n}: {\n part: ToolCallMessagePartProps;\n internalsRef: MutableRefObject<{ host: McpAppsHost }>;\n optionsRef: MutableRefObject<McpAppRendererOptions>;\n}) {\n const opts = optionsRef.current;\n const aui = useAui();\n const app = getMcpAppFromToolPart(part);\n const cachedAppRef = useRef<McpAppMetadata | undefined>(undefined);\n if (app != null && cachedAppRef.current?.resourceUri !== app.resourceUri) {\n cachedAppRef.current = app;\n }\n const appForRender = app ?? cachedAppRef.current;\n\n const [loadedResource, setLoadedResource] = useState<LoadedResourceState>();\n\n const resourceUri = appForRender?.resourceUri;\n useEffect(() => {\n if (appForRender == null || resourceUri == null) return;\n let cancelled = false;\n const targetUri = resourceUri;\n\n internalsRef.current.host\n .loadResource({ uri: targetUri })\n .then((res) => {\n if (!cancelled)\n setLoadedResource({ resourceUri: targetUri, resource: res });\n })\n .catch((error: unknown) => {\n if (!cancelled) {\n setLoadedResource({\n resourceUri: targetUri,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n });\n\n return () => {\n cancelled = true;\n };\n // oxlint-disable-next-line react/exhaustive-deps -- re-fetch only when URI changes; appForRender identity is unstable and internalsRef is a stable ref\n }, [resourceUri]);\n\n const bridgeHandlers = useMemo<McpAppBridgeHandlers>(\n () => ({\n openLink: defaultOpenLink,\n sendMessage: (params) => {\n const text = extractSendMessageText(params);\n if (!text) return { ok: false, reason: \"unrecognised params shape\" };\n aui.thread().append({ content: [{ type: \"text\", text }] });\n return { ok: true };\n },\n callTool: (params) => internalsRef.current.host.callTool(params),\n readResource: (params) => internalsRef.current.host.readResource(params),\n listResources: (params) =>\n internalsRef.current.host.listResources(params),\n }),\n [aui, internalsRef],\n );\n\n const loadedResourceForApp =\n loadedResource?.resourceUri === appForRender?.resourceUri\n ? loadedResource\n : undefined;\n const appResource = loadedResourceForApp?.resource;\n const error = loadedResourceForApp?.error;\n\n const fallback = opts.fallback ?? null;\n if (appForRender == null) {\n return <>{fallback}</>;\n }\n if (error != null) {\n const errorFallback = opts.errorFallback;\n if (errorFallback === undefined) return <>{fallback}</>;\n if (typeof errorFallback === \"function\") return <>{errorFallback(error)}</>;\n return <>{errorFallback}</>;\n }\n if (appResource == null) {\n return <>{opts.loadingFallback ?? fallback}</>;\n }\n\n return (\n <McpAppFrame\n app={appForRender}\n resource={appResource}\n input={getInput(part)}\n output={part.result}\n sandbox={opts.sandbox}\n handlers={bridgeHandlers}\n hostInfo={opts.hostInfo}\n hostContext={opts.hostContext}\n maxHeight={opts.maxHeight}\n />\n );\n}\n\n/**\n * Creates a tool-call renderer for MCP Apps embedded in assistant messages.\n *\n * Compose this into the `Tools` resource through its `mcpApp` option. When a\n * tool-call part carries `mcp.app` metadata for a `ui://` resource, the\n * renderer loads that resource from the configured host and displays it in a\n * sandboxed frame.\n */\nconst useMcpAppRenderer = (\n options: McpAppRendererOptions,\n): { readonly render: ToolCallMessagePartComponent } => {\n const host = useResource(options.host);\n\n const optionsRef = useRef<McpAppRendererOptions>(options);\n optionsRef.current = options;\n\n const internalsRef = useRef<{ host: McpAppsHost }>({ host });\n internalsRef.current = { host };\n\n const render = useMemo((): ToolCallMessagePartComponent => {\n const Render: ToolCallMessagePartComponent = (props) => (\n <InlineRenderer\n part={props}\n internalsRef={internalsRef}\n optionsRef={optionsRef}\n />\n );\n Render.displayName = \"McpAppRenderer\";\n return Render;\n }, []);\n\n return { render };\n};\n\nexport const McpAppRenderer = resource(useMcpAppRenderer);\n"],"mappings":"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"}
|
|
@@ -30,9 +30,9 @@ const useMcpAppsRemoteHost = (options) => {
|
|
|
30
30
|
optionsRef.current = options;
|
|
31
31
|
return useMemo(() => ({
|
|
32
32
|
loadResource: (params) => postToHost(optionsRef.current, "mcp-apps/read-resource", params),
|
|
33
|
-
callTool: (
|
|
34
|
-
readResource: (
|
|
35
|
-
listResources: (
|
|
33
|
+
callTool: (params_0) => postToHost(optionsRef.current, "tools/call", params_0),
|
|
34
|
+
readResource: (params_1) => postToHost(optionsRef.current, "resources/read", params_1),
|
|
35
|
+
listResources: (params_2) => postToHost(optionsRef.current, "resources/list", params_2)
|
|
36
36
|
}), []);
|
|
37
37
|
};
|
|
38
38
|
const McpAppsRemoteHost = resource(useMcpAppsRemoteHost);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpAppsRemoteHost.js","names":[],"sources":["../../src/mcp-apps/McpAppsRemoteHost.ts"],"sourcesContent":["import { useMemo, useRef } from \"react\";\nimport { resource } from \"@assistant-ui/tap\";\nimport type {\n McpAppResource,\n McpAppsHost,\n McpAppsRemoteHostOptions,\n} from \"./types\";\n\nasync function postToHost(\n options: McpAppsRemoteHostOptions,\n method: string,\n params: unknown,\n): Promise<unknown> {\n const doFetch = options.fetch ?? fetch;\n const extraHeaders =\n typeof options.headers === \"function\"\n ? await options.headers()\n : (options.headers ?? {});\n const res = await doFetch(options.url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", ...extraHeaders },\n body: JSON.stringify({ method, params }),\n });\n if (!res.ok) {\n throw new Error(`MCP App host request failed: ${res.status}`);\n }\n return res.json();\n}\n\n/**\n * Creates the default HTTP host for MCP App widgets.\n *\n * The host POSTs widget requests to the configured route as `{ method,\n * params }`, using the method names expected by the assistant-ui MCP Apps\n * guide.\n */\nconst useMcpAppsRemoteHost = (\n options: McpAppsRemoteHostOptions,\n): McpAppsHost => {\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n return useMemo(\n (): McpAppsHost => ({\n loadResource: (params) =>\n postToHost(\n optionsRef.current,\n \"mcp-apps/read-resource\",\n params,\n ) as Promise<McpAppResource>,\n callTool: (params) =>\n postToHost(optionsRef.current, \"tools/call\", params),\n readResource: (params) =>\n postToHost(optionsRef.current, \"resources/read\", params),\n listResources: (params) =>\n postToHost(optionsRef.current, \"resources/list\", params),\n }),\n [],\n );\n};\n\nexport const McpAppsRemoteHost = resource(useMcpAppsRemoteHost);\n"],"mappings":";;;AAQA,
|
|
1
|
+
{"version":3,"file":"McpAppsRemoteHost.js","names":["useMemo","useRef","resource","McpAppResource","McpAppsHost","McpAppsRemoteHostOptions","postToHost","options","method","params","Promise","doFetch","fetch","extraHeaders","headers","res","url","body","JSON","stringify","ok","Error","status","json","useMcpAppsRemoteHost","optionsRef","current","loadResource","callTool","readResource","listResources","McpAppsRemoteHost"],"sources":["../../src/mcp-apps/McpAppsRemoteHost.ts"],"sourcesContent":["import { useMemo, useRef } from \"react\";\nimport { resource } from \"@assistant-ui/tap\";\nimport type {\n McpAppResource,\n McpAppsHost,\n McpAppsRemoteHostOptions,\n} from \"./types\";\n\nasync function postToHost(\n options: McpAppsRemoteHostOptions,\n method: string,\n params: unknown,\n): Promise<unknown> {\n const doFetch = options.fetch ?? fetch;\n const extraHeaders =\n typeof options.headers === \"function\"\n ? await options.headers()\n : (options.headers ?? {});\n const res = await doFetch(options.url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", ...extraHeaders },\n body: JSON.stringify({ method, params }),\n });\n if (!res.ok) {\n throw new Error(`MCP App host request failed: ${res.status}`);\n }\n return res.json();\n}\n\n/**\n * Creates the default HTTP host for MCP App widgets.\n *\n * The host POSTs widget requests to the configured route as `{ method,\n * params }`, using the method names expected by the assistant-ui MCP Apps\n * guide.\n */\nconst useMcpAppsRemoteHost = (\n options: McpAppsRemoteHostOptions,\n): McpAppsHost => {\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n return useMemo(\n (): McpAppsHost => ({\n loadResource: (params) =>\n postToHost(\n optionsRef.current,\n \"mcp-apps/read-resource\",\n params,\n ) as Promise<McpAppResource>,\n callTool: (params) =>\n postToHost(optionsRef.current, \"tools/call\", params),\n readResource: (params) =>\n postToHost(optionsRef.current, \"resources/read\", params),\n listResources: (params) =>\n postToHost(optionsRef.current, \"resources/list\", params),\n }),\n [],\n );\n};\n\nexport const McpAppsRemoteHost = resource(useMcpAppsRemoteHost);\n"],"mappings":";;;AAQA,eAAeM,WACbC,SACAC,QACAC,QACkB;CAClB,MAAME,UAAUJ,QAAQK,SAASA;CACjC,MAAMC,eACJ,OAAON,QAAQO,YAAY,aACvB,MAAMP,QAAQO,QAAQ,IACrBP,QAAQO,WAAW,CAAC;CAC3B,MAAMC,MAAM,MAAMJ,QAAQJ,QAAQS,KAAK;EACrCR,QAAQ;EACRM,SAAS;GAAE,gBAAgB;GAAoB,GAAGD;EAAa;EAC/DI,MAAMC,KAAKC,UAAU;GAAEX;GAAQC;EAAO,CAAC;CACzC,CAAC;CACD,IAAI,CAACM,IAAIK,IACP,MAAM,IAAIC,MAAM,gCAAgCN,IAAIO,QAAQ;CAE9D,OAAOP,IAAIQ,KAAK;AAClB;;;;;;;;AASA,MAAMC,wBACJjB,YACgB;CAChB,MAAMkB,aAAaxB,OAAOM,OAAO;CACjCkB,WAAWC,UAAUnB;CAErB,OAAOP,eACe;EAClB2B,eAAelB,WACbH,WACEmB,WAAWC,SACX,0BACAjB,MACF;EACFmB,WAAWnB,aACTH,WAAWmB,WAAWC,SAAS,cAAcjB,QAAM;EACrDoB,eAAepB,aACbH,WAAWmB,WAAWC,SAAS,kBAAkBjB,QAAM;EACzDqB,gBAAgBrB,aACdH,WAAWmB,WAAWC,SAAS,kBAAkBjB,QAAM;CAC3D,IACA,CAAA,CACF;AACF;AAEA,MAAasB,oBAAoB7B,SAASsB,oBAAoB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createMcpAppBridge } from "./bridge.js";
|
|
3
3
|
import { SandboxHost } from "../sandbox-host/SandboxHost.js";
|
|
4
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
4
5
|
import { useEffect, useRef } from "@assistant-ui/tap/react-shim";
|
|
5
6
|
import { jsx } from "react/jsx-runtime";
|
|
6
7
|
//#region src/mcp-apps/app-frame.tsx
|
|
@@ -8,17 +9,35 @@ const DEFAULT_PRODUCT = "assistant-ui-mcp-app";
|
|
|
8
9
|
const INIT_TIMEOUT_MS = 5e3;
|
|
9
10
|
const DEFAULT_MAX_HEIGHT = 800;
|
|
10
11
|
function useBridgeNotify(value, bridgeRef, widgetReadyRef, pendingRef, lastSentRef, notify) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
const $ = c(9);
|
|
13
|
+
let t0;
|
|
14
|
+
if ($[0] !== bridgeRef || $[1] !== lastSentRef || $[2] !== notify || $[3] !== pendingRef || $[4] !== value || $[5] !== widgetReadyRef) {
|
|
15
|
+
t0 = () => {
|
|
16
|
+
if (!bridgeRef.current) return;
|
|
17
|
+
if (value === void 0) return;
|
|
18
|
+
if (lastSentRef.current === value) return;
|
|
19
|
+
if (!widgetReadyRef.current) {
|
|
20
|
+
pendingRef.current = value;
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
notify(bridgeRef.current, value);
|
|
24
|
+
lastSentRef.current = value;
|
|
25
|
+
};
|
|
26
|
+
$[0] = bridgeRef;
|
|
27
|
+
$[1] = lastSentRef;
|
|
28
|
+
$[2] = notify;
|
|
29
|
+
$[3] = pendingRef;
|
|
30
|
+
$[4] = value;
|
|
31
|
+
$[5] = widgetReadyRef;
|
|
32
|
+
$[6] = t0;
|
|
33
|
+
} else t0 = $[6];
|
|
34
|
+
let t1;
|
|
35
|
+
if ($[7] !== value) {
|
|
36
|
+
t1 = [value];
|
|
37
|
+
$[7] = value;
|
|
38
|
+
$[8] = t1;
|
|
39
|
+
} else t1 = $[8];
|
|
40
|
+
useEffect(t0, t1);
|
|
22
41
|
}
|
|
23
42
|
function buildLiveHandlers(initial, liveRef) {
|
|
24
43
|
const live = () => liveRef.current.handlers;
|
|
@@ -138,9 +157,9 @@ function McpAppFrame({ app, resource, input, output, sandbox, handlers, hostInfo
|
|
|
138
157
|
}
|
|
139
158
|
};
|
|
140
159
|
};
|
|
141
|
-
useBridgeNotify(input, bridgeRef, widgetReadyRef, pendingInputRef, lastSentInputRef, (
|
|
142
|
-
useBridgeNotify(output, bridgeRef, widgetReadyRef, pendingOutputRef, lastSentOutputRef, (
|
|
143
|
-
useBridgeNotify(hostContext, bridgeRef, widgetReadyRef, pendingHostContextRef, lastSentHostContextRef, (
|
|
160
|
+
useBridgeNotify(input, bridgeRef, widgetReadyRef, pendingInputRef, lastSentInputRef, (b_0, v) => b_0.notifyToolInput(v));
|
|
161
|
+
useBridgeNotify(output, bridgeRef, widgetReadyRef, pendingOutputRef, lastSentOutputRef, (b_1, v_0) => b_1.notifyToolResult(v_0));
|
|
162
|
+
useBridgeNotify(hostContext, bridgeRef, widgetReadyRef, pendingHostContextRef, lastSentHostContextRef, (b_2, v_1) => b_2.notifyHostContextChanged(v_1));
|
|
144
163
|
return /* @__PURE__ */ jsx(SandboxHost, {
|
|
145
164
|
content: { html: resource.html },
|
|
146
165
|
contentKey: resource.uri,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-frame.js","names":[],"sources":["../../src/mcp-apps/app-frame.tsx"],"sourcesContent":["\"use client\";\n\nimport { type MutableRefObject, useEffect, useRef } from \"react\";\nimport { type McpAppBridge, createMcpAppBridge } from \"./bridge\";\nimport {\n SandboxHost,\n type SandboxBridge,\n type SandboxHostApi,\n type SandboxHostFrame,\n} from \"../sandbox-host/SandboxHost\";\nimport type {\n McpAppBridgeHandlers,\n McpAppFrameProps,\n McpAppHostContext,\n} from \"./types\";\n\nconst DEFAULT_PRODUCT = \"assistant-ui-mcp-app\";\nconst INIT_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_HEIGHT = 800;\n\nfunction useBridgeNotify<T>(\n value: T | undefined,\n bridgeRef: MutableRefObject<McpAppBridge | null>,\n widgetReadyRef: MutableRefObject<boolean>,\n pendingRef: MutableRefObject<T | undefined>,\n lastSentRef: MutableRefObject<T | undefined>,\n notify: (bridge: McpAppBridge, v: T) => void,\n) {\n useEffect(() => {\n if (!bridgeRef.current) return;\n if (value === undefined) return;\n if (lastSentRef.current === value) return;\n if (!widgetReadyRef.current) {\n pendingRef.current = value;\n return;\n }\n notify(bridgeRef.current, value);\n lastSentRef.current = value;\n // oxlint-disable-next-line react/exhaustive-deps -- refs are stable; notify is assumed stable; re-run only when value changes\n }, [value]);\n}\n\ntype LiveSnapshot = {\n handlers: McpAppBridgeHandlers | undefined;\n hostInfo: McpAppFrameProps[\"hostInfo\"];\n hostContext: McpAppFrameProps[\"hostContext\"];\n input: unknown;\n output: unknown;\n};\n\n// Proxy each per-call handler through liveRef so the bridge always dispatches\n// to the latest handler reference (e.g. inline callbacks closing over state).\n// Capability presence is snapshot at mount: a handler added later requires a\n// remount (keyed on resource URI) to expose the capability to the widget.\nfunction buildLiveHandlers(\n initial: McpAppBridgeHandlers | undefined,\n liveRef: { readonly current: LiveSnapshot },\n): McpAppBridgeHandlers {\n const live = () => liveRef.current.handlers;\n const has = <K extends keyof McpAppBridgeHandlers>(key: K) =>\n initial?.[key] !== undefined;\n const out: McpAppBridgeHandlers = {};\n if (has(\"allowedTools\")) {\n Object.defineProperty(out, \"allowedTools\", {\n get: () => live()?.allowedTools,\n enumerable: true,\n configurable: true,\n });\n }\n const liveCall = <K extends keyof McpAppBridgeHandlers>(\n key: K,\n ): NonNullable<McpAppBridgeHandlers[K]> =>\n ((p: unknown) => {\n const fn = live()?.[key] as ((p: unknown) => unknown) | undefined;\n if (!fn) {\n throw new Error(`${key} handler is no longer available`);\n }\n return fn(p);\n }) as NonNullable<McpAppBridgeHandlers[K]>;\n if (has(\"callTool\")) out.callTool = liveCall(\"callTool\");\n if (has(\"readResource\")) out.readResource = liveCall(\"readResource\");\n if (has(\"listResources\")) out.listResources = liveCall(\"listResources\");\n if (has(\"openLink\")) out.openLink = liveCall(\"openLink\");\n if (has(\"sendMessage\")) out.sendMessage = liveCall(\"sendMessage\");\n if (has(\"updateModelContext\"))\n out.updateModelContext = liveCall(\"updateModelContext\");\n if (has(\"requestDisplayMode\"))\n out.requestDisplayMode = liveCall(\"requestDisplayMode\");\n out.onSizeChange = (p) => live()?.onSizeChange?.(p);\n out.onInitialized = () => live()?.onInitialized?.();\n out.onRequestTeardown = (p) => live()?.onRequestTeardown?.(p);\n out.onLog = (p) => live()?.onLog?.(p);\n out.onError = (e) => live()?.onError?.(e);\n return out;\n}\n\nexport function McpAppFrame({\n app,\n resource,\n input,\n output,\n sandbox,\n handlers,\n hostInfo,\n hostContext,\n maxHeight = DEFAULT_MAX_HEIGHT,\n}: McpAppFrameProps) {\n const bridgeRef = useRef<McpAppBridge | null>(null);\n const lastSentInputRef = useRef<unknown>(undefined);\n const lastSentOutputRef = useRef<unknown>(undefined);\n const lastSentHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n // Per MCP Apps spec, the host should defer notifications until the widget\n // signals readiness via `notifications/initialized`. Until then, we record\n // pending values and flush them on init.\n const widgetReadyRef = useRef(false);\n const pendingInputRef = useRef<unknown>(undefined);\n const pendingOutputRef = useRef<unknown>(undefined);\n const pendingHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n\n const liveRef = useRef<LiveSnapshot>(null!);\n liveRef.current = {\n handlers,\n hostInfo,\n hostContext,\n input,\n output,\n };\n\n const createBridge = (\n frame: SandboxHostFrame,\n host: SandboxHostApi,\n ): SandboxBridge => {\n const current = liveRef.current;\n let initTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const flushPending = () => {\n if (widgetReadyRef.current) return;\n widgetReadyRef.current = true;\n const b = bridgeRef.current;\n if (!b) return;\n if (pendingInputRef.current !== undefined) {\n b.notifyToolInput(pendingInputRef.current);\n lastSentInputRef.current = pendingInputRef.current;\n pendingInputRef.current = undefined;\n }\n if (pendingOutputRef.current !== undefined) {\n b.notifyToolResult(pendingOutputRef.current);\n lastSentOutputRef.current = pendingOutputRef.current;\n pendingOutputRef.current = undefined;\n }\n if (pendingHostContextRef.current !== undefined) {\n b.notifyHostContextChanged(pendingHostContextRef.current);\n lastSentHostContextRef.current = pendingHostContextRef.current;\n pendingHostContextRef.current = undefined;\n }\n };\n\n const liveHandlers = buildLiveHandlers(current.handlers, liveRef);\n const liveOnInitialized = liveHandlers.onInitialized;\n const wrappedHandlers: McpAppBridgeHandlers = {\n ...liveHandlers,\n onInitialized: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n flushPending();\n liveOnInitialized?.();\n },\n onSizeChange: (p) => {\n if (p.height != null) host.setHeight(p.height);\n liveHandlers.onSizeChange?.(p);\n },\n };\n\n // Safety net: if the widget never sends notifications/initialized (broken\n // or non-spec-compliant), flush the queue anyway so the host doesn't\n // appear hung.\n initTimeoutId = setTimeout(() => {\n initTimeoutId = null;\n flushPending();\n }, INIT_TIMEOUT_MS);\n\n const bridge = createMcpAppBridge({\n frame,\n handlers: wrappedHandlers,\n hostInfo: current.hostInfo,\n hostContext: current.hostContext,\n });\n bridgeRef.current = bridge;\n\n if (current.input !== undefined) pendingInputRef.current = current.input;\n if (current.output !== undefined) pendingOutputRef.current = current.output;\n // hostContext is delivered inside the ui/initialize response; subsequent\n // changes flow through useBridgeNotify's pending path.\n\n return {\n onMessage: bridge.onMessage,\n dispose: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n bridge.dispose();\n bridgeRef.current = null;\n lastSentInputRef.current = undefined;\n lastSentOutputRef.current = undefined;\n lastSentHostContextRef.current = undefined;\n widgetReadyRef.current = false;\n pendingInputRef.current = undefined;\n pendingOutputRef.current = undefined;\n pendingHostContextRef.current = undefined;\n },\n };\n };\n\n useBridgeNotify(\n input,\n bridgeRef,\n widgetReadyRef,\n pendingInputRef,\n lastSentInputRef,\n (b, v) => b.notifyToolInput(v),\n );\n useBridgeNotify(\n output,\n bridgeRef,\n widgetReadyRef,\n pendingOutputRef,\n lastSentOutputRef,\n (b, v) => b.notifyToolResult(v),\n );\n useBridgeNotify(\n hostContext,\n bridgeRef,\n widgetReadyRef,\n pendingHostContextRef,\n lastSentHostContextRef,\n (b, v) => b.notifyHostContextChanged(v),\n );\n\n return (\n <SandboxHost\n content={{ html: resource.html }}\n contentKey={resource.uri}\n sandbox={{ ...sandbox, product: sandbox?.product ?? DEFAULT_PRODUCT }}\n maxHeight={maxHeight}\n createBridge={createBridge}\n onError={(err) => liveRef.current.handlers?.onError?.(err)}\n containerProps={{\n \"data-mcp-app-resource\": app.resourceUri,\n \"data-mcp-app-prefers-border\": resource.meta?.prefersBorder\n ? \"\"\n : undefined,\n }}\n />\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-frame.js","names":["c","_c","MutableRefObject","useEffect","useRef","McpAppBridge","createMcpAppBridge","SandboxHost","SandboxBridge","SandboxHostApi","SandboxHostFrame","McpAppBridgeHandlers","McpAppFrameProps","McpAppHostContext","DEFAULT_PRODUCT","INIT_TIMEOUT_MS","DEFAULT_MAX_HEIGHT","useBridgeNotify","value","bridgeRef","widgetReadyRef","pendingRef","lastSentRef","notify","$","t0","current","undefined","t1","LiveSnapshot","handlers","hostInfo","hostContext","input","output","buildLiveHandlers","initial","liveRef","live","has","key","K","out","Object","defineProperty","get","allowedTools","enumerable","configurable","liveCall","NonNullable","p","fn","Error","callTool","readResource","listResources","openLink","sendMessage","updateModelContext","requestDisplayMode","onSizeChange","onInitialized","onRequestTeardown","onLog","onError","e","McpAppFrame","app","resource","sandbox","maxHeight","lastSentInputRef","lastSentOutputRef","lastSentHostContextRef","pendingInputRef","pendingOutputRef","pendingHostContextRef","createBridge","frame","host","initTimeoutId","ReturnType","setTimeout","flushPending","b","notifyToolInput","notifyToolResult","notifyHostContextChanged","liveHandlers","liveOnInitialized","wrappedHandlers","clearTimeout","height","setHeight","bridge","onMessage","dispose","v","html","uri","product","err","resourceUri","meta","prefersBorder"],"sources":["../../src/mcp-apps/app-frame.tsx"],"sourcesContent":["\"use client\";\n\nimport { type MutableRefObject, useEffect, useRef } from \"react\";\nimport { type McpAppBridge, createMcpAppBridge } from \"./bridge\";\nimport {\n SandboxHost,\n type SandboxBridge,\n type SandboxHostApi,\n type SandboxHostFrame,\n} from \"../sandbox-host/SandboxHost\";\nimport type {\n McpAppBridgeHandlers,\n McpAppFrameProps,\n McpAppHostContext,\n} from \"./types\";\n\nconst DEFAULT_PRODUCT = \"assistant-ui-mcp-app\";\nconst INIT_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_HEIGHT = 800;\n\nfunction useBridgeNotify<T>(\n value: T | undefined,\n bridgeRef: MutableRefObject<McpAppBridge | null>,\n widgetReadyRef: MutableRefObject<boolean>,\n pendingRef: MutableRefObject<T | undefined>,\n lastSentRef: MutableRefObject<T | undefined>,\n notify: (bridge: McpAppBridge, v: T) => void,\n) {\n useEffect(() => {\n if (!bridgeRef.current) return;\n if (value === undefined) return;\n if (lastSentRef.current === value) return;\n if (!widgetReadyRef.current) {\n pendingRef.current = value;\n return;\n }\n notify(bridgeRef.current, value);\n lastSentRef.current = value;\n // oxlint-disable-next-line react/exhaustive-deps -- refs are stable; notify is assumed stable; re-run only when value changes\n }, [value]);\n}\n\ntype LiveSnapshot = {\n handlers: McpAppBridgeHandlers | undefined;\n hostInfo: McpAppFrameProps[\"hostInfo\"];\n hostContext: McpAppFrameProps[\"hostContext\"];\n input: unknown;\n output: unknown;\n};\n\n// Proxy each per-call handler through liveRef so the bridge always dispatches\n// to the latest handler reference (e.g. inline callbacks closing over state).\n// Capability presence is snapshot at mount: a handler added later requires a\n// remount (keyed on resource URI) to expose the capability to the widget.\nfunction buildLiveHandlers(\n initial: McpAppBridgeHandlers | undefined,\n liveRef: { readonly current: LiveSnapshot },\n): McpAppBridgeHandlers {\n const live = () => liveRef.current.handlers;\n const has = <K extends keyof McpAppBridgeHandlers>(key: K) =>\n initial?.[key] !== undefined;\n const out: McpAppBridgeHandlers = {};\n if (has(\"allowedTools\")) {\n Object.defineProperty(out, \"allowedTools\", {\n get: () => live()?.allowedTools,\n enumerable: true,\n configurable: true,\n });\n }\n const liveCall = <K extends keyof McpAppBridgeHandlers>(\n key: K,\n ): NonNullable<McpAppBridgeHandlers[K]> =>\n ((p: unknown) => {\n const fn = live()?.[key] as ((p: unknown) => unknown) | undefined;\n if (!fn) {\n throw new Error(`${key} handler is no longer available`);\n }\n return fn(p);\n }) as NonNullable<McpAppBridgeHandlers[K]>;\n if (has(\"callTool\")) out.callTool = liveCall(\"callTool\");\n if (has(\"readResource\")) out.readResource = liveCall(\"readResource\");\n if (has(\"listResources\")) out.listResources = liveCall(\"listResources\");\n if (has(\"openLink\")) out.openLink = liveCall(\"openLink\");\n if (has(\"sendMessage\")) out.sendMessage = liveCall(\"sendMessage\");\n if (has(\"updateModelContext\"))\n out.updateModelContext = liveCall(\"updateModelContext\");\n if (has(\"requestDisplayMode\"))\n out.requestDisplayMode = liveCall(\"requestDisplayMode\");\n out.onSizeChange = (p) => live()?.onSizeChange?.(p);\n out.onInitialized = () => live()?.onInitialized?.();\n out.onRequestTeardown = (p) => live()?.onRequestTeardown?.(p);\n out.onLog = (p) => live()?.onLog?.(p);\n out.onError = (e) => live()?.onError?.(e);\n return out;\n}\n\nexport function McpAppFrame({\n app,\n resource,\n input,\n output,\n sandbox,\n handlers,\n hostInfo,\n hostContext,\n maxHeight = DEFAULT_MAX_HEIGHT,\n}: McpAppFrameProps) {\n const bridgeRef = useRef<McpAppBridge | null>(null);\n const lastSentInputRef = useRef<unknown>(undefined);\n const lastSentOutputRef = useRef<unknown>(undefined);\n const lastSentHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n // Per MCP Apps spec, the host should defer notifications until the widget\n // signals readiness via `notifications/initialized`. Until then, we record\n // pending values and flush them on init.\n const widgetReadyRef = useRef(false);\n const pendingInputRef = useRef<unknown>(undefined);\n const pendingOutputRef = useRef<unknown>(undefined);\n const pendingHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n\n const liveRef = useRef<LiveSnapshot>(null!);\n liveRef.current = {\n handlers,\n hostInfo,\n hostContext,\n input,\n output,\n };\n\n const createBridge = (\n frame: SandboxHostFrame,\n host: SandboxHostApi,\n ): SandboxBridge => {\n const current = liveRef.current;\n let initTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const flushPending = () => {\n if (widgetReadyRef.current) return;\n widgetReadyRef.current = true;\n const b = bridgeRef.current;\n if (!b) return;\n if (pendingInputRef.current !== undefined) {\n b.notifyToolInput(pendingInputRef.current);\n lastSentInputRef.current = pendingInputRef.current;\n pendingInputRef.current = undefined;\n }\n if (pendingOutputRef.current !== undefined) {\n b.notifyToolResult(pendingOutputRef.current);\n lastSentOutputRef.current = pendingOutputRef.current;\n pendingOutputRef.current = undefined;\n }\n if (pendingHostContextRef.current !== undefined) {\n b.notifyHostContextChanged(pendingHostContextRef.current);\n lastSentHostContextRef.current = pendingHostContextRef.current;\n pendingHostContextRef.current = undefined;\n }\n };\n\n const liveHandlers = buildLiveHandlers(current.handlers, liveRef);\n const liveOnInitialized = liveHandlers.onInitialized;\n const wrappedHandlers: McpAppBridgeHandlers = {\n ...liveHandlers,\n onInitialized: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n flushPending();\n liveOnInitialized?.();\n },\n onSizeChange: (p) => {\n if (p.height != null) host.setHeight(p.height);\n liveHandlers.onSizeChange?.(p);\n },\n };\n\n // Safety net: if the widget never sends notifications/initialized (broken\n // or non-spec-compliant), flush the queue anyway so the host doesn't\n // appear hung.\n initTimeoutId = setTimeout(() => {\n initTimeoutId = null;\n flushPending();\n }, INIT_TIMEOUT_MS);\n\n const bridge = createMcpAppBridge({\n frame,\n handlers: wrappedHandlers,\n hostInfo: current.hostInfo,\n hostContext: current.hostContext,\n });\n bridgeRef.current = bridge;\n\n if (current.input !== undefined) pendingInputRef.current = current.input;\n if (current.output !== undefined) pendingOutputRef.current = current.output;\n // hostContext is delivered inside the ui/initialize response; subsequent\n // changes flow through useBridgeNotify's pending path.\n\n return {\n onMessage: bridge.onMessage,\n dispose: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n bridge.dispose();\n bridgeRef.current = null;\n lastSentInputRef.current = undefined;\n lastSentOutputRef.current = undefined;\n lastSentHostContextRef.current = undefined;\n widgetReadyRef.current = false;\n pendingInputRef.current = undefined;\n pendingOutputRef.current = undefined;\n pendingHostContextRef.current = undefined;\n },\n };\n };\n\n useBridgeNotify(\n input,\n bridgeRef,\n widgetReadyRef,\n pendingInputRef,\n lastSentInputRef,\n (b, v) => b.notifyToolInput(v),\n );\n useBridgeNotify(\n output,\n bridgeRef,\n widgetReadyRef,\n pendingOutputRef,\n lastSentOutputRef,\n (b, v) => b.notifyToolResult(v),\n );\n useBridgeNotify(\n hostContext,\n bridgeRef,\n widgetReadyRef,\n pendingHostContextRef,\n lastSentHostContextRef,\n (b, v) => b.notifyHostContextChanged(v),\n );\n\n return (\n <SandboxHost\n content={{ html: resource.html }}\n contentKey={resource.uri}\n sandbox={{ ...sandbox, product: sandbox?.product ?? DEFAULT_PRODUCT }}\n maxHeight={maxHeight}\n createBridge={createBridge}\n onError={(err) => liveRef.current.handlers?.onError?.(err)}\n containerProps={{\n \"data-mcp-app-resource\": app.resourceUri,\n \"data-mcp-app-prefers-border\": resource.meta?.prefersBorder\n ? \"\"\n : undefined,\n }}\n />\n );\n}\n"],"mappings":"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"}
|