@assistant-ui/core 0.2.22 → 0.3.0
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/thread-history.d.ts +8 -0
- package/dist/adapters/thread-history.d.ts.map +1 -1
- package/dist/internal.d.ts +3 -2
- package/dist/internal.js +3 -2
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +36 -21
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/types.d.ts.map +1 -1
- package/dist/model-context/types.js +13 -4
- package/dist/model-context/types.js.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js +3 -2
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +40 -55
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/client/interactable-model-context.js +1 -0
- package/dist/react/client/interactable-model-context.js.map +1 -1
- package/dist/react/interactables-legacy/useAssistantInteractable.js +1 -1
- package/dist/react/interactables-legacy/useAssistantInteractable.js.map +1 -1
- package/dist/react/interactables-legacy/useInteractableState.js +4 -3
- package/dist/react/interactables-legacy/useInteractableState.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/useAssistantTool.js +29 -25
- 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/useInteractable.js +1 -1
- package/dist/react/model-context/useInteractable.js.map +1 -1
- package/dist/react/model-context/useInteractableState.js +3 -2
- package/dist/react/model-context/useInteractableState.js.map +1 -1
- package/dist/react/model-context/useInteractableVersions.js +1 -0
- package/dist/react/model-context/useInteractableVersions.js.map +1 -1
- package/dist/react/model-context/useToolArgsStatus.js +1 -0
- package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.js +4 -3
- package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.js +2 -1
- package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarFeedback.js +3 -2
- package/dist/react/primitive-hooks/useActionBarFeedback.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.js +2 -1
- package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarSpeak.js +2 -1
- package/dist/react/primitive-hooks/useActionBarSpeak.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarStopSpeaking.js +2 -1
- package/dist/react/primitive-hooks/useActionBarStopSpeaking.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.js +2 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js +2 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerAddAttachment.js +2 -1
- package/dist/react/primitive-hooks/useComposerAddAttachment.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.js +2 -1
- package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerDictate.js +2 -1
- package/dist/react/primitive-hooks/useComposerDictate.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.js +2 -1
- package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useEditComposerCancel.js +2 -1
- package/dist/react/primitive-hooks/useEditComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useEditComposerSend.js +2 -1
- package/dist/react/primitive-hooks/useEditComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useMessageBranching.js +3 -2
- package/dist/react/primitive-hooks/useMessageBranching.js.map +1 -1
- package/dist/react/primitive-hooks/useMessageReload.js +2 -1
- package/dist/react/primitive-hooks/useMessageReload.js.map +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.js +8 -7
- package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemArchive.js +2 -1
- package/dist/react/primitive-hooks/useThreadListItemArchive.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemDelete.js +2 -1
- package/dist/react/primitive-hooks/useThreadListItemDelete.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemTrigger.js +2 -1
- package/dist/react/primitive-hooks/useThreadListItemTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemUnarchive.js +2 -1
- package/dist/react/primitive-hooks/useThreadListItemUnarchive.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.js +2 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListNew.js +2 -1
- package/dist/react/primitive-hooks/useThreadListNew.js.map +1 -1
- package/dist/react/primitive-hooks/useVoice.js +5 -13
- package/dist/react/primitive-hooks/useVoice.js.map +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.d.ts.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/message/MessageAttachments.d.ts.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/MessageParts.js +84 -122
- package/dist/react/primitives/message/MessageParts.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 +2 -2
- package/dist/react/providers/AttachmentByIndexProvider.js.map +1 -1
- package/dist/react/providers/ChainOfThoughtByIndicesProvider.js +1 -1
- package/dist/react/providers/ChainOfThoughtByIndicesProvider.js.map +1 -1
- package/dist/react/providers/ChainOfThoughtPartByIndexProvider.d.ts.map +1 -1
- package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js +30 -18
- package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js.map +1 -1
- package/dist/react/providers/MessageByIdProvider.js +2 -2
- package/dist/react/providers/MessageByIdProvider.js.map +1 -1
- package/dist/react/providers/MessageByIndexProvider.js +2 -2
- package/dist/react/providers/MessageByIndexProvider.js.map +1 -1
- package/dist/react/providers/PartByIndexProvider.d.ts.map +1 -1
- package/dist/react/providers/PartByIndexProvider.js +30 -18
- package/dist/react/providers/PartByIndexProvider.js.map +1 -1
- package/dist/react/providers/QueueItemByIndexProvider.js +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 +1 -1
- package/dist/react/providers/SuggestionByIndexProvider.js.map +1 -1
- package/dist/react/providers/TextMessagePartProvider.js +1 -0
- package/dist/react/providers/TextMessagePartProvider.js.map +1 -1
- package/dist/react/providers/ThreadListItemByIndexProvider.js +1 -1
- package/dist/react/providers/ThreadListItemByIndexProvider.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +3 -3
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +6 -4
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +31 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +42 -20
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +12 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js +2 -1
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +75 -73
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/createRuntimeExtras.js +1 -1
- package/dist/react/runtimes/createRuntimeExtras.js.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/useExternalStoreSharedOptions.js +1 -0
- package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
- package/dist/react/runtimes/useLocalRuntime.d.ts +0 -1
- package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
- package/dist/react/types/scopes/tools.d.ts +0 -6
- package/dist/react/types/scopes/tools.d.ts.map +1 -1
- package/dist/react/utils/groupParts.d.ts +1 -3
- package/dist/react/utils/groupParts.d.ts.map +1 -1
- package/dist/react/utils/groupParts.js +1 -3
- package/dist/react/utils/groupParts.js.map +1 -1
- package/dist/runtime/api/assistant-runtime.d.ts +1 -1
- package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
- package/dist/runtime/api/assistant-runtime.js +1 -1
- package/dist/runtime/api/assistant-runtime.js.map +1 -1
- package/dist/runtime/api/attachment-runtime.d.ts +1 -1
- package/dist/runtime/api/attachment-runtime.d.ts.map +1 -1
- package/dist/runtime/api/attachment-runtime.js +1 -1
- package/dist/runtime/api/attachment-runtime.js.map +1 -1
- package/dist/runtime/api/composer-runtime.d.ts +2 -2
- package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.js +2 -2
- package/dist/runtime/api/composer-runtime.js.map +1 -1
- package/dist/runtime/api/message-part-runtime.d.ts +4 -4
- package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-part-runtime.js +3 -3
- package/dist/runtime/api/message-part-runtime.js.map +1 -1
- package/dist/runtime/api/message-runtime.d.ts +1 -1
- package/dist/runtime/api/message-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-runtime.js +2 -2
- package/dist/runtime/api/message-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.d.ts +1 -1
- package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.js +2 -2
- package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +1 -1
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts +2 -2
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.js +2 -2
- package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +4 -2
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +12 -0
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/internal.d.ts +2 -1
- package/dist/runtimes/internal.js +2 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +44 -13
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +32 -27
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +2 -0
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/no-op-composer-client.js +1 -0
- package/dist/store/clients/no-op-composer-client.js.map +1 -1
- package/dist/store/clients/runtime-adapter.js +3 -3
- package/dist/store/clients/runtime-adapter.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js +1 -0
- 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 +17 -15
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scopes/thread.d.ts +1 -0
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/dist/subscribable/subscribable.d.ts +3 -3
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/subscribable/subscribable.js +3 -3
- package/dist/subscribable/subscribable.js.map +1 -1
- package/package.json +8 -8
- package/src/adapters/thread-history.ts +8 -0
- package/src/internal.ts +1 -1
- package/src/model-context/frame/host.test.ts +47 -0
- package/src/model-context/frame/host.ts +46 -19
- package/src/model-context/types.ts +16 -6
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +17 -7
- package/src/react/client/Tools.ts +0 -7
- package/src/react/interactables-legacy/useAssistantInteractable.ts +1 -1
- package/src/react/interactables-legacy/useInteractableState.ts +3 -3
- package/src/react/model-context/useAssistantContext.ts +1 -1
- package/src/react/model-context/useAssistantDataUI.ts +1 -1
- package/src/react/model-context/useAssistantInstructions.ts +1 -1
- package/src/react/model-context/useAssistantTool.ts +2 -2
- package/src/react/model-context/useAssistantToolUI.ts +1 -1
- package/src/react/model-context/useAuiToolOverrides.ts +1 -1
- package/src/react/model-context/useInteractable.ts +1 -1
- package/src/react/model-context/useInteractableState.ts +2 -2
- package/src/react/primitive-hooks/useActionBarCopy.test.ts +2 -2
- package/src/react/primitive-hooks/useActionBarCopy.ts +3 -3
- package/src/react/primitive-hooks/useActionBarEdit.ts +1 -1
- package/src/react/primitive-hooks/useActionBarFeedback.ts +2 -2
- package/src/react/primitive-hooks/useActionBarReload.ts +1 -1
- package/src/react/primitive-hooks/useActionBarSpeak.ts +1 -1
- package/src/react/primitive-hooks/useActionBarStopSpeaking.ts +1 -1
- package/src/react/primitive-hooks/useBranchPickerNext.ts +1 -1
- package/src/react/primitive-hooks/useBranchPickerPrevious.ts +1 -1
- package/src/react/primitive-hooks/useComposerAddAttachment.ts +1 -1
- package/src/react/primitive-hooks/useComposerCancel.ts +1 -1
- package/src/react/primitive-hooks/useComposerDictate.ts +1 -1
- package/src/react/primitive-hooks/useComposerSend.ts +1 -1
- package/src/react/primitive-hooks/useEditComposerCancel.ts +1 -1
- package/src/react/primitive-hooks/useEditComposerSend.ts +1 -1
- package/src/react/primitive-hooks/useMessageBranching.ts +2 -2
- package/src/react/primitive-hooks/useMessageReload.ts +1 -1
- package/src/react/primitive-hooks/useSuggestionTrigger.ts +9 -9
- package/src/react/primitive-hooks/useThreadListItemArchive.ts +1 -1
- package/src/react/primitive-hooks/useThreadListItemDelete.ts +1 -1
- package/src/react/primitive-hooks/useThreadListItemTrigger.ts +1 -1
- package/src/react/primitive-hooks/useThreadListItemUnarchive.ts +1 -1
- package/src/react/primitive-hooks/useThreadListLoadMore.ts +1 -1
- package/src/react/primitive-hooks/useThreadListNew.ts +1 -1
- package/src/react/primitive-hooks/useVoice.ts +5 -5
- package/src/react/primitives/chainOfThought/ChainOfThoughtParts.tsx +1 -1
- package/src/react/primitives/composer/ComposerAttachments.tsx +1 -1
- package/src/react/primitives/composer/ComposerQueue.tsx +1 -3
- package/src/react/primitives/message/MessageAttachments.tsx +1 -3
- package/src/react/primitives/message/MessageParts.tsx +9 -9
- package/src/react/primitives/thread/ThreadMessages.tsx +1 -1
- package/src/react/primitives/thread/ThreadSuggestions.tsx +1 -1
- package/src/react/primitives/threadList/ThreadListItems.tsx +1 -1
- package/src/react/providers/AttachmentByIndexProvider.tsx +2 -2
- package/src/react/providers/ChainOfThoughtByIndicesProvider.tsx +1 -1
- package/src/react/providers/ChainOfThoughtPartByIndexProvider.tsx +2 -19
- package/src/react/providers/MessageByIdProvider.tsx +2 -2
- package/src/react/providers/MessageByIndexProvider.tsx +2 -2
- package/src/react/providers/PartByIndexProvider.tsx +2 -16
- package/src/react/providers/QueueItemByIndexProvider.tsx +1 -1
- package/src/react/providers/ReadonlyThreadProvider.tsx +1 -1
- package/src/react/providers/SuggestionByIndexProvider.tsx +1 -1
- package/src/react/providers/ThreadListItemByIndexProvider.tsx +1 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +3 -3
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +20 -6
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +34 -0
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +32 -7
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +47 -16
- package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +5 -1
- package/src/react/runtimes/cloud/auiV0.ts +14 -0
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +90 -88
- package/src/react/runtimes/createRuntimeExtras.test.ts +1 -1
- package/src/react/runtimes/createRuntimeExtras.ts +1 -1
- package/src/react/runtimes/external-message-converter.test.ts +346 -0
- package/src/react/runtimes/external-message-converter.ts +1 -1
- package/src/react/runtimes/useLocalRuntime.test.tsx +43 -0
- package/src/react/types/scopes/tools.ts +0 -6
- package/src/react/utils/groupParts.ts +1 -7
- package/src/runtime/api/assistant-runtime.ts +4 -1
- package/src/runtime/api/attachment-runtime.ts +8 -2
- package/src/runtime/api/composer-runtime.ts +9 -5
- package/src/runtime/api/message-part-runtime.ts +10 -3
- package/src/runtime/api/message-runtime.ts +7 -2
- package/src/runtime/api/thread-list-item-runtime.ts +7 -2
- package/src/runtime/api/thread-list-runtime.ts +10 -2
- package/src/runtime/base/base-thread-runtime-core.ts +5 -1
- package/src/runtime/base/default-edit-composer-runtime-core.ts +14 -2
- package/src/runtime/base/default-thread-composer-runtime-core.ts +11 -1
- package/src/runtime/utils/message-repository.ts +19 -13
- package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +15 -0
- package/src/runtimes/internal.ts +3 -0
- package/src/runtimes/local/local-thread-runtime-core.test.ts +596 -0
- package/src/runtimes/local/local-thread-runtime-core.ts +85 -21
- package/src/runtimes/local/should-continue.test.ts +122 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +9 -10
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +38 -32
- package/src/store/clients/model-context-client.test.ts +21 -1
- package/src/store/clients/runtime-adapter.ts +3 -3
- package/src/store/runtime-clients/thread-runtime-client.ts +2 -1
- package/src/store/scopes/thread.ts +1 -0
- package/src/subscribable/subscribable.ts +16 -8
- package/src/tests/MessageRepository.test.ts +12 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-position.test.ts +121 -0
- package/src/tests/auiV0Encode.test.ts +74 -0
- package/src/tests/base-composer-runtime-core.test.ts +422 -0
- package/src/tests/external-store-thread-list-runtime-core.test.ts +6 -6
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +575 -0
- package/src/tests/external-store-thread-runtime-core.test.ts +55 -1
- package/src/tests/groupParts.test.ts +3 -48
- package/src/tests/OptimisticState-delete-crash.test.ts +0 -208
|
@@ -68,6 +68,45 @@ export class LocalThreadRuntimeCore
|
|
|
68
68
|
private _queue: MessageQueueController | null = null;
|
|
69
69
|
private _queueRunInFlight = false;
|
|
70
70
|
|
|
71
|
+
private _historyWrites = new Map<string, Promise<void>>();
|
|
72
|
+
|
|
73
|
+
// Writes for one message id must land in issue order; an earlier paused
|
|
74
|
+
// snapshot arriving after the terminal write would resurrect the pause.
|
|
75
|
+
private _chainHistoryWrite(
|
|
76
|
+
id: string,
|
|
77
|
+
write: () => Promise<void>,
|
|
78
|
+
): Promise<void> {
|
|
79
|
+
const next = (this._historyWrites.get(id) ?? Promise.resolve()).then(
|
|
80
|
+
write,
|
|
81
|
+
write,
|
|
82
|
+
);
|
|
83
|
+
const stored = next.then(
|
|
84
|
+
() => {},
|
|
85
|
+
() => {},
|
|
86
|
+
);
|
|
87
|
+
this._historyWrites.set(id, stored);
|
|
88
|
+
void stored.then(() => {
|
|
89
|
+
if (this._historyWrites.get(id) === stored) {
|
|
90
|
+
this._historyWrites.delete(id);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
return next;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// A decision recorded on a still-paused message must reach history before
|
|
97
|
+
// the run resumes, or a refresh would restore the message without it.
|
|
98
|
+
private _persistPausedMessage(
|
|
99
|
+
parentId: string | null,
|
|
100
|
+
message: ThreadAssistantMessage,
|
|
101
|
+
) {
|
|
102
|
+
if (message.status?.type !== "requires-action") return;
|
|
103
|
+
const history = this._options.adapters.history;
|
|
104
|
+
if (!history?.update) return;
|
|
105
|
+
const update = history.update.bind(history);
|
|
106
|
+
const item = { parentId, message, runConfig: this._lastRunConfig };
|
|
107
|
+
this._chainHistoryWrite(message.id, () => update(item)).catch(() => {});
|
|
108
|
+
}
|
|
109
|
+
|
|
71
110
|
public readonly isDisabled = false;
|
|
72
111
|
public readonly isSendDisabled = false;
|
|
73
112
|
|
|
@@ -351,6 +390,12 @@ export class LocalThreadRuntimeCore
|
|
|
351
390
|
): Promise<void> {
|
|
352
391
|
this._notifyEventSubscribers("runStart", {});
|
|
353
392
|
|
|
393
|
+
// A run entered on a requires-action message resumes a pause an
|
|
394
|
+
// update-capable adapter already holds (written at pause time or loaded).
|
|
395
|
+
const alreadyPersisted =
|
|
396
|
+
message.status?.type === "requires-action" &&
|
|
397
|
+
this._options.adapters.history?.update !== undefined;
|
|
398
|
+
|
|
354
399
|
try {
|
|
355
400
|
// mark busy for runs not started through the queue (regenerate, resume)
|
|
356
401
|
this._queue?.notifyBusy();
|
|
@@ -364,6 +409,7 @@ export class LocalThreadRuntimeCore
|
|
|
364
409
|
parentId,
|
|
365
410
|
message,
|
|
366
411
|
runConfig,
|
|
412
|
+
alreadyPersisted,
|
|
367
413
|
runCallback,
|
|
368
414
|
);
|
|
369
415
|
runCallback = undefined;
|
|
@@ -406,6 +452,7 @@ export class LocalThreadRuntimeCore
|
|
|
406
452
|
parentId: string | null,
|
|
407
453
|
message: ThreadAssistantMessage,
|
|
408
454
|
runConfig: RunConfig | undefined,
|
|
455
|
+
alreadyPersisted: boolean,
|
|
409
456
|
runCallback?: ChatModelAdapter["run"],
|
|
410
457
|
) {
|
|
411
458
|
const messages = parentId ? this.repository.getMessages(parentId) : [];
|
|
@@ -471,17 +518,18 @@ export class LocalThreadRuntimeCore
|
|
|
471
518
|
|
|
472
519
|
const maxSteps = this._options.maxSteps ?? 2;
|
|
473
520
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
521
|
+
try {
|
|
522
|
+
const steps = message.metadata?.steps?.length ?? 0;
|
|
523
|
+
if (steps >= maxSteps) {
|
|
524
|
+
updateMessage({
|
|
525
|
+
status: {
|
|
526
|
+
type: "incomplete",
|
|
527
|
+
reason: "tool-calls",
|
|
528
|
+
},
|
|
529
|
+
});
|
|
530
|
+
return message;
|
|
531
|
+
}
|
|
532
|
+
|
|
485
533
|
updateMessage({
|
|
486
534
|
status: {
|
|
487
535
|
type: "running",
|
|
@@ -491,9 +539,7 @@ export class LocalThreadRuntimeCore
|
|
|
491
539
|
// Switch to the new message branch right after adding it for the first time
|
|
492
540
|
this.repository.resetHead(message.id);
|
|
493
541
|
this._notifySubscribers();
|
|
494
|
-
}
|
|
495
542
|
|
|
496
|
-
try {
|
|
497
543
|
this._lastRunConfig = runConfig ?? {};
|
|
498
544
|
// unstable_composerMetadata is composer-only (stamped onto the outgoing
|
|
499
545
|
// message); never expose it to the chat-model adapter's run context.
|
|
@@ -565,15 +611,29 @@ export class LocalThreadRuntimeCore
|
|
|
565
611
|
} finally {
|
|
566
612
|
this.abortController = null;
|
|
567
613
|
|
|
568
|
-
|
|
614
|
+
const history = this._options.adapters.history;
|
|
615
|
+
const item = {
|
|
616
|
+
parentId,
|
|
617
|
+
message,
|
|
618
|
+
runConfig: this._lastRunConfig,
|
|
619
|
+
};
|
|
620
|
+
const isTerminal =
|
|
569
621
|
message.status.type === "complete" ||
|
|
570
|
-
message.status.type === "incomplete"
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
622
|
+
message.status.type === "incomplete";
|
|
623
|
+
const isPausing =
|
|
624
|
+
message.status.type === "requires-action" &&
|
|
625
|
+
!shouldContinue(message, this._options.unstable_humanToolNames);
|
|
626
|
+
|
|
627
|
+
// Pauses are written only for adapters that can rewrite the entry later;
|
|
628
|
+
// an append-only adapter would strand a half-finished run in history.
|
|
629
|
+
if (isTerminal || (isPausing && history?.update)) {
|
|
630
|
+
const write =
|
|
631
|
+
alreadyPersisted && history?.update
|
|
632
|
+
? history.update.bind(history)
|
|
633
|
+
: history?.append.bind(history);
|
|
634
|
+
if (write) {
|
|
635
|
+
await this._chainHistoryWrite(message.id, () => write(item));
|
|
636
|
+
}
|
|
577
637
|
}
|
|
578
638
|
}
|
|
579
639
|
return message;
|
|
@@ -643,6 +703,8 @@ export class LocalThreadRuntimeCore
|
|
|
643
703
|
shouldContinue(message, this._options.unstable_humanToolNames)
|
|
644
704
|
) {
|
|
645
705
|
this._runLoop(parentId, message, this._lastRunConfig).catch(() => {});
|
|
706
|
+
} else if (added) {
|
|
707
|
+
this._persistPausedMessage(parentId, message);
|
|
646
708
|
}
|
|
647
709
|
}
|
|
648
710
|
|
|
@@ -721,6 +783,8 @@ export class LocalThreadRuntimeCore
|
|
|
721
783
|
shouldContinue(message, this._options.unstable_humanToolNames)
|
|
722
784
|
) {
|
|
723
785
|
this._runLoop(parentId, message, this._lastRunConfig).catch(() => {});
|
|
786
|
+
} else {
|
|
787
|
+
this._persistPausedMessage(parentId, message);
|
|
724
788
|
}
|
|
725
789
|
}
|
|
726
790
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import type { ThreadAssistantMessage } from "../../types/message";
|
|
3
|
+
import { shouldContinue } from "./should-continue";
|
|
4
|
+
|
|
5
|
+
const makeMessage = (
|
|
6
|
+
overrides: Partial<ThreadAssistantMessage>,
|
|
7
|
+
): ThreadAssistantMessage => ({
|
|
8
|
+
id: "msg-1",
|
|
9
|
+
role: "assistant",
|
|
10
|
+
createdAt: new Date(),
|
|
11
|
+
content: [],
|
|
12
|
+
status: { type: "complete", reason: "stop" },
|
|
13
|
+
metadata: {
|
|
14
|
+
unstable_state: null,
|
|
15
|
+
unstable_annotations: [],
|
|
16
|
+
unstable_data: [],
|
|
17
|
+
steps: [],
|
|
18
|
+
custom: {},
|
|
19
|
+
},
|
|
20
|
+
...overrides,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const toolCall = (toolName: string, result?: unknown) => ({
|
|
24
|
+
type: "tool-call" as const,
|
|
25
|
+
toolCallId: `call-${toolName}`,
|
|
26
|
+
toolName,
|
|
27
|
+
args: {},
|
|
28
|
+
argsText: "{}",
|
|
29
|
+
...(result !== undefined ? { result } : {}),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe("shouldContinue", () => {
|
|
33
|
+
it("returns false when status is not requires-action", () => {
|
|
34
|
+
const msg = makeMessage({
|
|
35
|
+
status: { type: "complete", reason: "stop" },
|
|
36
|
+
});
|
|
37
|
+
expect(shouldContinue(msg, undefined)).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("returns false when reason is not tool-calls", () => {
|
|
41
|
+
const msg = makeMessage({
|
|
42
|
+
status: { type: "requires-action", reason: "interrupt" },
|
|
43
|
+
});
|
|
44
|
+
expect(shouldContinue(msg, undefined)).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("returns true when all tool calls have results (no humanToolNames)", () => {
|
|
48
|
+
const msg = makeMessage({
|
|
49
|
+
status: { type: "requires-action", reason: "tool-calls" },
|
|
50
|
+
content: [toolCall("search", "found it"), toolCall("calculate", 42)],
|
|
51
|
+
});
|
|
52
|
+
expect(shouldContinue(msg, undefined)).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("returns false when some tool calls have no result (no humanToolNames)", () => {
|
|
56
|
+
const msg = makeMessage({
|
|
57
|
+
status: { type: "requires-action", reason: "tool-calls" },
|
|
58
|
+
content: [toolCall("search", "found it"), toolCall("calculate")],
|
|
59
|
+
});
|
|
60
|
+
expect(shouldContinue(msg, undefined)).toBe(false);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("returns true when unresolved tool call is not a human tool", () => {
|
|
64
|
+
const msg = makeMessage({
|
|
65
|
+
status: { type: "requires-action", reason: "tool-calls" },
|
|
66
|
+
content: [toolCall("auto-tool")],
|
|
67
|
+
});
|
|
68
|
+
expect(shouldContinue(msg, ["human-approval"])).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("returns false when unresolved tool call IS a human tool", () => {
|
|
72
|
+
const msg = makeMessage({
|
|
73
|
+
status: { type: "requires-action", reason: "tool-calls" },
|
|
74
|
+
content: [toolCall("human-approval")],
|
|
75
|
+
});
|
|
76
|
+
expect(shouldContinue(msg, ["human-approval"])).toBe(false);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("returns true for non-tool-call content parts", () => {
|
|
80
|
+
const msg = makeMessage({
|
|
81
|
+
status: { type: "requires-action", reason: "tool-calls" },
|
|
82
|
+
content: [
|
|
83
|
+
{ type: "text", text: "Hello" } as any,
|
|
84
|
+
toolCall("search", "done"),
|
|
85
|
+
],
|
|
86
|
+
});
|
|
87
|
+
expect(shouldContinue(msg, undefined)).toBe(true);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("returns false while a tool call has a pending approval", () => {
|
|
91
|
+
const msg = makeMessage({
|
|
92
|
+
status: { type: "requires-action", reason: "tool-calls" },
|
|
93
|
+
content: [{ ...toolCall("deploy"), approval: { id: "a1" } }],
|
|
94
|
+
});
|
|
95
|
+
expect(shouldContinue(msg, undefined)).toBe(false);
|
|
96
|
+
expect(shouldContinue(msg, ["human-approval"])).toBe(false);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("returns true when a decided approval has no result", () => {
|
|
100
|
+
const msg = makeMessage({
|
|
101
|
+
status: { type: "requires-action", reason: "tool-calls" },
|
|
102
|
+
content: [
|
|
103
|
+
{ ...toolCall("deploy"), approval: { id: "a1", approved: true } },
|
|
104
|
+
],
|
|
105
|
+
});
|
|
106
|
+
expect(shouldContinue(msg, undefined)).toBe(true);
|
|
107
|
+
expect(shouldContinue(msg, ["human-approval"])).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("exempts approval-gated tool calls from the human tool result requirement", () => {
|
|
111
|
+
const msg = makeMessage({
|
|
112
|
+
status: { type: "requires-action", reason: "tool-calls" },
|
|
113
|
+
content: [
|
|
114
|
+
{
|
|
115
|
+
...toolCall("human-approval"),
|
|
116
|
+
approval: { id: "a1", approved: true },
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
});
|
|
120
|
+
expect(shouldContinue(msg, ["human-approval"])).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
@@ -3,7 +3,6 @@ import { describe, expect, it, vi } from "vitest";
|
|
|
3
3
|
import {
|
|
4
4
|
ToolInvocationTracker,
|
|
5
5
|
type ToolExecutionStatus,
|
|
6
|
-
type ToolInvocationTrackerSnapshot,
|
|
7
6
|
} from "./ToolInvocationTracker";
|
|
8
7
|
import type {
|
|
9
8
|
ThreadAssistantMessage,
|
|
@@ -34,7 +33,7 @@ async function waitFor(
|
|
|
34
33
|
const createState = (
|
|
35
34
|
messages: ThreadAssistantMessage[],
|
|
36
35
|
isRunning: boolean = true,
|
|
37
|
-
):
|
|
36
|
+
): ToolInvocationTracker.Snapshot => ({
|
|
38
37
|
messages: messages as readonly ThreadMessage[],
|
|
39
38
|
isRunning,
|
|
40
39
|
});
|
|
@@ -152,13 +151,13 @@ describe("ToolInvocationTracker", () => {
|
|
|
152
151
|
}
|
|
153
152
|
});
|
|
154
153
|
|
|
155
|
-
it("does not auto-submit a parse-error result when divergent argsText closes without a backend result
|
|
156
|
-
//
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
154
|
+
it("does not auto-submit a parse-error result when divergent argsText closes without a backend result", async () => {
|
|
155
|
+
// A human-in-the-loop tool whose argsText diverges mid-stream and never
|
|
156
|
+
// re-converges, with no backend result at close time. The args stream must
|
|
157
|
+
// not close on the divergent snapshot (which holds a stale prefix the
|
|
158
|
+
// execution path would parse), so no bogus parse-error result is
|
|
159
|
+
// auto-submitted to resume the host graph and abandon the pending
|
|
160
|
+
// interrupt.
|
|
162
161
|
const execute = vi.fn(async () => ({ forecast: "ok" }));
|
|
163
162
|
const streamCall = vi.fn((_reader, { human }) => {
|
|
164
163
|
// Request human input immediately — sets up the pending interrupt.
|
|
@@ -236,7 +235,7 @@ describe("ToolInvocationTracker", () => {
|
|
|
236
235
|
}
|
|
237
236
|
});
|
|
238
237
|
|
|
239
|
-
it("does not auto-submit a parse-error result for a non-executable tool whose divergent argsText closes
|
|
238
|
+
it("does not auto-submit a parse-error result for a non-executable tool whose divergent argsText closes", async () => {
|
|
240
239
|
// Same close-gating mismatch as the executable case, but for a tool with
|
|
241
240
|
// no frontend execute. Closing on the divergent complete snapshot would
|
|
242
241
|
// still parse the incomplete stale prefix and fabricate a parse-error
|
|
@@ -35,34 +35,6 @@ export type AddToolResultCommand = {
|
|
|
35
35
|
readonly modelContent?: readonly ToolModelContentPart[];
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
export type ToolInvocationTrackerSnapshot = {
|
|
39
|
-
readonly messages: readonly ThreadMessage[];
|
|
40
|
-
/** Whether the producing runtime is currently streaming new output. */
|
|
41
|
-
readonly isRunning: boolean;
|
|
42
|
-
/**
|
|
43
|
-
* Whether the producing runtime is still loading historical state.
|
|
44
|
-
* When `true`, every snapshot is treated as historical (no `streamCall` /
|
|
45
|
-
* `execute` fires). When `false`, processing resumes as live.
|
|
46
|
-
*/
|
|
47
|
-
readonly isLoading?: boolean;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export type ToolInvocationTrackerCallbacks = {
|
|
51
|
-
/**
|
|
52
|
-
* Invoked when a client-side `execute()` returns a result and the runtime
|
|
53
|
-
* needs to feed it back into the conversation.
|
|
54
|
-
*/
|
|
55
|
-
onResult: (command: AddToolResultCommand) => void;
|
|
56
|
-
/**
|
|
57
|
-
* Invoked whenever the per-tool-call status map changes (executing /
|
|
58
|
-
* interrupt / cleared). The callback receives a fresh map; mutating the
|
|
59
|
-
* argument is not supported.
|
|
60
|
-
*/
|
|
61
|
-
onStatusesChange: (
|
|
62
|
-
statuses: ReadonlyMap<string, ToolExecutionStatus>,
|
|
63
|
-
) => void;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
38
|
type ToolCallEntry = {
|
|
67
39
|
toolName: string;
|
|
68
40
|
argsText: string;
|
|
@@ -123,10 +95,12 @@ const isEquivalentCompleteArgsText = (previous: string, next: string) => {
|
|
|
123
95
|
* the hot message-processing path, so a malformed snapshot must never crash
|
|
124
96
|
* the host runtime. See ./EDGE_CASES.md for the known non-trivial state
|
|
125
97
|
* transitions and what each does today.
|
|
98
|
+
*
|
|
99
|
+
* @deprecated Internal — for framework bindings; not a public API. May change without notice.
|
|
126
100
|
*/
|
|
127
101
|
export class ToolInvocationTracker {
|
|
128
102
|
private readonly _getTools: () => Record<string, Tool> | undefined;
|
|
129
|
-
private readonly _callbacks:
|
|
103
|
+
private readonly _callbacks: ToolInvocationTracker.Callbacks;
|
|
130
104
|
|
|
131
105
|
private readonly _entries = new Map<string, ToolCallEntry>();
|
|
132
106
|
/**
|
|
@@ -157,7 +131,7 @@ export class ToolInvocationTracker {
|
|
|
157
131
|
private _pendingRestore = true;
|
|
158
132
|
|
|
159
133
|
/** Cached last snapshot, used to skip processing on identical re-renders. */
|
|
160
|
-
private _lastSnapshot:
|
|
134
|
+
private _lastSnapshot: ToolInvocationTracker.Snapshot | null = null;
|
|
161
135
|
private _isRunning = false;
|
|
162
136
|
|
|
163
137
|
private _controller!: ReturnType<typeof createAssistantStreamController>[1];
|
|
@@ -175,7 +149,7 @@ export class ToolInvocationTracker {
|
|
|
175
149
|
|
|
176
150
|
constructor(
|
|
177
151
|
getTools: () => Record<string, Tool> | undefined,
|
|
178
|
-
callbacks:
|
|
152
|
+
callbacks: ToolInvocationTracker.Callbacks,
|
|
179
153
|
) {
|
|
180
154
|
this._getTools = getTools;
|
|
181
155
|
this._callbacks = callbacks;
|
|
@@ -235,7 +209,7 @@ export class ToolInvocationTracker {
|
|
|
235
209
|
* Feed the next observed snapshot into the tracker. Called from the host
|
|
236
210
|
* runtime whenever its message list / running state changes.
|
|
237
211
|
*/
|
|
238
|
-
public setState(snapshot:
|
|
212
|
+
public setState(snapshot: ToolInvocationTracker.Snapshot): void {
|
|
239
213
|
try {
|
|
240
214
|
// Recover from a dead pipeline before processing anything. We demote
|
|
241
215
|
// all active entries to "restored" so the rebuilt pipeline does not
|
|
@@ -782,3 +756,35 @@ export class ToolInvocationTracker {
|
|
|
782
756
|
}
|
|
783
757
|
}
|
|
784
758
|
}
|
|
759
|
+
|
|
760
|
+
export namespace ToolInvocationTracker {
|
|
761
|
+
export type ExecutionStatus = ToolExecutionStatus;
|
|
762
|
+
|
|
763
|
+
export type Snapshot = {
|
|
764
|
+
readonly messages: readonly ThreadMessage[];
|
|
765
|
+
/** Whether the producing runtime is currently streaming new output. */
|
|
766
|
+
readonly isRunning: boolean;
|
|
767
|
+
/**
|
|
768
|
+
* Whether the producing runtime is still loading historical state.
|
|
769
|
+
* When `true`, every snapshot is treated as historical (no `streamCall` /
|
|
770
|
+
* `execute` fires). When `false`, processing resumes as live.
|
|
771
|
+
*/
|
|
772
|
+
readonly isLoading?: boolean;
|
|
773
|
+
};
|
|
774
|
+
|
|
775
|
+
export type Callbacks = {
|
|
776
|
+
/**
|
|
777
|
+
* Invoked when a client-side `execute()` returns a result and the runtime
|
|
778
|
+
* needs to feed it back into the conversation.
|
|
779
|
+
*/
|
|
780
|
+
onResult: (command: AddToolResultCommand) => void;
|
|
781
|
+
/**
|
|
782
|
+
* Invoked whenever the per-tool-call status map changes (executing /
|
|
783
|
+
* interrupt / cleared). The callback receives a fresh map; mutating the
|
|
784
|
+
* argument is not supported.
|
|
785
|
+
*/
|
|
786
|
+
onStatusesChange: (
|
|
787
|
+
statuses: ReadonlyMap<string, ToolExecutionStatus>,
|
|
788
|
+
) => void;
|
|
789
|
+
};
|
|
790
|
+
}
|
|
@@ -149,7 +149,7 @@ describe("mergeModelContexts", () => {
|
|
|
149
149
|
});
|
|
150
150
|
});
|
|
151
151
|
|
|
152
|
-
it("
|
|
152
|
+
it("rejects duplicate tools at the same priority", () => {
|
|
153
153
|
expect(() =>
|
|
154
154
|
mergeModelContexts(
|
|
155
155
|
new Set([
|
|
@@ -160,6 +160,26 @@ describe("mergeModelContexts", () => {
|
|
|
160
160
|
).toThrow(/already exists/);
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
+
it("silently replaces a same-priority tool when the later registration sets overwrite", () => {
|
|
164
|
+
const merged = mergeModelContexts(
|
|
165
|
+
new Set([
|
|
166
|
+
provider({ tools: { duplicate: toolFixture() } }),
|
|
167
|
+
provider({
|
|
168
|
+
tools: {
|
|
169
|
+
duplicate: {
|
|
170
|
+
...toolFixture(),
|
|
171
|
+
description: "latest",
|
|
172
|
+
overwrite: true,
|
|
173
|
+
} as Tool<any, any>,
|
|
174
|
+
},
|
|
175
|
+
}),
|
|
176
|
+
]),
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
expect(merged.tools?.duplicate?.description).toBe("latest");
|
|
180
|
+
expect(merged.tools?.duplicate?.overwrite).toBeUndefined();
|
|
181
|
+
});
|
|
182
|
+
|
|
163
183
|
it("preserves the highest priority when a lower-priority provider reuses the same tool object", () => {
|
|
164
184
|
const shared = {
|
|
165
185
|
...toolFixture(),
|
|
@@ -13,17 +13,17 @@ export const baseRuntimeAdapterTransformScopes = (
|
|
|
13
13
|
scopes.thread ??= Derived({
|
|
14
14
|
source: "threads",
|
|
15
15
|
query: { type: "main" },
|
|
16
|
-
get: (aui) => aui.threads
|
|
16
|
+
get: (aui) => aui.threads.thread("main"),
|
|
17
17
|
});
|
|
18
18
|
scopes.threadListItem ??= Derived({
|
|
19
19
|
source: "threads",
|
|
20
20
|
query: { type: "main" },
|
|
21
|
-
get: (aui) => aui.threads
|
|
21
|
+
get: (aui) => aui.threads.item("main"),
|
|
22
22
|
});
|
|
23
23
|
scopes.composer ??= Derived({
|
|
24
24
|
source: "thread",
|
|
25
25
|
query: {},
|
|
26
|
-
get: (aui) => aui.threads
|
|
26
|
+
get: (aui) => aui.threads.thread("main").composer(),
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
if (!scopes.modelContext && parent.modelContext.source === null) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Unsubscribe } from "../../types/unsubscribe";
|
|
2
2
|
import type { ThreadRuntimeEventType } from "../../runtime/interfaces/thread-runtime-core";
|
|
3
3
|
import type { ThreadRuntime } from "../../runtime/api/thread-runtime";
|
|
4
|
-
import { useMemo, useEffect, RefObject } from "react";
|
|
4
|
+
import { useMemo, useEffect, type RefObject } from "react";
|
|
5
5
|
import { useResource, resource, withKey } from "@assistant-ui/tap";
|
|
6
6
|
import { liveRef } from "./liveRef";
|
|
7
7
|
import {
|
|
@@ -113,6 +113,7 @@ const useThreadClient = ({
|
|
|
113
113
|
deleteMessage: runtime.deleteMessage,
|
|
114
114
|
startRun: runtime.startRun,
|
|
115
115
|
resumeRun: runtime.resumeRun,
|
|
116
|
+
importExternalState: runtime.importExternalState,
|
|
116
117
|
cancelRun: runtime.cancelRun,
|
|
117
118
|
getModelContext: runtime.getModelContext,
|
|
118
119
|
export: runtime.export,
|
|
@@ -108,6 +108,7 @@ export type ThreadMethods = {
|
|
|
108
108
|
* @param initialMessages - Optional array of initial messages to populate the thread
|
|
109
109
|
*/
|
|
110
110
|
reset(initialMessages?: readonly ThreadMessageLike[]): void;
|
|
111
|
+
importExternalState?(state: unknown): void;
|
|
111
112
|
message(selector: { id: string } | { index: number }): MessageMethods;
|
|
112
113
|
/** @deprecated This API is still under active development and might change without notice. */
|
|
113
114
|
stopSpeaking(): void;
|
|
@@ -141,10 +141,11 @@ export class ShallowMemoizeSubject<TState extends object, TPath>
|
|
|
141
141
|
return this.binding.path;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
) {
|
|
144
|
+
private binding: SubscribableWithState<TState | SKIP_UPDATE, TPath>;
|
|
145
|
+
|
|
146
|
+
constructor(binding: SubscribableWithState<TState | SKIP_UPDATE, TPath>) {
|
|
147
147
|
super();
|
|
148
|
+
this.binding = binding;
|
|
148
149
|
const state = binding.getState();
|
|
149
150
|
if (state === SKIP_UPDATE)
|
|
150
151
|
throw new Error("Entry not available in the store");
|
|
@@ -184,10 +185,11 @@ export class LazyMemoizeSubject<TState extends object, TPath>
|
|
|
184
185
|
return this.binding.path;
|
|
185
186
|
}
|
|
186
187
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
) {
|
|
188
|
+
private binding: SubscribableWithState<TState | SKIP_UPDATE, TPath>;
|
|
189
|
+
|
|
190
|
+
constructor(binding: SubscribableWithState<TState | SKIP_UPDATE, TPath>) {
|
|
190
191
|
super();
|
|
192
|
+
this.binding = binding;
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
private _previousStateDirty = true;
|
|
@@ -228,8 +230,11 @@ export class NestedSubscriptionSubject<
|
|
|
228
230
|
return this.binding.path;
|
|
229
231
|
}
|
|
230
232
|
|
|
231
|
-
|
|
233
|
+
private binding: NestedSubscribable<TState, TPath>;
|
|
234
|
+
|
|
235
|
+
constructor(binding: NestedSubscribable<TState, TPath>) {
|
|
232
236
|
super();
|
|
237
|
+
this.binding = binding;
|
|
233
238
|
}
|
|
234
239
|
|
|
235
240
|
public getState() {
|
|
@@ -269,8 +274,11 @@ export class NestedSubscriptionSubject<
|
|
|
269
274
|
export class EventSubscriptionSubject<
|
|
270
275
|
TEvent extends string,
|
|
271
276
|
> extends BaseSubject {
|
|
272
|
-
|
|
277
|
+
private config: EventSubscribable<TEvent>;
|
|
278
|
+
|
|
279
|
+
constructor(config: EventSubscribable<TEvent>) {
|
|
273
280
|
super();
|
|
281
|
+
this.config = config;
|
|
274
282
|
}
|
|
275
283
|
|
|
276
284
|
public getState() {
|
|
@@ -110,6 +110,18 @@ describe("MessageRepository", () => {
|
|
|
110
110
|
}).toThrow(/Parent message not found/);
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
+
it("should throw when a message would be linked under an ancestor with the same id", () => {
|
|
114
|
+
const message = createTestMessage({ id: "message-id" });
|
|
115
|
+
repository.addOrUpdateMessage(null, message);
|
|
116
|
+
|
|
117
|
+
expect(() => {
|
|
118
|
+
repository.addOrUpdateMessage(
|
|
119
|
+
"message-id",
|
|
120
|
+
createTestMessage({ id: "message-id" }),
|
|
121
|
+
);
|
|
122
|
+
}).toThrow(/same id already exists in the parent tree/);
|
|
123
|
+
});
|
|
124
|
+
|
|
113
125
|
it("should retrieve all messages in the current branch", () => {
|
|
114
126
|
const parent = createTestMessage({ id: "parent-id" });
|
|
115
127
|
const child = createTestMessage({ id: "child-id" });
|