@assistant-ui/core 0.2.10 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/attachment.d.ts.map +1 -1
- package/dist/adapters/attachment.js +22 -12
- package/dist/adapters/attachment.js.map +1 -1
- package/dist/adapters/directive-formatter.js.map +1 -1
- package/dist/adapters/speech.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.js +1 -1
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/frame/provider.js.map +1 -1
- package/dist/model-context/registry.js.map +1 -1
- package/dist/model-context/types.js.map +1 -1
- package/dist/react/AssistantProvider.js +1 -1
- package/dist/react/AssistantRuntimeProvider.d.ts +1 -1
- package/dist/react/AssistantRuntimeProvider.d.ts.map +1 -1
- package/dist/react/AssistantRuntimeProvider.js +1 -1
- package/dist/react/RuntimeAdapter.js +4 -2
- package/dist/react/RuntimeAdapter.js.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/DataRenderers.d.ts.map +1 -1
- package/dist/react/client/DataRenderers.js +6 -5
- package/dist/react/client/DataRenderers.js.map +1 -1
- package/dist/react/client/Interactables.d.ts.map +1 -1
- package/dist/react/client/Interactables.js +30 -29
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +10 -9
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/index.d.ts +5 -4
- package/dist/react/index.js +3 -2
- package/dist/react/model-context/define-mcp-toolkit.js.map +1 -1
- package/dist/react/model-context/define-toolkit.d.ts +9 -12
- package/dist/react/model-context/define-toolkit.d.ts.map +1 -1
- package/dist/react/model-context/define-toolkit.js +1 -1
- package/dist/react/model-context/define-toolkit.js.map +1 -1
- package/dist/react/model-context/external-tool.d.ts +14 -0
- package/dist/react/model-context/external-tool.d.ts.map +1 -0
- package/dist/react/model-context/external-tool.js +17 -0
- package/dist/react/model-context/external-tool.js.map +1 -0
- package/dist/react/model-context/human-tool.d.ts +27 -0
- package/dist/react/model-context/human-tool.d.ts.map +1 -0
- package/dist/react/model-context/human-tool.js +30 -0
- package/dist/react/model-context/human-tool.js.map +1 -0
- package/dist/react/model-context/toolbox.d.ts +3 -3
- package/dist/react/model-context/toolbox.js.map +1 -1
- package/dist/react/model-context/useAssistantContext.js +1 -1
- package/dist/react/model-context/useAssistantContext.js.map +1 -1
- package/dist/react/model-context/useAssistantDataUI.js +1 -1
- package/dist/react/model-context/useAssistantDataUI.js.map +1 -1
- package/dist/react/model-context/useAssistantInstructions.js +1 -1
- package/dist/react/model-context/useAssistantInstructions.js.map +1 -1
- package/dist/react/model-context/useAssistantInteractable.js +1 -1
- package/dist/react/model-context/useAssistantInteractable.js.map +1 -1
- package/dist/react/model-context/useAssistantTool.js +1 -1
- package/dist/react/model-context/useAssistantTool.js.map +1 -1
- package/dist/react/model-context/useAssistantToolUI.js +1 -1
- package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
- package/dist/react/model-context/useAuiToolOverrides.js +1 -1
- package/dist/react/model-context/useAuiToolOverrides.js.map +1 -1
- package/dist/react/model-context/useInlineRender.js +1 -1
- package/dist/react/model-context/useInlineRender.js.map +1 -1
- package/dist/react/model-context/useInteractableState.js +1 -1
- package/dist/react/model-context/useInteractableState.js.map +1 -1
- package/dist/react/model-context/useToolArgsStatus.js +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.js +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.js +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarFeedback.js +1 -1
- package/dist/react/primitive-hooks/useActionBarFeedback.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.js +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarSpeak.js +1 -1
- package/dist/react/primitive-hooks/useActionBarSpeak.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarStopSpeaking.js +1 -1
- package/dist/react/primitive-hooks/useActionBarStopSpeaking.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.js +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerAddAttachment.js +1 -1
- package/dist/react/primitive-hooks/useComposerAddAttachment.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.js +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerDictate.js +1 -1
- package/dist/react/primitive-hooks/useComposerDictate.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.js +1 -1
- package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useEditComposerCancel.js +1 -1
- package/dist/react/primitive-hooks/useEditComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useEditComposerSend.js +1 -1
- package/dist/react/primitive-hooks/useEditComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useMessageBranching.js +1 -1
- package/dist/react/primitive-hooks/useMessageBranching.js.map +1 -1
- package/dist/react/primitive-hooks/useMessageReload.js +1 -1
- package/dist/react/primitive-hooks/useMessageReload.js.map +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.js +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemArchive.js +1 -1
- package/dist/react/primitive-hooks/useThreadListItemArchive.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemDelete.js +1 -1
- package/dist/react/primitive-hooks/useThreadListItemDelete.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemTrigger.js +1 -1
- package/dist/react/primitive-hooks/useThreadListItemTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemUnarchive.js +1 -1
- package/dist/react/primitive-hooks/useThreadListItemUnarchive.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.js +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListNew.js +1 -1
- package/dist/react/primitive-hooks/useThreadListNew.js.map +1 -1
- package/dist/react/primitive-hooks/useVoice.js +1 -1
- package/dist/react/primitive-hooks/useVoice.js.map +1 -1
- package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.d.ts +1 -1
- package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js +1 -1
- package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js.map +1 -1
- package/dist/react/primitives/composer/ComposerAttachments.js +1 -1
- package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
- package/dist/react/primitives/composer/ComposerQueue.js +1 -1
- package/dist/react/primitives/composer/ComposerQueue.js.map +1 -1
- package/dist/react/primitives/generativeUI/GenerativeUI.js +1 -1
- package/dist/react/primitives/generativeUI/GenerativeUI.js.map +1 -1
- package/dist/react/primitives/message/MessageAttachments.js +1 -1
- package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.js +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
- package/dist/react/primitives/message/MessageParts.d.ts +1 -1
- package/dist/react/primitives/message/MessageParts.js +1 -1
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/primitives/message/MessageQuote.js +1 -1
- package/dist/react/primitives/part/PartMessages.d.ts +2 -2
- package/dist/react/primitives/part/PartMessages.js +3 -3
- package/dist/react/primitives/part/PartMessages.js.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.js +1 -1
- package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
- package/dist/react/primitives/thread/ThreadSuggestions.js +1 -1
- package/dist/react/primitives/thread/ThreadSuggestions.js.map +1 -1
- package/dist/react/primitives/threadList/ThreadListItems.js +1 -1
- package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
- package/dist/react/providers/AttachmentByIndexProvider.js.map +1 -1
- package/dist/react/providers/ChainOfThoughtByIndicesProvider.js.map +1 -1
- package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js.map +1 -1
- package/dist/react/providers/MessageByIndexProvider.js.map +1 -1
- package/dist/react/providers/PartByIndexProvider.js.map +1 -1
- package/dist/react/providers/QueueItemByIndexProvider.js.map +1 -1
- package/dist/react/providers/ReadonlyThreadProvider.js +1 -1
- package/dist/react/providers/ReadonlyThreadProvider.js.map +1 -1
- package/dist/react/providers/SuggestionByIndexProvider.js.map +1 -1
- package/dist/react/providers/TextMessagePartProvider.d.ts.map +1 -1
- package/dist/react/providers/TextMessagePartProvider.js +4 -3
- package/dist/react/providers/TextMessagePartProvider.js.map +1 -1
- package/dist/react/providers/ThreadListItemByIndexProvider.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +7 -0
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +7 -0
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RuntimeAdapterProvider.js +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/createMessageConverter.d.ts +2 -2
- package/dist/react/runtimes/createMessageConverter.d.ts.map +1 -1
- package/dist/react/runtimes/createMessageConverter.js.map +1 -1
- package/dist/react/runtimes/external-message-converter.d.ts +4 -3
- package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
- package/dist/react/runtimes/external-message-converter.js +1 -1
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreRuntime.js +1 -1
- package/dist/react/runtimes/useExternalStoreSharedOptions.js +1 -1
- package/dist/react/runtimes/useLocalRuntime.d.ts +2 -1
- package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useLocalRuntime.js +4 -3
- package/dist/react/runtimes/useLocalRuntime.js.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.js +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
- package/dist/react/utils/groupParts.d.ts +1 -1
- package/dist/react/utils/groupParts.js.map +1 -1
- package/dist/runtime/api/attachment-runtime.js.map +1 -1
- package/dist/runtime/api/composer-runtime.d.ts +8 -2
- package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.js +14 -0
- package/dist/runtime/api/composer-runtime.js.map +1 -1
- package/dist/runtime/api/message-part-runtime.js.map +1 -1
- package/dist/runtime/api/message-runtime.js +1 -1
- package/dist/runtime/api/message-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +7 -0
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts +4 -0
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +7 -1
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +4 -0
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js +17 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/composer-runtime-core.d.ts +6 -1
- package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +4 -0
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/queue/external-thread-queue-adapter.d.ts +20 -0
- package/dist/runtime/queue/external-thread-queue-adapter.d.ts.map +1 -0
- package/dist/runtime/queue/external-thread-queue-adapter.js +0 -0
- package/dist/runtime/queue/message-queue.d.ts +20 -0
- package/dist/runtime/queue/message-queue.d.ts.map +1 -0
- package/dist/runtime/queue/message-queue.js +97 -0
- package/dist/runtime/queue/message-queue.js.map +1 -0
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/thread-message-like.js.map +1 -1
- package/dist/runtimes/external-store/external-store-adapter.d.ts +3 -1
- package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-runtime-core.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +4 -0
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +20 -2
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/local/local-runtime-core.js.map +1 -1
- package/dist/runtimes/local/local-runtime-options.d.ts +5 -0
- package/dist/runtimes/local/local-runtime-options.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +7 -0
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +45 -0
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +3 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +3 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.js +3 -0
- package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/chain-of-thought-client.d.ts.map +1 -1
- package/dist/store/clients/chain-of-thought-client.js +6 -5
- package/dist/store/clients/chain-of-thought-client.js.map +1 -1
- package/dist/store/clients/model-context-client.d.ts.map +1 -1
- package/dist/store/clients/model-context-client.js +6 -5
- package/dist/store/clients/model-context-client.js.map +1 -1
- package/dist/store/clients/no-op-composer-client.d.ts.map +1 -1
- package/dist/store/clients/no-op-composer-client.js +4 -3
- package/dist/store/clients/no-op-composer-client.js.map +1 -1
- package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
- package/dist/store/clients/runtime-adapter.js +7 -6
- package/dist/store/clients/runtime-adapter.js.map +1 -1
- package/dist/store/clients/suggestions.d.ts.map +1 -1
- package/dist/store/clients/suggestions.js +7 -6
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/clients/thread-message-client.d.ts.map +1 -1
- package/dist/store/clients/thread-message-client.js +13 -12
- package/dist/store/clients/thread-message-client.js.map +1 -1
- package/dist/store/index.d.ts +1 -1
- package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/attachment-runtime-client.js +3 -3
- package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.d.ts +12 -5
- package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js +32 -16
- package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/message-part-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/message-part-runtime-client.js +3 -3
- package/dist/store/runtime-clients/message-part-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.d.ts +6 -3
- package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.js +17 -16
- package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js +8 -7
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js +11 -10
- package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +15 -14
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/useSubscribable.d.ts +7 -0
- package/dist/store/runtime-clients/useSubscribable.d.ts.map +1 -0
- package/dist/store/runtime-clients/useSubscribable.js +16 -0
- package/dist/store/runtime-clients/useSubscribable.js.map +1 -0
- package/dist/store/scope-registration.d.ts +1 -1
- package/dist/store/scopes/composer.d.ts +1 -1
- package/dist/store/scopes/queue-item.d.ts +2 -1
- package/dist/store/scopes/queue-item.d.ts.map +1 -1
- package/dist/store/scopes/queue-item.js +6 -0
- package/dist/store/scopes/queue-item.js.map +1 -0
- package/dist/store/scopes/thread.d.ts +1 -1
- package/dist/store/scopes/threads.d.ts +1 -1
- package/dist/types/message.d.ts +2 -1
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js.map +1 -1
- package/dist/utils/composite-context-provider.d.ts +1 -1
- package/dist/utils/composite-context-provider.js +3 -1
- package/dist/utils/composite-context-provider.js.map +1 -1
- package/dist/utils/json/is-json.js.map +1 -1
- package/dist/utils/text.js.map +1 -1
- package/package.json +14 -10
- package/src/adapters/attachment.ts +24 -4
- package/src/index.ts +8 -0
- package/src/react/RuntimeAdapter.ts +6 -4
- package/src/react/client/DataRenderers.ts +48 -42
- package/src/react/client/Interactables.ts +263 -267
- package/src/react/client/Tools.ts +122 -129
- package/src/react/index.ts +3 -1
- package/src/react/model-context/define-toolkit.test.ts +14 -7
- package/src/react/model-context/define-toolkit.ts +18 -19
- package/src/react/model-context/external-tool.ts +16 -0
- package/src/react/model-context/{hitl.ts → human-tool.ts} +13 -8
- package/src/react/model-context/toolbox.ts +3 -3
- package/src/react/primitives/message/MessageGroupedParts.tsx +1 -1
- package/src/react/primitives/part/PartMessages.tsx +2 -2
- package/src/react/providers/TextMessagePartProvider.tsx +31 -32
- package/src/react/runtimes/createMessageConverter.ts +2 -1
- package/src/react/runtimes/external-message-converter.ts +5 -3
- package/src/react/runtimes/useLocalRuntime.ts +2 -0
- package/src/runtime/api/composer-runtime.ts +26 -0
- package/src/runtime/base/base-composer-runtime-core.ts +11 -0
- package/src/runtime/base/default-thread-composer-runtime-core.ts +22 -0
- package/src/runtime/interfaces/composer-runtime-core.ts +7 -0
- package/src/runtime/interfaces/thread-runtime-core.ts +5 -0
- package/src/runtime/queue/external-thread-queue-adapter.ts +14 -0
- package/src/runtime/queue/message-queue.ts +128 -0
- package/src/runtimes/external-store/external-store-adapter.ts +3 -0
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +31 -2
- package/src/runtimes/local/local-runtime-options.ts +6 -0
- package/src/runtimes/local/local-thread-runtime-core.ts +70 -0
- package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +4 -0
- package/src/runtimes/remote-thread-list/empty-thread-core.ts +4 -0
- package/src/store/clients/chain-of-thought-client.ts +24 -25
- package/src/store/clients/model-context-client.ts +22 -19
- package/src/store/clients/no-op-composer-client.ts +69 -66
- package/src/store/clients/runtime-adapter.ts +9 -6
- package/src/store/clients/suggestions.ts +41 -40
- package/src/store/clients/thread-message-client.ts +127 -132
- package/src/store/runtime-clients/attachment-runtime-client.ts +7 -3
- package/src/store/runtime-clients/composer-runtime-client.ts +142 -113
- package/src/store/runtime-clients/message-part-runtime-client.ts +16 -14
- package/src/store/runtime-clients/message-runtime-client.ts +124 -122
- package/src/store/runtime-clients/thread-list-item-runtime-client.ts +44 -45
- package/src/store/runtime-clients/thread-list-runtime-client.ts +83 -80
- package/src/store/runtime-clients/thread-runtime-client.ts +113 -119
- package/src/store/runtime-clients/{tap-subscribable.ts → useSubscribable.ts} +4 -4
- package/src/store/scopes/queue-item.ts +2 -0
- package/src/tests/attachment-adapters.test.ts +86 -0
- package/src/tests/external-store-thread-runtime-core.test.ts +125 -0
- package/src/tests/message-queue.test.ts +168 -0
- package/src/types/message.ts +2 -0
- package/src/utils/composite-context-provider.ts +3 -1
- package/dist/react/model-context/hitl.d.ts +0 -23
- package/dist/react/model-context/hitl.d.ts.map +0 -1
- package/dist/react/model-context/hitl.js +0 -26
- package/dist/react/model-context/hitl.js.map +0 -1
- package/dist/store/runtime-clients/tap-subscribable.d.ts +0 -7
- package/dist/store/runtime-clients/tap-subscribable.d.ts.map +0 -1
- package/dist/store/runtime-clients/tap-subscribable.js +0 -16
- package/dist/store/runtime-clients/tap-subscribable.js.map +0 -1
|
@@ -3,6 +3,7 @@ import type { MessageRole } from "../../types/message";
|
|
|
3
3
|
import type { QuoteInfo } from "../../types/quote";
|
|
4
4
|
import type { Unsubscribe } from "../../types/unsubscribe";
|
|
5
5
|
import type { RunConfig } from "../../types/message";
|
|
6
|
+
import type { QueueItemState } from "../../store/scopes/queue-item";
|
|
6
7
|
import {
|
|
7
8
|
LazyMemoizeSubject,
|
|
8
9
|
EventSubscriptionSubject,
|
|
@@ -63,6 +64,9 @@ type BaseComposerState = {
|
|
|
63
64
|
* Undefined when no quote is set.
|
|
64
65
|
*/
|
|
65
66
|
readonly quote: QuoteInfo | undefined;
|
|
67
|
+
|
|
68
|
+
/** Messages waiting to be processed. Empty unless the `queue` capability is set. */
|
|
69
|
+
readonly queue: readonly QueueItemState[];
|
|
66
70
|
};
|
|
67
71
|
|
|
68
72
|
export type ThreadComposerState = BaseComposerState & {
|
|
@@ -97,6 +101,7 @@ const getThreadComposerState = (
|
|
|
97
101
|
attachmentAccept: runtime?.attachmentAccept ?? "",
|
|
98
102
|
dictation: runtime?.dictation,
|
|
99
103
|
quote: runtime?.quote,
|
|
104
|
+
queue: runtime?.queue ?? EMPTY_ARRAY,
|
|
100
105
|
|
|
101
106
|
value: runtime?.text ?? "",
|
|
102
107
|
});
|
|
@@ -120,6 +125,7 @@ const getEditComposerState = (
|
|
|
120
125
|
attachmentAccept: runtime?.attachmentAccept ?? "",
|
|
121
126
|
dictation: runtime?.dictation,
|
|
122
127
|
quote: runtime?.quote,
|
|
128
|
+
queue: runtime?.queue ?? EMPTY_ARRAY,
|
|
123
129
|
|
|
124
130
|
parentId: runtime?.parentId ?? null,
|
|
125
131
|
sourceId: runtime?.sourceId ?? null,
|
|
@@ -194,6 +200,12 @@ export type ComposerRuntime = {
|
|
|
194
200
|
*/
|
|
195
201
|
cancel(): void;
|
|
196
202
|
|
|
203
|
+
/** Promote a queued message so it processes next. */
|
|
204
|
+
steerQueueItem(queueItemId: string): void;
|
|
205
|
+
|
|
206
|
+
/** Remove a queued message. */
|
|
207
|
+
removeQueueItem(queueItemId: string): void;
|
|
208
|
+
|
|
197
209
|
/**
|
|
198
210
|
* Listens for changes to the composer state.
|
|
199
211
|
* @param callback The callback to call when the composer state changes.
|
|
@@ -251,6 +263,8 @@ export abstract class ComposerRuntimeImpl implements ComposerRuntime {
|
|
|
251
263
|
this.clearAttachments = this.clearAttachments.bind(this);
|
|
252
264
|
this.send = this.send.bind(this);
|
|
253
265
|
this.cancel = this.cancel.bind(this);
|
|
266
|
+
this.steerQueueItem = this.steerQueueItem.bind(this);
|
|
267
|
+
this.removeQueueItem = this.removeQueueItem.bind(this);
|
|
254
268
|
this.setRole = this.setRole.bind(this);
|
|
255
269
|
this.getAttachmentByIndex = this.getAttachmentByIndex.bind(this);
|
|
256
270
|
this.startDictation = this.startDictation.bind(this);
|
|
@@ -303,6 +317,18 @@ export abstract class ComposerRuntimeImpl implements ComposerRuntime {
|
|
|
303
317
|
core.cancel();
|
|
304
318
|
}
|
|
305
319
|
|
|
320
|
+
public steerQueueItem(queueItemId: string) {
|
|
321
|
+
const core = this._core.getState();
|
|
322
|
+
if (!core) throw new Error("Composer is not available");
|
|
323
|
+
core.steerQueueItem(queueItemId);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
public removeQueueItem(queueItemId: string) {
|
|
327
|
+
const core = this._core.getState();
|
|
328
|
+
if (!core) throw new Error("Composer is not available");
|
|
329
|
+
core.removeQueueItem(queueItemId);
|
|
330
|
+
}
|
|
331
|
+
|
|
306
332
|
public setRole(role: MessageRole) {
|
|
307
333
|
const core = this._core.getState();
|
|
308
334
|
if (!core) throw new Error("Composer is not available");
|
|
@@ -23,6 +23,10 @@ import type {
|
|
|
23
23
|
SendOptions,
|
|
24
24
|
} from "../interfaces/composer-runtime-core";
|
|
25
25
|
import type { DictationAdapter } from "../../adapters/speech";
|
|
26
|
+
import {
|
|
27
|
+
EMPTY_QUEUE_ITEMS,
|
|
28
|
+
type QueueItemState,
|
|
29
|
+
} from "../../store/scopes/queue-item";
|
|
26
30
|
import { generateId } from "../../utils/id";
|
|
27
31
|
|
|
28
32
|
const isAttachmentComplete = (a: Attachment): a is CompleteAttachment =>
|
|
@@ -200,6 +204,13 @@ export abstract class BaseComposerRuntimeCore
|
|
|
200
204
|
this.handleCancel();
|
|
201
205
|
}
|
|
202
206
|
|
|
207
|
+
public get queue(): readonly QueueItemState[] {
|
|
208
|
+
return EMPTY_QUEUE_ITEMS;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public steerQueueItem(_queueItemId: string): void {}
|
|
212
|
+
public removeQueueItem(_queueItemId: string): void {}
|
|
213
|
+
|
|
203
214
|
protected abstract handleSend(
|
|
204
215
|
message: Omit<AppendMessage, "parentId" | "sourceId">,
|
|
205
216
|
options?: SendOptions,
|
|
@@ -6,6 +6,10 @@ import type {
|
|
|
6
6
|
ThreadComposerRuntimeCore,
|
|
7
7
|
} from "../interfaces/composer-runtime-core";
|
|
8
8
|
import type { ThreadRuntimeCore } from "../interfaces/thread-runtime-core";
|
|
9
|
+
import {
|
|
10
|
+
EMPTY_QUEUE_ITEMS,
|
|
11
|
+
type QueueItemState,
|
|
12
|
+
} from "../../store/scopes/queue-item";
|
|
9
13
|
import { BaseComposerRuntimeCore } from "./base-composer-runtime-core";
|
|
10
14
|
|
|
11
15
|
export class DefaultThreadComposerRuntimeCore
|
|
@@ -21,6 +25,18 @@ export class DefaultThreadComposerRuntimeCore
|
|
|
21
25
|
return !this.isEmpty && !this.runtime.isSendDisabled;
|
|
22
26
|
}
|
|
23
27
|
|
|
28
|
+
public override get queue(): readonly QueueItemState[] {
|
|
29
|
+
return this.runtime.getQueueItems?.() ?? EMPTY_QUEUE_ITEMS;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public override steerQueueItem(queueItemId: string): void {
|
|
33
|
+
this.runtime.steerQueueItem?.(queueItemId);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public override removeQueueItem(queueItemId: string): void {
|
|
37
|
+
this.runtime.removeQueueItem?.(queueItemId);
|
|
38
|
+
}
|
|
39
|
+
|
|
24
40
|
protected getAttachmentAdapter() {
|
|
25
41
|
return this.runtime.adapters?.attachments;
|
|
26
42
|
}
|
|
@@ -45,6 +61,7 @@ export class DefaultThreadComposerRuntimeCore
|
|
|
45
61
|
|
|
46
62
|
public connect() {
|
|
47
63
|
let lastIsSendDisabled = this.runtime.isSendDisabled;
|
|
64
|
+
let lastQueue = this.queue;
|
|
48
65
|
return this.runtime.subscribe(() => {
|
|
49
66
|
let changed = false;
|
|
50
67
|
if (this.canCancel !== this.runtime.capabilities.cancel) {
|
|
@@ -55,6 +72,10 @@ export class DefaultThreadComposerRuntimeCore
|
|
|
55
72
|
lastIsSendDisabled = this.runtime.isSendDisabled;
|
|
56
73
|
changed = true;
|
|
57
74
|
}
|
|
75
|
+
if (lastQueue !== this.queue) {
|
|
76
|
+
lastQueue = this.queue;
|
|
77
|
+
changed = true;
|
|
78
|
+
}
|
|
58
79
|
if (changed) this._notifySubscribers();
|
|
59
80
|
});
|
|
60
81
|
}
|
|
@@ -68,6 +89,7 @@ export class DefaultThreadComposerRuntimeCore
|
|
|
68
89
|
parentId: this.runtime.messages.at(-1)?.id ?? null,
|
|
69
90
|
sourceId: null,
|
|
70
91
|
startRun: options?.startRun,
|
|
92
|
+
steer: options?.steer,
|
|
71
93
|
});
|
|
72
94
|
}
|
|
73
95
|
|
|
@@ -4,6 +4,7 @@ import type { Attachment, CreateAttachment } from "../../types/attachment";
|
|
|
4
4
|
import type { Unsubscribe } from "../../types/unsubscribe";
|
|
5
5
|
import type { RunConfig } from "../../types/message";
|
|
6
6
|
import type { DictationAdapter } from "../../adapters/speech";
|
|
7
|
+
import type { QueueItemState } from "../../store/scopes/queue-item";
|
|
7
8
|
|
|
8
9
|
export type AttachmentAddErrorReason =
|
|
9
10
|
| "no-adapter"
|
|
@@ -45,6 +46,8 @@ export type DictationState = {
|
|
|
45
46
|
|
|
46
47
|
export type SendOptions = {
|
|
47
48
|
startRun?: boolean;
|
|
49
|
+
/** Process this message next; only meaningful with the `queue` capability. */
|
|
50
|
+
steer?: boolean;
|
|
48
51
|
};
|
|
49
52
|
|
|
50
53
|
export type ComposerRuntimeCore = Readonly<{
|
|
@@ -78,6 +81,10 @@ export type ComposerRuntimeCore = Readonly<{
|
|
|
78
81
|
send: (options?: SendOptions) => void;
|
|
79
82
|
cancel: () => void;
|
|
80
83
|
|
|
84
|
+
queue: readonly QueueItemState[];
|
|
85
|
+
steerQueueItem: (queueItemId: string) => void;
|
|
86
|
+
removeQueueItem: (queueItemId: string) => void;
|
|
87
|
+
|
|
81
88
|
dictation: DictationState | undefined;
|
|
82
89
|
startDictation: () => void;
|
|
83
90
|
stopDictation: () => void;
|
|
@@ -16,6 +16,7 @@ import type {
|
|
|
16
16
|
EditComposerRuntimeCore,
|
|
17
17
|
ThreadComposerRuntimeCore,
|
|
18
18
|
} from "./composer-runtime-core";
|
|
19
|
+
import type { QueueItemState } from "../../store/scopes/queue-item";
|
|
19
20
|
|
|
20
21
|
export type RuntimeCapabilities = {
|
|
21
22
|
readonly switchToBranch: boolean;
|
|
@@ -169,6 +170,10 @@ export type ThreadRuntimeCore = Readonly<{
|
|
|
169
170
|
getEditComposer: (messageId: string) => EditComposerRuntimeCore | undefined;
|
|
170
171
|
beginEdit: (messageId: string) => void;
|
|
171
172
|
|
|
173
|
+
getQueueItems?: () => readonly QueueItemState[];
|
|
174
|
+
steerQueueItem?: (queueItemId: string) => void;
|
|
175
|
+
removeQueueItem?: (queueItemId: string) => void;
|
|
176
|
+
|
|
172
177
|
speech: SpeechState | undefined;
|
|
173
178
|
voice: VoiceSessionState | undefined;
|
|
174
179
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AppendMessage } from "../../types/message";
|
|
2
|
+
import type { QueueItemState } from "../../store/scopes/queue-item";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The queue surface a runtime exposes so the composer can stay usable during a
|
|
6
|
+
* run and render the pending messages.
|
|
7
|
+
*/
|
|
8
|
+
export type ExternalThreadQueueAdapter = {
|
|
9
|
+
items: readonly QueueItemState[];
|
|
10
|
+
enqueue: (message: AppendMessage, options: { steer: boolean }) => void;
|
|
11
|
+
steer: (queueItemId: string) => void;
|
|
12
|
+
remove: (queueItemId: string) => void;
|
|
13
|
+
clear: (reason: "edit" | "reload" | "cancel-run") => void;
|
|
14
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { AppendMessage } from "../../types/message";
|
|
2
|
+
import {
|
|
3
|
+
EMPTY_QUEUE_ITEMS,
|
|
4
|
+
type QueueItemState,
|
|
5
|
+
} from "../../store/scopes/queue-item";
|
|
6
|
+
import { generateId } from "../../utils/id";
|
|
7
|
+
import { getThreadMessageText } from "../../utils/text";
|
|
8
|
+
import type { ExternalThreadQueueAdapter } from "./external-thread-queue-adapter";
|
|
9
|
+
|
|
10
|
+
export type MessageQueueDriver = {
|
|
11
|
+
run: (message: AppendMessage, options: { steer: boolean }) => void;
|
|
12
|
+
/** When omitted, `steer` degrades to "process next" instead of interrupting. */
|
|
13
|
+
cancel?: (() => void) | undefined;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type MessageQueueController = {
|
|
17
|
+
readonly adapter: ExternalThreadQueueAdapter;
|
|
18
|
+
/** Mark a run as in flight so concurrent sends buffer; call on the rising edge. */
|
|
19
|
+
notifyBusy: () => void;
|
|
20
|
+
/** Advances to the next pending message; call on the run's falling edge. */
|
|
21
|
+
notifyIdle: () => void;
|
|
22
|
+
subscribe: (callback: () => void) => () => void;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const createMessageQueue = (
|
|
26
|
+
driver: MessageQueueDriver,
|
|
27
|
+
): MessageQueueController => {
|
|
28
|
+
let items: readonly QueueItemState[] = EMPTY_QUEUE_ITEMS;
|
|
29
|
+
const messages = new Map<string, AppendMessage>();
|
|
30
|
+
const subscribers = new Set<() => void>();
|
|
31
|
+
|
|
32
|
+
let running = false;
|
|
33
|
+
// swallow the cancelled run's settle when steering so it does not double-advance
|
|
34
|
+
let suppressIdle = 0;
|
|
35
|
+
|
|
36
|
+
const notify = () => {
|
|
37
|
+
for (const callback of subscribers) callback();
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const setItems = (next: readonly QueueItemState[]) => {
|
|
41
|
+
items = next;
|
|
42
|
+
adapter.items = next;
|
|
43
|
+
notify();
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const advance = () => {
|
|
47
|
+
if (running || items.length === 0) return;
|
|
48
|
+
const head = items[0]!;
|
|
49
|
+
const message = messages.get(head.id);
|
|
50
|
+
messages.delete(head.id);
|
|
51
|
+
setItems(items.slice(1));
|
|
52
|
+
if (!message) return;
|
|
53
|
+
running = true;
|
|
54
|
+
driver.run(message, { steer: false });
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const enqueue = (message: AppendMessage, { steer }: { steer: boolean }) => {
|
|
58
|
+
const id = generateId();
|
|
59
|
+
const prompt = getThreadMessageText(message);
|
|
60
|
+
messages.set(id, message);
|
|
61
|
+
setItems([...items, { id, prompt }]);
|
|
62
|
+
if (steer) {
|
|
63
|
+
steerItem(id);
|
|
64
|
+
} else {
|
|
65
|
+
advance();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const steerItem = (queueItemId: string) => {
|
|
70
|
+
if (!messages.has(queueItemId)) return;
|
|
71
|
+
|
|
72
|
+
if (driver.cancel && running) {
|
|
73
|
+
const message = messages.get(queueItemId)!;
|
|
74
|
+
messages.delete(queueItemId);
|
|
75
|
+
setItems(items.filter((item) => item.id !== queueItemId));
|
|
76
|
+
suppressIdle++;
|
|
77
|
+
driver.cancel();
|
|
78
|
+
running = true;
|
|
79
|
+
driver.run(message, { steer: true });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const target = items.find((item) => item.id === queueItemId);
|
|
84
|
+
if (!target) return;
|
|
85
|
+
setItems([target, ...items.filter((item) => item.id !== queueItemId)]);
|
|
86
|
+
advance();
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const remove = (queueItemId: string) => {
|
|
90
|
+
if (!messages.delete(queueItemId)) return;
|
|
91
|
+
setItems(items.filter((item) => item.id !== queueItemId));
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const clear = () => {
|
|
95
|
+
if (items.length === 0) return;
|
|
96
|
+
messages.clear();
|
|
97
|
+
setItems(EMPTY_QUEUE_ITEMS);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const adapter: ExternalThreadQueueAdapter = {
|
|
101
|
+
items,
|
|
102
|
+
enqueue,
|
|
103
|
+
steer: steerItem,
|
|
104
|
+
remove,
|
|
105
|
+
clear,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
adapter,
|
|
110
|
+
notifyBusy: () => {
|
|
111
|
+
running = true;
|
|
112
|
+
},
|
|
113
|
+
notifyIdle: () => {
|
|
114
|
+
if (suppressIdle > 0) {
|
|
115
|
+
suppressIdle--;
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
running = false;
|
|
119
|
+
advance();
|
|
120
|
+
},
|
|
121
|
+
subscribe: (callback) => {
|
|
122
|
+
subscribers.add(callback);
|
|
123
|
+
return () => {
|
|
124
|
+
subscribers.delete(callback);
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
};
|
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
import type { ExportedMessageRepository } from "../../runtime/utils/message-repository";
|
|
18
18
|
import type { ReadonlyJSONValue } from "assistant-stream/utils";
|
|
19
19
|
import type { ToolExecutionStatus } from "../tool-invocations/ToolInvocationTracker";
|
|
20
|
+
import type { ExternalThreadQueueAdapter } from "../../runtime/queue/external-thread-queue-adapter";
|
|
20
21
|
|
|
21
22
|
export type ExternalStoreThreadData<TState extends "regular" | "archived"> = {
|
|
22
23
|
status: TState;
|
|
@@ -105,6 +106,8 @@ type ExternalStoreAdapterBase<T> = {
|
|
|
105
106
|
onExportExternalState?: (() => any) | undefined;
|
|
106
107
|
onLoadExternalState?: ((state: any) => void) | undefined;
|
|
107
108
|
onNew: (message: AppendMessage) => Promise<void>;
|
|
109
|
+
/** Opt in to message queuing. Typically produced by `createMessageQueue`. */
|
|
110
|
+
queue?: ExternalThreadQueueAdapter | undefined;
|
|
108
111
|
onEdit?: ((message: AppendMessage) => Promise<void>) | undefined;
|
|
109
112
|
onReload?: // TODO: remove parentId in 0.12.0
|
|
110
113
|
| ((parentId: string | null, config: StartRunConfig) => Promise<void>)
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
} from "../../runtime/utils/message-repository";
|
|
33
33
|
import { generateId } from "../../utils/id";
|
|
34
34
|
import { ToolInvocationTracker } from "../tool-invocations/ToolInvocationTracker";
|
|
35
|
+
import { EMPTY_QUEUE_ITEMS } from "../../store/scopes/queue-item";
|
|
35
36
|
|
|
36
37
|
const EMPTY_ARRAY: readonly ThreadSuggestion[] = Object.freeze([]);
|
|
37
38
|
|
|
@@ -155,7 +156,7 @@ export class ExternalStoreThreadRuntimeCore
|
|
|
155
156
|
unstable_copy: this._store.unstable_capabilities?.copy !== false,
|
|
156
157
|
attachments: !!this._store.adapters?.attachments,
|
|
157
158
|
feedback: !!this._store.adapters?.feedback,
|
|
158
|
-
queue:
|
|
159
|
+
queue: this._store.queue !== undefined,
|
|
159
160
|
};
|
|
160
161
|
if (!shallowEqual(this._capabilities, newCapabilities)) {
|
|
161
162
|
this._capabilities = newCapabilities;
|
|
@@ -389,6 +390,15 @@ export class ExternalStoreThreadRuntimeCore
|
|
|
389
390
|
}
|
|
390
391
|
|
|
391
392
|
public async append(message: AppendMessage): Promise<void> {
|
|
393
|
+
const isEdit = message.parentId !== (this.messages.at(-1)?.id ?? null);
|
|
394
|
+
|
|
395
|
+
// Buffering does not start a run, so the tool-abort below must wait until
|
|
396
|
+
// the queue flushes. By then the prior run (and its tools) has settled.
|
|
397
|
+
if (!isEdit && this._store.queue) {
|
|
398
|
+
this._store.queue.enqueue(message, { steer: message.steer ?? false });
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
|
|
392
402
|
// Auto-abort in-flight client-side tool executions when a new run is
|
|
393
403
|
// about to start. Without this, a tool that finishes after the new turn
|
|
394
404
|
// begins would feed a stale result into `onAddToolResult`, racing with
|
|
@@ -399,19 +409,36 @@ export class ExternalStoreThreadRuntimeCore
|
|
|
399
409
|
await this._toolInvocations?.abort();
|
|
400
410
|
}
|
|
401
411
|
|
|
402
|
-
if (
|
|
412
|
+
if (isEdit) {
|
|
403
413
|
if (!this._store.onEdit)
|
|
404
414
|
throw new Error("Runtime does not support editing messages.");
|
|
415
|
+
this._store.queue?.clear("edit");
|
|
405
416
|
await this._store.onEdit(message);
|
|
406
417
|
} else {
|
|
407
418
|
await this._store.onNew(message);
|
|
408
419
|
}
|
|
409
420
|
}
|
|
410
421
|
|
|
422
|
+
public getQueueItems() {
|
|
423
|
+
// The composer reads this during base-thread construction, before the
|
|
424
|
+
// constructor assigns `_store`, so guard against the unset field.
|
|
425
|
+
return this._store?.queue?.items ?? EMPTY_QUEUE_ITEMS;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
public steerQueueItem(queueItemId: string) {
|
|
429
|
+
this._store?.queue?.steer(queueItemId);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
public removeQueueItem(queueItemId: string) {
|
|
433
|
+
this._store?.queue?.remove(queueItemId);
|
|
434
|
+
}
|
|
435
|
+
|
|
411
436
|
public async startRun(config: StartRunConfig): Promise<void> {
|
|
412
437
|
if (!this._store.onReload)
|
|
413
438
|
throw new Error("Runtime does not support reloading messages.");
|
|
414
439
|
|
|
440
|
+
this._store.queue?.clear("reload");
|
|
441
|
+
|
|
415
442
|
// Auto-abort in-flight client-side tool executions when a run reloads;
|
|
416
443
|
// any results that land afterward would target a turn that no longer
|
|
417
444
|
// exists. See `append` above for full rationale.
|
|
@@ -457,6 +484,8 @@ export class ExternalStoreThreadRuntimeCore
|
|
|
457
484
|
if (!this._store.onCancel)
|
|
458
485
|
throw new Error("Runtime does not support cancelling runs.");
|
|
459
486
|
|
|
487
|
+
this._store.queue?.clear("cancel-run");
|
|
488
|
+
|
|
460
489
|
// Abort any in-flight client-side tool executions. Fire-and-forget —
|
|
461
490
|
// the abort resolves once executions settle, but we don't gate the
|
|
462
491
|
// cancel on it.
|
|
@@ -26,4 +26,10 @@ export type LocalRuntimeOptionsBase = {
|
|
|
26
26
|
* Names of tools that are allowed to interrupt the run in order to wait for human/external approval.
|
|
27
27
|
*/
|
|
28
28
|
unstable_humanToolNames?: string[] | undefined;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Opt in to message queuing: a message sent during a run is held in
|
|
32
|
+
* `composer.queue` and sent once the run settles. Steering runs it next.
|
|
33
|
+
*/
|
|
34
|
+
unstable_enableMessageQueue?: boolean | undefined;
|
|
29
35
|
};
|
|
@@ -22,6 +22,14 @@ import type {
|
|
|
22
22
|
} from "../../types/message";
|
|
23
23
|
import type { RunConfig } from "../../types/message";
|
|
24
24
|
import type { ModelContextProvider } from "../../model-context/types";
|
|
25
|
+
import {
|
|
26
|
+
createMessageQueue,
|
|
27
|
+
type MessageQueueController,
|
|
28
|
+
} from "../../runtime/queue/message-queue";
|
|
29
|
+
import {
|
|
30
|
+
EMPTY_QUEUE_ITEMS,
|
|
31
|
+
type QueueItemState,
|
|
32
|
+
} from "../../store/scopes/queue-item";
|
|
25
33
|
|
|
26
34
|
class AbortError extends Error {
|
|
27
35
|
override name = "AbortError";
|
|
@@ -54,6 +62,9 @@ export class LocalThreadRuntimeCore
|
|
|
54
62
|
|
|
55
63
|
private abortController: AbortController | null = null;
|
|
56
64
|
|
|
65
|
+
private _queue: MessageQueueController | null = null;
|
|
66
|
+
private _queueRunInFlight = false;
|
|
67
|
+
|
|
57
68
|
public readonly isDisabled = false;
|
|
58
69
|
public readonly isSendDisabled = false;
|
|
59
70
|
|
|
@@ -139,6 +150,31 @@ export class LocalThreadRuntimeCore
|
|
|
139
150
|
hasUpdates = true;
|
|
140
151
|
}
|
|
141
152
|
|
|
153
|
+
const canQueue = options.unstable_enableMessageQueue === true;
|
|
154
|
+
if (canQueue && !this._queue) {
|
|
155
|
+
this._queue = createMessageQueue({
|
|
156
|
+
run: (message) => {
|
|
157
|
+
// release the queue when the dispatch settles, even if it rejects
|
|
158
|
+
// before reaching startRun's finally, so a failure can't deadlock it
|
|
159
|
+
this._queueRunInFlight = true;
|
|
160
|
+
void this._runAppend(message)
|
|
161
|
+
.finally(() => {
|
|
162
|
+
this._queueRunInFlight = false;
|
|
163
|
+
this._queue?.notifyIdle();
|
|
164
|
+
})
|
|
165
|
+
.catch(() => {});
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
this._queue.subscribe(() => this._notifySubscribers());
|
|
169
|
+
} else if (!canQueue && this._queue) {
|
|
170
|
+
this._queue.adapter.clear("cancel-run");
|
|
171
|
+
this._queue = null;
|
|
172
|
+
}
|
|
173
|
+
if (this.capabilities.queue !== canQueue) {
|
|
174
|
+
this.capabilities.queue = canQueue;
|
|
175
|
+
hasUpdates = true;
|
|
176
|
+
}
|
|
177
|
+
|
|
142
178
|
if (hasUpdates) this._notifySubscribers();
|
|
143
179
|
}
|
|
144
180
|
|
|
@@ -183,6 +219,31 @@ export class LocalThreadRuntimeCore
|
|
|
183
219
|
}
|
|
184
220
|
|
|
185
221
|
public async append(message: AppendMessage): Promise<void> {
|
|
222
|
+
const isTail = message.parentId === (this.messages.at(-1)?.id ?? null);
|
|
223
|
+
const willRun = message.startRun ?? message.role === "user";
|
|
224
|
+
if (this._queue && willRun && isTail) {
|
|
225
|
+
this._queue.adapter.enqueue(message, { steer: message.steer ?? false });
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (this._queue && !isTail) this._queue.adapter.clear("edit");
|
|
229
|
+
return this._runAppend(message);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
public getQueueItems(): readonly QueueItemState[] {
|
|
233
|
+
// Reads can arrive during base-thread construction, before the queue field
|
|
234
|
+
// is assigned, so guard against the unset field.
|
|
235
|
+
return this._queue?.adapter.items ?? EMPTY_QUEUE_ITEMS;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public steerQueueItem(queueItemId: string): void {
|
|
239
|
+
this._queue?.adapter.steer(queueItemId);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
public removeQueueItem(queueItemId: string): void {
|
|
243
|
+
this._queue?.adapter.remove(queueItemId);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private async _runAppend(message: AppendMessage): Promise<void> {
|
|
186
247
|
this.ensureInitialized();
|
|
187
248
|
|
|
188
249
|
const initPromise = this._getInitializePromise?.();
|
|
@@ -254,6 +315,8 @@ export class LocalThreadRuntimeCore
|
|
|
254
315
|
this._notifyEventSubscribers("runStart", {});
|
|
255
316
|
|
|
256
317
|
try {
|
|
318
|
+
// mark busy for runs not started through the queue (regenerate, resume)
|
|
319
|
+
this._queue?.notifyBusy();
|
|
257
320
|
this._suggestions = [];
|
|
258
321
|
this._suggestionsController?.abort();
|
|
259
322
|
this._suggestionsController = null;
|
|
@@ -270,6 +333,11 @@ export class LocalThreadRuntimeCore
|
|
|
270
333
|
} while (shouldContinue(message, this._options.unstable_humanToolNames));
|
|
271
334
|
} finally {
|
|
272
335
|
this._notifyEventSubscribers("runEnd", {});
|
|
336
|
+
// queue-driven runs release from the driver settle handler; a direct
|
|
337
|
+
// run (regenerate, resume) releases here
|
|
338
|
+
if (!this._queueRunInFlight) {
|
|
339
|
+
queueMicrotask(() => this._queue?.notifyIdle());
|
|
340
|
+
}
|
|
273
341
|
}
|
|
274
342
|
|
|
275
343
|
this._suggestionsController = new AbortController();
|
|
@@ -474,12 +542,14 @@ export class LocalThreadRuntimeCore
|
|
|
474
542
|
}
|
|
475
543
|
|
|
476
544
|
public detach() {
|
|
545
|
+
this._queue?.adapter.clear("cancel-run");
|
|
477
546
|
const error = new AbortError(true);
|
|
478
547
|
this.abortController?.abort(error);
|
|
479
548
|
this.abortController = null;
|
|
480
549
|
}
|
|
481
550
|
|
|
482
551
|
public cancelRun() {
|
|
552
|
+
this._queue?.adapter.clear("cancel-run");
|
|
483
553
|
const error = new AbortError(false);
|
|
484
554
|
this.abortController?.abort(error);
|
|
485
555
|
this.abortController = null;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMemo, useState } from "react";
|
|
2
|
+
import { resource } from "@assistant-ui/tap";
|
|
2
3
|
import type { ClientOutput } from "@assistant-ui/store";
|
|
3
4
|
import type {
|
|
4
5
|
ChainOfThoughtState,
|
|
@@ -11,30 +12,28 @@ const COMPLETE_STATUS: MessagePartStatus = Object.freeze({
|
|
|
11
12
|
type: "complete",
|
|
12
13
|
});
|
|
13
14
|
|
|
14
|
-
export const ChainOfThoughtClient = resource(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const [collapsed, setCollapsed] = tapState(true);
|
|
15
|
+
export const ChainOfThoughtClient = resource(function ChainOfThoughtClient({
|
|
16
|
+
parts,
|
|
17
|
+
getMessagePart,
|
|
18
|
+
}: {
|
|
19
|
+
parts: readonly ChainOfThoughtPart[];
|
|
20
|
+
getMessagePart: (selector: { index: number }) => PartMethods;
|
|
21
|
+
}): ClientOutput<"chainOfThought"> {
|
|
22
|
+
const [collapsed, setCollapsed] = useState(true);
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
const status = useMemo(() => {
|
|
25
|
+
const lastPart = parts[parts.length - 1];
|
|
26
|
+
return lastPart?.status ?? COMPLETE_STATUS;
|
|
27
|
+
}, [parts]);
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
const state = useMemo<ChainOfThoughtState>(
|
|
30
|
+
() => ({ parts, collapsed, status }),
|
|
31
|
+
[parts, collapsed, status],
|
|
32
|
+
);
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
);
|
|
34
|
+
return {
|
|
35
|
+
getState: () => state,
|
|
36
|
+
setCollapsed,
|
|
37
|
+
part: getMessagePart,
|
|
38
|
+
};
|
|
39
|
+
});
|