@assistant-ui/core 0.3.13 → 0.3.15
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/speech.d.ts.map +1 -1
- package/dist/adapters/speech.js +9 -15
- package/dist/adapters/speech.js.map +1 -1
- package/dist/adapters/thread-history.d.ts +2 -0
- package/dist/adapters/thread-history.d.ts.map +1 -1
- package/dist/adapters/voice.d.ts.map +1 -1
- package/dist/adapters/voice.js +38 -15
- package/dist/adapters/voice.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +3 -2
- package/dist/internal.js +8 -7
- package/dist/model-context/frame/host.d.ts +1 -1
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +19 -4
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/frame/provider.d.ts +4 -0
- package/dist/model-context/frame/provider.d.ts.map +1 -1
- package/dist/model-context/frame/provider.js +50 -3
- package/dist/model-context/frame/provider.js.map +1 -1
- package/dist/model-context/frame/types.d.ts +4 -1
- package/dist/model-context/frame/types.d.ts.map +1 -1
- package/dist/model-context/frame/types.js.map +1 -1
- package/dist/model-context/registry.d.ts.map +1 -1
- package/dist/model-context/registry.js +16 -4
- package/dist/model-context/registry.js.map +1 -1
- package/dist/react/RuntimeAdapter.d.ts +8 -1
- package/dist/react/RuntimeAdapter.d.ts.map +1 -1
- package/dist/react/RuntimeAdapter.js +23 -18
- package/dist/react/RuntimeAdapter.js.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js +28 -12
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/AdaptedRemoteThread.d.ts +11 -0
- package/dist/react/client/AdaptedRemoteThread.d.ts.map +1 -0
- package/dist/react/client/AdaptedRemoteThread.js +27 -0
- package/dist/react/client/AdaptedRemoteThread.js.map +1 -0
- package/dist/react/client/InMemoryThreadList.d.ts +19 -0
- package/dist/react/client/InMemoryThreadList.d.ts.map +1 -0
- package/dist/react/client/InMemoryThreadList.js +418 -0
- package/dist/react/client/InMemoryThreadList.js.map +1 -0
- package/dist/react/client/Interactables.d.ts.map +1 -1
- package/dist/react/client/Interactables.js +159 -102
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/RemoteThreadList.d.ts +34 -0
- package/dist/react/client/RemoteThreadList.d.ts.map +1 -0
- package/dist/react/client/RemoteThreadList.js +898 -0
- package/dist/react/client/RemoteThreadList.js.map +1 -0
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +38 -27
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/index.d.ts +7 -2
- package/dist/react/index.js +5 -2
- package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
- package/dist/react/interactables-legacy/Interactables.js +145 -110
- package/dist/react/interactables-legacy/Interactables.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.js +20 -19
- package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.js +2 -4
- package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.js +2 -4
- package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.js +2 -6
- package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js +2 -6
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.js +2 -4
- package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.js +2 -4
- package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.js +6 -2
- package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts +3 -0
- package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useThreadIsEmpty.js +3 -0
- package/dist/react/primitive-hooks/useThreadIsEmpty.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadIsRunning.d.ts +3 -0
- package/dist/react/primitive-hooks/useThreadIsRunning.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useThreadIsRunning.js +3 -0
- package/dist/react/primitive-hooks/useThreadIsRunning.js.map +1 -1
- package/dist/react/primitives/message/MessageParts.d.ts +13 -0
- package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.d.ts.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/runtimes/RemoteThreadListHookInstanceManager.d.ts +24 -10
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +115 -71
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +14 -2
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +232 -63
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.d.ts +30 -0
- package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -0
- package/dist/react/runtimes/RemoteThreadResource.js +136 -0
- package/dist/react/runtimes/RemoteThreadResource.js.map +1 -0
- package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +3 -10
- package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
- package/dist/react/runtimes/RuntimeAdapterProvider.js +3 -6
- package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
- package/dist/react/runtimes/assistant-transport/commandQueue.d.ts +17 -0
- package/dist/react/runtimes/assistant-transport/commandQueue.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/commandQueue.js +55 -0
- package/dist/react/runtimes/assistant-transport/commandQueue.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts +11 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js +165 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/runManager.d.ts +15 -0
- package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/runManager.js +86 -0
- package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/types.d.ts +130 -0
- package/dist/react/runtimes/assistant-transport/types.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/types.js +0 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts +14 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js +296 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts +7 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.js +25 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts +7 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.js +27 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -0
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +39 -13
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +2 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +3 -3
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +4 -0
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js +7 -0
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +60 -17
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts +16 -0
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts.map +1 -0
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js +36 -0
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -0
- package/dist/react/runtimes/external-message-converter.js +14 -14
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useExternalStoreRuntime.js +44 -28
- package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
- package/dist/react/runtimes/useLocalRuntime.js +1 -1
- package/dist/react/runtimes/useRuntimeAdapters.d.ts +9 -0
- package/dist/react/runtimes/useRuntimeAdapters.d.ts.map +1 -0
- package/dist/react/runtimes/useRuntimeAdapters.js +20 -0
- package/dist/react/runtimes/useRuntimeAdapters.js.map +1 -0
- package/dist/runtime/api/composer-runtime.d.ts +5 -0
- package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.js.map +1 -1
- package/dist/runtime/api/message-runtime.js +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts +1 -0
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +4 -2
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +12 -2
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +8 -2
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +8 -7
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -0
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +3 -3
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +0 -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 +10 -4
- package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/internal.js +5 -5
- package/dist/runtime/queue/message-queue.d.ts.map +1 -1
- package/dist/runtime/queue/message-queue.js +2 -1
- package/dist/runtime/queue/message-queue.js.map +1 -1
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +27 -18
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/thread-runtime-lifecycle.d.ts +8 -0
- package/dist/runtime/utils/thread-runtime-lifecycle.d.ts.map +1 -0
- package/dist/runtime/utils/thread-runtime-lifecycle.js +11 -0
- package/dist/runtime/utils/thread-runtime-lifecycle.js.map +1 -0
- package/dist/runtimes/external-store/external-store-shared-options.js.map +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 +4 -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 +8 -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 +37 -13
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts +102 -0
- package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts.map +1 -0
- package/dist/runtimes/inert/InertThreadRuntimeCore.js +156 -0
- package/dist/runtimes/inert/InertThreadRuntimeCore.js.map +1 -0
- package/dist/runtimes/internal.d.ts +1 -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 +78 -19
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +12 -59
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +10 -142
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/remote-thread-list/adapter-changed.d.ts +9 -0
- package/dist/runtimes/remote-thread-list/adapter-changed.d.ts.map +1 -0
- package/dist/runtimes/remote-thread-list/adapter-changed.js +13 -0
- package/dist/runtimes/remote-thread-list/adapter-changed.js.map +1 -0
- package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.js +16 -152
- package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/optimistic-state.d.ts +2 -0
- package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/optimistic-state.js +11 -0
- package/dist/runtimes/remote-thread-list/optimistic-state.js.map +1 -1
- package/dist/runtimes/remote-thread-list/types.d.ts +32 -1
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +1 -12
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +67 -38
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/external-thread.js +1 -1
- package/dist/store/clients/external-thread.js.map +1 -1
- package/dist/store/clients/suggestions.js +2 -2
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/clients/thread-selection-events.d.ts +10 -0
- package/dist/store/clients/thread-selection-events.d.ts.map +1 -0
- package/dist/store/clients/thread-selection-events.js +40 -0
- package/dist/store/clients/thread-selection-events.js.map +1 -0
- package/dist/store/env.d.ts +5 -0
- package/dist/store/env.d.ts.map +1 -0
- package/dist/store/env.js +12 -0
- package/dist/store/env.js.map +1 -0
- package/dist/store/index.d.ts +5 -3
- package/dist/store/index.js +4 -2
- package/dist/store/internal.d.ts +4 -1
- package/dist/store/internal.js +4 -1
- package/dist/store/primitive-predicates.d.ts +19 -0
- package/dist/store/primitive-predicates.d.ts.map +1 -0
- package/dist/store/primitive-predicates.js +19 -0
- package/dist/store/primitive-predicates.js.map +1 -0
- package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/attachment-runtime-client.js +18 -11
- package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/handle-runtime-action.d.ts +5 -0
- package/dist/store/runtime-clients/handle-runtime-action.d.ts.map +1 -0
- package/dist/store/runtime-clients/handle-runtime-action.js +14 -0
- package/dist/store/runtime-clients/handle-runtime-action.js.map +1 -0
- package/dist/store/runtime-clients/handle-thread-list-action.d.ts +5 -0
- package/dist/store/runtime-clients/handle-thread-list-action.d.ts.map +1 -0
- package/dist/store/runtime-clients/handle-thread-list-action.js +7 -0
- package/dist/store/runtime-clients/handle-thread-list-action.js.map +1 -0
- 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 +62 -29
- 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 +5 -6
- package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
- package/dist/store/scopes/composer.d.ts +9 -4
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/thread-list-item.d.ts +7 -6
- package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
- package/dist/store/scopes/thread.d.ts +8 -7
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/dist/store/scopes/threads.d.ts +17 -1
- package/dist/store/scopes/threads.d.ts.map +1 -1
- package/dist/subscribable/subscribable.d.ts +2 -1
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/subscribable/subscribable.js +23 -18
- package/dist/subscribable/subscribable.js.map +1 -1
- package/dist/types/message.d.ts +1 -1
- package/dist/types/message.js.map +1 -1
- package/dist/utils/composite-context-provider.d.ts +1 -0
- package/dist/utils/composite-context-provider.d.ts.map +1 -1
- package/dist/utils/composite-context-provider.js +25 -9
- package/dist/utils/composite-context-provider.js.map +1 -1
- package/dist/utils/notify-event-listeners.d.ts +2 -2
- package/dist/utils/notify-event-listeners.d.ts.map +1 -1
- package/dist/utils/notify-event-listeners.js +2 -2
- package/dist/utils/notify-event-listeners.js.map +1 -1
- package/dist/utils/silent-runtime-action.d.ts +6 -0
- package/dist/utils/silent-runtime-action.d.ts.map +1 -0
- package/dist/utils/silent-runtime-action.js +7 -0
- package/dist/utils/silent-runtime-action.js.map +1 -0
- package/package.json +8 -8
- package/src/adapters/speech.test.ts +118 -1
- package/src/adapters/speech.ts +21 -22
- package/src/adapters/thread-history.ts +2 -0
- package/src/adapters/voice.test.ts +134 -0
- package/src/adapters/voice.ts +35 -27
- package/src/index.ts +1 -0
- package/src/internal.ts +1 -0
- package/src/model-context/frame/host.test.ts +87 -5
- package/src/model-context/frame/host.ts +18 -4
- package/src/model-context/frame/provider.test.ts +347 -20
- package/src/model-context/frame/provider.ts +58 -2
- package/src/model-context/frame/types.ts +5 -0
- package/src/model-context/registry.test.ts +131 -0
- package/src/model-context/registry.ts +16 -6
- package/src/react/RuntimeAdapter.test.ts +2 -0
- package/src/react/RuntimeAdapter.ts +20 -8
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +34 -17
- package/src/react/client/AdaptedRemoteThread.ts +41 -0
- package/src/react/client/InMemoryThreadList.test.tsx +148 -0
- package/src/react/client/InMemoryThreadList.ts +290 -0
- package/src/react/client/Interactables.test.ts +326 -2
- package/src/react/client/Interactables.ts +227 -110
- package/src/react/client/RemoteThreadList.test.ts +1222 -0
- package/src/react/client/RemoteThreadList.ts +1136 -0
- package/src/react/client/Tools.ts +36 -29
- package/src/react/index.ts +13 -0
- package/src/react/interactables-legacy/Interactables.test.ts +317 -0
- package/src/react/interactables-legacy/Interactables.ts +204 -128
- package/src/react/primitive-hooks/useActionBarCopy.test.ts +15 -0
- package/src/react/primitive-hooks/useActionBarCopy.ts +15 -10
- package/src/react/primitive-hooks/useActionBarEdit.ts +2 -1
- package/src/react/primitive-hooks/useActionBarReload.ts +2 -6
- package/src/react/primitive-hooks/useBranchPickerNext.ts +2 -7
- package/src/react/primitive-hooks/useBranchPickerPrevious.ts +2 -7
- package/src/react/primitive-hooks/useComposerCancel.ts +2 -1
- package/src/react/primitive-hooks/useComposerSend.ts +2 -5
- package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +11 -0
- package/src/react/primitive-hooks/useSuggestionTrigger.ts +4 -5
- package/src/react/primitive-hooks/useThreadIsEmpty.ts +3 -0
- package/src/react/primitive-hooks/useThreadIsRunning.ts +3 -0
- package/src/react/primitives/message/MessageParts.tsx +0 -1
- package/src/react/primitives/thread/ThreadMessages.tsx +2 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.retry.test.tsx +116 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +1 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +57 -6
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.title.test.tsx +272 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +171 -124
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.republish.test.ts +87 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +327 -83
- package/src/react/runtimes/RemoteThreadResource.test.ts +141 -0
- package/src/react/runtimes/RemoteThreadResource.ts +233 -0
- package/src/react/runtimes/RuntimeAdapterProvider.tsx +8 -20
- package/src/react/runtimes/assistant-transport/commandQueue.ts +68 -0
- package/src/react/runtimes/assistant-transport/replayBoundaryStream.test.ts +455 -0
- package/src/react/runtimes/assistant-transport/replayBoundaryStream.ts +172 -0
- package/src/react/runtimes/assistant-transport/runManager.ts +124 -0
- package/src/react/runtimes/assistant-transport/transport-delivery.test.tsx +79 -0
- package/src/react/runtimes/assistant-transport/transport-parentid.test.tsx +97 -0
- package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +414 -0
- package/src/react/runtimes/assistant-transport/types.ts +170 -0
- package/src/react/runtimes/assistant-transport/useAssistantTransport.spec.md +141 -0
- package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.test.tsx +683 -0
- package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +483 -0
- package/src/react/runtimes/assistant-transport/useConvertedState.ts +20 -0
- package/src/react/runtimes/assistant-transport/useLatestRef.ts +9 -0
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +131 -6
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +61 -15
- package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +6 -4
- package/src/react/runtimes/cloud/auiV0.ts +17 -1
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +98 -3
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +104 -27
- package/src/react/runtimes/cloud/useCloudThreadListRuntime.test.tsx +56 -0
- package/src/react/runtimes/cloud/useCloudThreadListRuntime.ts +31 -0
- package/src/react/runtimes/external-message-converter.test.ts +143 -0
- package/src/react/runtimes/external-message-converter.ts +41 -41
- package/src/react/runtimes/remote-thread-hook-on-tap.test.ts +58 -0
- package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +83 -0
- package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +13 -3
- package/src/react/runtimes/useExternalStoreRuntime.ts +7 -0
- package/src/react/runtimes/useExternalStoreSharedOptions.ts +3 -1
- package/src/react/runtimes/useLocalRuntime.test.tsx +134 -8
- package/src/react/runtimes/useRuntimeAdapters.test.tsx +62 -0
- package/src/react/runtimes/useRuntimeAdapters.ts +28 -0
- package/src/runtime/api/composer-runtime.ts +5 -0
- package/src/runtime/api/thread-list-runtime.ts +3 -1
- package/src/runtime/api/thread-runtime.ts +20 -2
- package/src/runtime/base/base-composer-runtime-core.ts +6 -5
- package/src/runtime/base/base-thread-runtime-core.test.ts +191 -0
- package/src/runtime/base/base-thread-runtime-core.ts +11 -2
- package/src/runtime/base/default-thread-composer-runtime-core.ts +12 -4
- package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
- package/src/runtime/queue/message-queue.ts +2 -1
- package/src/runtime/utils/message-repository.ts +26 -18
- package/src/runtime/utils/thread-runtime-lifecycle.ts +18 -0
- package/src/runtimes/external-store/external-store-shared-options.ts +3 -1
- 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 +103 -34
- package/src/runtimes/inert/InertThreadRuntimeCore.test.ts +253 -0
- package/src/runtimes/inert/InertThreadRuntimeCore.ts +232 -0
- package/src/runtimes/local/local-thread-runtime-core.test.ts +692 -4
- package/src/runtimes/local/local-thread-runtime-core.ts +117 -22
- package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +17 -205
- package/src/runtimes/remote-thread-list/adapter-changed.ts +10 -0
- package/src/runtimes/remote-thread-list/empty-thread-core.ts +28 -217
- package/src/runtimes/remote-thread-list/optimistic-state.test.ts +18 -0
- package/src/runtimes/remote-thread-list/optimistic-state.ts +13 -0
- package/src/runtimes/remote-thread-list/types.ts +34 -0
- package/src/runtimes/tool-invocations/EDGE_CASES.md +17 -6
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +243 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +127 -61
- package/src/store/clients/external-thread.ts +1 -1
- package/src/store/clients/model-context-client.test.ts +16 -8
- package/src/store/clients/suggestions.ts +2 -2
- package/src/store/clients/thread-selection-events.ts +21 -0
- package/src/store/env.ts +11 -0
- package/src/store/index.ts +14 -1
- package/src/store/internal.ts +13 -0
- package/src/store/primitive-predicates.test.ts +184 -0
- package/src/store/primitive-predicates.ts +43 -0
- package/src/store/runtime-clients/attachment-runtime-client.test.ts +41 -0
- package/src/store/runtime-clients/attachment-runtime-client.ts +2 -1
- package/src/store/runtime-clients/handle-runtime-action.test.ts +40 -0
- package/src/store/runtime-clients/handle-runtime-action.ts +14 -0
- package/src/store/runtime-clients/handle-thread-list-action.test.ts +69 -0
- package/src/store/runtime-clients/handle-thread-list-action.ts +6 -0
- package/src/store/runtime-clients/thread-list-item-runtime-client.ts +15 -7
- package/src/store/runtime-clients/thread-list-runtime-client.ts +9 -6
- package/src/store/scopes/composer.ts +9 -4
- package/src/store/scopes/thread-list-item.ts +7 -6
- package/src/store/scopes/thread.ts +8 -7
- package/src/store/scopes/threads.ts +14 -0
- package/src/subscribable/subscribable.test.ts +77 -1
- package/src/subscribable/subscribable.ts +38 -23
- package/src/tests/MessageRepository.test.ts +48 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-errors.test.ts +2 -2
- package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +8 -6
- package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-unarchive.test.ts +25 -0
- package/src/tests/auiV0Encode.test.ts +66 -0
- package/src/tests/base-composer-runtime-core-send.test.ts +30 -0
- package/src/tests/base-composer-runtime-core.test.ts +28 -0
- package/src/tests/composer-can-cancel.test.ts +101 -0
- package/src/tests/empty-thread-core.test.ts +6 -0
- package/src/tests/external-store-thread-list-runtime-core.test.ts +101 -0
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +211 -1
- package/src/tests/external-store-thread-runtime-core.test.ts +124 -0
- package/src/tests/external-thread-isEmpty.test.tsx +100 -0
- package/src/tests/interactables-toolui-migration.test.tsx +66 -0
- package/src/tests/message-queue.test.ts +28 -0
- package/src/tests/remote-thread-list-adapter-switch.test.ts +383 -0
- package/src/tests/session-reset-notification.test.ts +145 -0
- package/src/tests/thread-switch-events.test.tsx +99 -1
- package/src/tests/tools-scope-migration.test.tsx +58 -0
- package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +67 -0
- package/src/types/message.ts +1 -1
- package/src/utils/composite-context-provider.test.ts +139 -0
- package/src/utils/composite-context-provider.ts +26 -8
- package/src/utils/notify-event-listeners.ts +10 -5
- package/src/utils/silent-runtime-action.ts +6 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { renderHook } from "@testing-library/react";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { useStableRuntimeAdapters } from "./useRuntimeAdapters";
|
|
6
|
+
import type { RuntimeAdapters } from "../../runtimes/remote-thread-list/types";
|
|
7
|
+
import type { ThreadHistoryAdapter } from "../../adapters/thread-history";
|
|
8
|
+
|
|
9
|
+
const makeHistory = (): ThreadHistoryAdapter => ({
|
|
10
|
+
load: async () => ({ messages: [] }),
|
|
11
|
+
append: async () => {},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("useStableRuntimeAdapters", () => {
|
|
15
|
+
it("keeps the previous bag when a fresh literal is shallow-equal", () => {
|
|
16
|
+
const history = makeHistory();
|
|
17
|
+
const { result, rerender } = renderHook(
|
|
18
|
+
({ adapters }: { adapters: RuntimeAdapters | null }) =>
|
|
19
|
+
useStableRuntimeAdapters(adapters),
|
|
20
|
+
{ initialProps: { adapters: { history } } },
|
|
21
|
+
);
|
|
22
|
+
const first = result.current;
|
|
23
|
+
|
|
24
|
+
rerender({ adapters: { history } });
|
|
25
|
+
|
|
26
|
+
expect(result.current).toBe(first);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("adopts the new bag when a field changes", () => {
|
|
30
|
+
const first = makeHistory();
|
|
31
|
+
const second = makeHistory();
|
|
32
|
+
const { result, rerender } = renderHook(
|
|
33
|
+
({ adapters }: { adapters: RuntimeAdapters | null }) =>
|
|
34
|
+
useStableRuntimeAdapters(adapters),
|
|
35
|
+
{ initialProps: { adapters: { history: first } } },
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
rerender({ adapters: { history: second } });
|
|
39
|
+
|
|
40
|
+
expect(result.current?.history).toBe(second);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("moves between null and a bag", () => {
|
|
44
|
+
const history = makeHistory();
|
|
45
|
+
const { result, rerender } = renderHook(
|
|
46
|
+
({ adapters }: { adapters: RuntimeAdapters | null }) =>
|
|
47
|
+
useStableRuntimeAdapters(adapters),
|
|
48
|
+
{ initialProps: { adapters: null as RuntimeAdapters | null } },
|
|
49
|
+
);
|
|
50
|
+
expect(result.current).toBeNull();
|
|
51
|
+
|
|
52
|
+
rerender({ adapters: { history } });
|
|
53
|
+
expect(result.current?.history).toBe(history);
|
|
54
|
+
|
|
55
|
+
rerender({ adapters: null });
|
|
56
|
+
expect(result.current).toBeNull();
|
|
57
|
+
|
|
58
|
+
rerender({ adapters: {} });
|
|
59
|
+
expect(result.current).not.toBeNull();
|
|
60
|
+
expect(result.current).toEqual({});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
import { useContextProvider } from "@assistant-ui/tap";
|
|
3
|
+
import { useShallowStable } from "@assistant-ui/store/internal";
|
|
4
|
+
import type { RuntimeAdapters } from "../../runtimes/remote-thread-list/types";
|
|
5
|
+
|
|
6
|
+
const RuntimeAdaptersContext = createContext<RuntimeAdapters | null>(null);
|
|
7
|
+
|
|
8
|
+
export const useRuntimeAdaptersProvider = <T>(
|
|
9
|
+
adapters: RuntimeAdapters | null,
|
|
10
|
+
fn: () => T,
|
|
11
|
+
): T => useContextProvider(RuntimeAdaptersContext, adapters, fn);
|
|
12
|
+
|
|
13
|
+
export const useRuntimeAdapters = () => {
|
|
14
|
+
return useContext(RuntimeAdaptersContext);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const NO_ADAPTERS: RuntimeAdapters = {};
|
|
18
|
+
|
|
19
|
+
// Both adapter faces absorb a fresh but shallow-equal bag from
|
|
20
|
+
// `unstable_useAdapters`, so a per-render literal does not churn the context.
|
|
21
|
+
export const useStableRuntimeAdapters = (
|
|
22
|
+
adapters: RuntimeAdapters | null | undefined,
|
|
23
|
+
): RuntimeAdapters | null => {
|
|
24
|
+
const stable = useShallowStable(adapters ?? NO_ADAPTERS);
|
|
25
|
+
return adapters == null ? null : stable;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { RuntimeAdaptersContext };
|
|
@@ -42,6 +42,11 @@ export type {
|
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
type BaseComposerState = {
|
|
45
|
+
/**
|
|
46
|
+
* Whether the composer can cancel the current run. `true` when the runtime
|
|
47
|
+
* supports cancel and a run is in flight, not merely when cancel is a
|
|
48
|
+
* capability.
|
|
49
|
+
*/
|
|
45
50
|
readonly canCancel: boolean;
|
|
46
51
|
readonly canSend: boolean;
|
|
47
52
|
readonly isEditing: boolean;
|
|
@@ -114,6 +114,7 @@ export type ThreadListRuntimeCoreBinding = ThreadListRuntimeCore;
|
|
|
114
114
|
|
|
115
115
|
export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
116
116
|
private _getState;
|
|
117
|
+
private _stateBinding: LazyMemoizeSubject<ThreadListState, object>;
|
|
117
118
|
private _core: ThreadListRuntimeCoreBinding;
|
|
118
119
|
private _runtimeFactory: new (
|
|
119
120
|
binding: ThreadRuntimeCoreBinding,
|
|
@@ -136,6 +137,7 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
|
136
137
|
});
|
|
137
138
|
|
|
138
139
|
this._getState = stateBinding.getState.bind(stateBinding);
|
|
140
|
+
this._stateBinding = stateBinding;
|
|
139
141
|
|
|
140
142
|
this._mainThreadListItemRuntime = new ThreadListItemRuntimeImpl(
|
|
141
143
|
new ShallowMemoizeSubject({
|
|
@@ -213,7 +215,7 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
|
213
215
|
}
|
|
214
216
|
|
|
215
217
|
public subscribe(callback: () => void): Unsubscribe {
|
|
216
|
-
return this.
|
|
218
|
+
return this._stateBinding.subscribe(callback);
|
|
217
219
|
}
|
|
218
220
|
|
|
219
221
|
private _mainThreadListItemRuntime;
|
|
@@ -199,7 +199,7 @@ export type ThreadState = {
|
|
|
199
199
|
* reports it directly; the rest fall back to the trailing assistant message.
|
|
200
200
|
*/
|
|
201
201
|
export const getThreadRuntimeCoreIsRunning = (
|
|
202
|
-
runtime: ThreadRuntimeCore,
|
|
202
|
+
runtime: Pick<ThreadRuntimeCore, "isRunning" | "messages">,
|
|
203
203
|
): boolean => {
|
|
204
204
|
if (runtime.isRunning !== undefined) return runtime.isRunning;
|
|
205
205
|
const lastMessage = runtime.messages.at(-1);
|
|
@@ -294,6 +294,13 @@ export type ThreadRuntime = {
|
|
|
294
294
|
|
|
295
295
|
subscribe(callback: () => void): Unsubscribe;
|
|
296
296
|
cancelRun(): void;
|
|
297
|
+
/**
|
|
298
|
+
* Notifies the runtime that the adapter discarded its backing session.
|
|
299
|
+
* Clears session-scoped tool-invocation state without run-cancel side
|
|
300
|
+
* effects such as composer draft restoration. Internal API for
|
|
301
|
+
* external-store adapter authors.
|
|
302
|
+
*/
|
|
303
|
+
unstable_notifySessionReset(): void;
|
|
297
304
|
getModelContext(): ModelContext;
|
|
298
305
|
|
|
299
306
|
export(): ExportedMessageRepository;
|
|
@@ -339,6 +346,10 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
339
346
|
private readonly _threadBinding: ThreadRuntimeCoreBinding & {
|
|
340
347
|
getStateState(): ThreadState;
|
|
341
348
|
};
|
|
349
|
+
private readonly _stateBinding: ShallowMemoizeSubject<
|
|
350
|
+
ThreadState,
|
|
351
|
+
ThreadRuntimePath
|
|
352
|
+
>;
|
|
342
353
|
|
|
343
354
|
constructor(
|
|
344
355
|
threadBinding: ThreadRuntimeCoreBinding,
|
|
@@ -361,6 +372,7 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
361
372
|
},
|
|
362
373
|
});
|
|
363
374
|
|
|
375
|
+
this._stateBinding = stateBinding;
|
|
364
376
|
this._threadBinding = {
|
|
365
377
|
path: threadBinding.path,
|
|
366
378
|
getState: () => threadBinding.getState(),
|
|
@@ -392,6 +404,8 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
392
404
|
this.exportExternalState = this.exportExternalState.bind(this);
|
|
393
405
|
this.startRun = this.startRun.bind(this);
|
|
394
406
|
this.cancelRun = this.cancelRun.bind(this);
|
|
407
|
+
this.unstable_notifySessionReset =
|
|
408
|
+
this.unstable_notifySessionReset.bind(this);
|
|
395
409
|
this.stopSpeaking = this.stopSpeaking.bind(this);
|
|
396
410
|
this.connectVoice = this.connectVoice.bind(this);
|
|
397
411
|
this.disconnectVoice = this.disconnectVoice.bind(this);
|
|
@@ -435,7 +449,7 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
435
449
|
}
|
|
436
450
|
|
|
437
451
|
public subscribe(callback: () => void) {
|
|
438
|
-
return this.
|
|
452
|
+
return this._stateBinding.subscribe(callback);
|
|
439
453
|
}
|
|
440
454
|
|
|
441
455
|
public getModelContext() {
|
|
@@ -462,6 +476,10 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
462
476
|
this._threadBinding.getState().cancelRun();
|
|
463
477
|
}
|
|
464
478
|
|
|
479
|
+
public unstable_notifySessionReset() {
|
|
480
|
+
this._threadBinding.getState().unstable_notifySessionReset();
|
|
481
|
+
}
|
|
482
|
+
|
|
465
483
|
public stopSpeaking() {
|
|
466
484
|
return this._threadBinding.getState().stopSpeaking();
|
|
467
485
|
}
|
|
@@ -240,6 +240,8 @@ export abstract class BaseComposerRuntimeCore
|
|
|
240
240
|
const originalAttachments = this.attachments;
|
|
241
241
|
const text = this.text;
|
|
242
242
|
const quote = this._quote;
|
|
243
|
+
const role = this.role;
|
|
244
|
+
const runConfig = this.runConfig;
|
|
243
245
|
this._quote = undefined;
|
|
244
246
|
this._text = "";
|
|
245
247
|
this._isSending = true;
|
|
@@ -291,10 +293,10 @@ export abstract class BaseComposerRuntimeCore
|
|
|
291
293
|
|
|
292
294
|
const message: Omit<AppendMessage, "parentId" | "sourceId"> = {
|
|
293
295
|
createdAt: new Date(),
|
|
294
|
-
role
|
|
296
|
+
role,
|
|
295
297
|
content: text ? [{ type: "text", text }] : [],
|
|
296
298
|
attachments: finalAttachments,
|
|
297
|
-
runConfig
|
|
299
|
+
runConfig,
|
|
298
300
|
metadata: { custom: { ...(quote ? { quote } : {}) } },
|
|
299
301
|
};
|
|
300
302
|
|
|
@@ -718,9 +720,8 @@ export abstract class BaseComposerRuntimeCore
|
|
|
718
720
|
|
|
719
721
|
const session = this._dictationSession;
|
|
720
722
|
const sessionId = this._activeDictationSessionId;
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
});
|
|
723
|
+
const cleanup = () => this._cleanupDictation({ sessionId });
|
|
724
|
+
void session.stop().then(cleanup, cleanup);
|
|
724
725
|
}
|
|
725
726
|
|
|
726
727
|
private _cleanupDictation(options?: { sessionId: number | undefined }): void {
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import type { RealtimeVoiceAdapter } from "../../adapters/voice";
|
|
3
|
+
import type { AppendMessage } from "../../types/message";
|
|
4
|
+
import type {
|
|
5
|
+
AddToolResultOptions,
|
|
6
|
+
ResumeRunConfig,
|
|
7
|
+
ResumeToolCallOptions,
|
|
8
|
+
RespondToToolApprovalOptions,
|
|
9
|
+
RuntimeCapabilities,
|
|
10
|
+
StartRunConfig,
|
|
11
|
+
ThreadSuggestion,
|
|
12
|
+
} from "../interfaces/thread-runtime-core";
|
|
13
|
+
import { BaseThreadRuntimeCore } from "./base-thread-runtime-core";
|
|
14
|
+
|
|
15
|
+
const createVoiceAdapter = () => {
|
|
16
|
+
let volumeCallback: ((volume: number) => void) | undefined;
|
|
17
|
+
const session: RealtimeVoiceAdapter.Session = {
|
|
18
|
+
status: { type: "running" },
|
|
19
|
+
isMuted: false,
|
|
20
|
+
disconnect: vi.fn(),
|
|
21
|
+
mute: vi.fn(),
|
|
22
|
+
unmute: vi.fn(),
|
|
23
|
+
onStatusChange: () => () => {},
|
|
24
|
+
onTranscript: () => () => {},
|
|
25
|
+
onModeChange: () => () => {},
|
|
26
|
+
onVolumeChange: (callback) => {
|
|
27
|
+
volumeCallback = callback;
|
|
28
|
+
return () => {
|
|
29
|
+
volumeCallback = undefined;
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
adapter: { connect: () => session },
|
|
36
|
+
emitVolume: (volume: number) => volumeCallback?.(volume),
|
|
37
|
+
session,
|
|
38
|
+
} satisfies {
|
|
39
|
+
adapter: RealtimeVoiceAdapter;
|
|
40
|
+
emitVolume: (volume: number) => void;
|
|
41
|
+
session: RealtimeVoiceAdapter.Session;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
class TestRuntime extends BaseThreadRuntimeCore {
|
|
46
|
+
private readonly voiceAdapter: ReturnType<typeof createVoiceAdapter>;
|
|
47
|
+
|
|
48
|
+
constructor(voiceAdapter: ReturnType<typeof createVoiceAdapter>) {
|
|
49
|
+
super({ getModelContext: () => ({}) });
|
|
50
|
+
this.voiceAdapter = voiceAdapter;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get adapters() {
|
|
54
|
+
return { voice: this.voiceAdapter.adapter };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get isDisabled() {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get isSendDisabled() {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get isLoading() {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get suggestions(): readonly ThreadSuggestion[] {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get extras() {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get capabilities(): RuntimeCapabilities {
|
|
78
|
+
return {
|
|
79
|
+
switchToBranch: false,
|
|
80
|
+
switchBranchDuringRun: false,
|
|
81
|
+
edit: false,
|
|
82
|
+
delete: false,
|
|
83
|
+
reload: false,
|
|
84
|
+
refetchThread: false,
|
|
85
|
+
cancel: false,
|
|
86
|
+
unstable_copy: false,
|
|
87
|
+
speech: false,
|
|
88
|
+
dictation: false,
|
|
89
|
+
voice: true,
|
|
90
|
+
attachments: false,
|
|
91
|
+
feedback: false,
|
|
92
|
+
queue: false,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
append(_message: AppendMessage) {}
|
|
97
|
+
deleteMessage(_messageId: string) {}
|
|
98
|
+
startRun(_config: StartRunConfig) {}
|
|
99
|
+
resumeRun(_config: ResumeRunConfig) {}
|
|
100
|
+
addToolResult(_options: AddToolResultOptions) {}
|
|
101
|
+
resumeToolCall(_options: ResumeToolCallOptions) {}
|
|
102
|
+
respondToToolApproval(_options: RespondToToolApprovalOptions) {}
|
|
103
|
+
cancelRun() {}
|
|
104
|
+
exportExternalState() {
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
importExternalState(_state: unknown) {}
|
|
108
|
+
unstable_notifySessionReset() {}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
afterEach(() => {
|
|
112
|
+
vi.restoreAllMocks();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe("BaseThreadRuntimeCore voice volume subscriptions", () => {
|
|
116
|
+
it("continues notifying subscribers when one throws", () => {
|
|
117
|
+
const consoleError = vi
|
|
118
|
+
.spyOn(console, "error")
|
|
119
|
+
.mockImplementation(() => {});
|
|
120
|
+
const voice = createVoiceAdapter();
|
|
121
|
+
const runtime = new TestRuntime(voice);
|
|
122
|
+
runtime.connectVoice();
|
|
123
|
+
|
|
124
|
+
const listenerError = new Error("listener failed");
|
|
125
|
+
const laterListener = vi.fn();
|
|
126
|
+
runtime.subscribeVoiceVolume(() => {
|
|
127
|
+
throw listenerError;
|
|
128
|
+
});
|
|
129
|
+
runtime.subscribeVoiceVolume(laterListener);
|
|
130
|
+
|
|
131
|
+
expect(() => voice.emitVolume(0.5)).not.toThrow();
|
|
132
|
+
expect(laterListener).toHaveBeenCalledOnce();
|
|
133
|
+
expect(runtime.getVoiceVolume()).toBe(0.5);
|
|
134
|
+
expect(consoleError).toHaveBeenCalledWith(
|
|
135
|
+
"[assistant-ui] Voice volume listener threw an error",
|
|
136
|
+
listenerError,
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("continues disconnect cleanup when a subscriber throws", () => {
|
|
141
|
+
const consoleError = vi
|
|
142
|
+
.spyOn(console, "error")
|
|
143
|
+
.mockImplementation(() => {});
|
|
144
|
+
const voice = createVoiceAdapter();
|
|
145
|
+
const runtime = new TestRuntime(voice);
|
|
146
|
+
runtime.connectVoice();
|
|
147
|
+
|
|
148
|
+
const listenerError = new Error("disconnect listener failed");
|
|
149
|
+
const laterListener = vi.fn();
|
|
150
|
+
runtime.subscribeVoiceVolume(() => {
|
|
151
|
+
throw listenerError;
|
|
152
|
+
});
|
|
153
|
+
runtime.subscribeVoiceVolume(laterListener);
|
|
154
|
+
|
|
155
|
+
expect(() => runtime.disconnectVoice()).not.toThrow();
|
|
156
|
+
expect(laterListener).toHaveBeenCalledOnce();
|
|
157
|
+
expect(runtime.getVoiceVolume()).toBe(0);
|
|
158
|
+
expect(runtime.voice).toBeUndefined();
|
|
159
|
+
expect(voice.session.disconnect).toHaveBeenCalledOnce();
|
|
160
|
+
expect(consoleError).toHaveBeenCalledWith(
|
|
161
|
+
"[assistant-ui] Voice volume listener threw an error",
|
|
162
|
+
listenerError,
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("reports rejected subscriber thenables", async () => {
|
|
167
|
+
const consoleError = vi
|
|
168
|
+
.spyOn(console, "error")
|
|
169
|
+
.mockImplementation(() => {});
|
|
170
|
+
const voice = createVoiceAdapter();
|
|
171
|
+
const runtime = new TestRuntime(voice);
|
|
172
|
+
runtime.connectVoice();
|
|
173
|
+
|
|
174
|
+
const listenerError = new Error("async listener failed");
|
|
175
|
+
const laterListener = vi.fn();
|
|
176
|
+
runtime.subscribeVoiceVolume(async () => {
|
|
177
|
+
throw listenerError;
|
|
178
|
+
});
|
|
179
|
+
runtime.subscribeVoiceVolume(laterListener);
|
|
180
|
+
|
|
181
|
+
voice.emitVolume(0.5);
|
|
182
|
+
|
|
183
|
+
await vi.waitFor(() => {
|
|
184
|
+
expect(laterListener).toHaveBeenCalledOnce();
|
|
185
|
+
expect(consoleError).toHaveBeenCalledWith(
|
|
186
|
+
"[assistant-ui] Voice volume listener threw an error",
|
|
187
|
+
listenerError,
|
|
188
|
+
);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
});
|
|
@@ -69,6 +69,7 @@ export abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
|
|
|
69
69
|
public abstract cancelRun(): void;
|
|
70
70
|
public abstract exportExternalState(): any;
|
|
71
71
|
public abstract importExternalState(state: any): void;
|
|
72
|
+
public abstract unstable_notifySessionReset(): void;
|
|
72
73
|
|
|
73
74
|
protected _voiceMessages: ThreadMessage[] = [];
|
|
74
75
|
protected _voiceGeneration = 0;
|
|
@@ -355,7 +356,11 @@ export abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
|
|
|
355
356
|
unsubs.push(
|
|
356
357
|
session.onVolumeChange((volume) => {
|
|
357
358
|
this._voiceVolume = volume;
|
|
358
|
-
|
|
359
|
+
notifyEventListeners(
|
|
360
|
+
this._voiceVolumeSubscribers,
|
|
361
|
+
undefined,
|
|
362
|
+
"Voice volume",
|
|
363
|
+
);
|
|
359
364
|
}),
|
|
360
365
|
);
|
|
361
366
|
|
|
@@ -454,7 +459,11 @@ export abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
|
|
|
454
459
|
this._voiceSession = undefined;
|
|
455
460
|
this.voice = undefined;
|
|
456
461
|
this._voiceVolume = 0;
|
|
457
|
-
|
|
462
|
+
notifyEventListeners(
|
|
463
|
+
this._voiceVolumeSubscribers,
|
|
464
|
+
undefined,
|
|
465
|
+
"Voice volume",
|
|
466
|
+
);
|
|
458
467
|
this._voiceMessages = [];
|
|
459
468
|
this._markVoiceMessagesDirty();
|
|
460
469
|
this._notifySubscribers();
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
ThreadComposerRuntimeCore,
|
|
7
7
|
} from "../interfaces/composer-runtime-core";
|
|
8
8
|
import type { ThreadRuntimeCore } from "../interfaces/thread-runtime-core";
|
|
9
|
+
import { getThreadRuntimeCoreIsRunning } from "../api/thread-runtime";
|
|
9
10
|
import type { QueuePlacement } from "../queue/external-thread-queue-adapter";
|
|
10
11
|
import {
|
|
11
12
|
EMPTY_QUEUE_ITEMS,
|
|
@@ -13,13 +14,18 @@ import {
|
|
|
13
14
|
} from "../../store/scopes/queue-item";
|
|
14
15
|
import { BaseComposerRuntimeCore } from "./base-composer-runtime-core";
|
|
15
16
|
|
|
17
|
+
const isCancelable = (runtime: Omit<ThreadRuntimeCore, "composer">) => {
|
|
18
|
+
// capabilities is a subclass field assigned after this composer is constructed
|
|
19
|
+
if (!runtime.capabilities?.cancel) return false;
|
|
20
|
+
return getThreadRuntimeCoreIsRunning(runtime);
|
|
21
|
+
};
|
|
22
|
+
|
|
16
23
|
export class DefaultThreadComposerRuntimeCore
|
|
17
24
|
extends BaseComposerRuntimeCore
|
|
18
25
|
implements ThreadComposerRuntimeCore
|
|
19
26
|
{
|
|
20
|
-
private _canCancel = false;
|
|
21
27
|
public get canCancel() {
|
|
22
|
-
return this.
|
|
28
|
+
return isCancelable(this.runtime);
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
public get canSend() {
|
|
@@ -94,12 +100,14 @@ export class DefaultThreadComposerRuntimeCore
|
|
|
94
100
|
}
|
|
95
101
|
|
|
96
102
|
public connect() {
|
|
103
|
+
let lastCanCancel = false;
|
|
97
104
|
let lastIsSendDisabled = this.runtime.isSendDisabled;
|
|
98
105
|
let lastQueue = this.queue;
|
|
99
106
|
return this.runtime.subscribe(() => {
|
|
100
107
|
let changed = false;
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
const nextCanCancel = this.canCancel;
|
|
109
|
+
if (lastCanCancel !== nextCanCancel) {
|
|
110
|
+
lastCanCancel = nextCanCancel;
|
|
103
111
|
changed = true;
|
|
104
112
|
}
|
|
105
113
|
if (lastIsSendDisabled !== this.runtime.isSendDisabled) {
|
|
@@ -72,6 +72,11 @@ export type SubmitFeedbackOptions = {
|
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
export type ThreadSuggestion = {
|
|
75
|
+
/** Display heading for the suggestion. Falls back to the prompt when absent. */
|
|
76
|
+
title?: string;
|
|
77
|
+
/** Secondary display text shown alongside the title. */
|
|
78
|
+
label?: string;
|
|
79
|
+
/** The message text sent when the suggestion is selected. */
|
|
75
80
|
prompt: string;
|
|
76
81
|
};
|
|
77
82
|
|
|
@@ -156,6 +161,7 @@ export type ThreadRuntimeCore = Readonly<{
|
|
|
156
161
|
startRun: (config: StartRunConfig) => void;
|
|
157
162
|
resumeRun: (config: ResumeRunConfig) => void;
|
|
158
163
|
cancelRun: () => void;
|
|
164
|
+
unstable_notifySessionReset: () => void;
|
|
159
165
|
|
|
160
166
|
addToolResult: (options: AddToolResultOptions) => void;
|
|
161
167
|
resumeToolCall: (options: ResumeToolCallOptions) => void;
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type QueueItemState,
|
|
9
9
|
} from "../../store/scopes/queue-item";
|
|
10
10
|
import { generateId } from "../../utils/id";
|
|
11
|
+
import { notifyEventListeners } from "../../utils/notify-event-listeners";
|
|
11
12
|
import { getThreadMessageText } from "../../utils/text";
|
|
12
13
|
import type {
|
|
13
14
|
ExternalThreadQueueAdapter,
|
|
@@ -87,7 +88,7 @@ export const createMessageQueue = (
|
|
|
87
88
|
let interrupting = false;
|
|
88
89
|
|
|
89
90
|
const notify = () => {
|
|
90
|
-
|
|
91
|
+
notifyEventListeners(subscribers, undefined, "Message queue");
|
|
91
92
|
};
|
|
92
93
|
|
|
93
94
|
const setLanes = (next: Record<Lane, readonly QueueItemState[]>) => {
|
|
@@ -81,9 +81,9 @@ type RepositoryMessage = RepositoryParent & {
|
|
|
81
81
|
const findHead = (
|
|
82
82
|
message: RepositoryMessage | RepositoryParent,
|
|
83
83
|
): RepositoryMessage | null => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return null;
|
|
84
|
+
let current = message;
|
|
85
|
+
while (current.next) current = current.next;
|
|
86
|
+
return "current" in current ? current : null;
|
|
87
87
|
};
|
|
88
88
|
|
|
89
89
|
class CachedValue<T> {
|
|
@@ -116,11 +116,17 @@ export class MessageRepository {
|
|
|
116
116
|
};
|
|
117
117
|
|
|
118
118
|
private updateLevels(message: RepositoryMessage, newLevel: number) {
|
|
119
|
-
message
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
const pending = [{ message, level: newLevel }];
|
|
120
|
+
|
|
121
|
+
while (pending.length > 0) {
|
|
122
|
+
const current = pending.pop()!;
|
|
123
|
+
current.message.level = current.level;
|
|
124
|
+
|
|
125
|
+
for (const childId of current.message.children) {
|
|
126
|
+
const childMessage = this.messages.get(childId);
|
|
127
|
+
if (childMessage) {
|
|
128
|
+
pending.push({ message: childMessage, level: current.level + 1 });
|
|
129
|
+
}
|
|
124
130
|
}
|
|
125
131
|
}
|
|
126
132
|
}
|
|
@@ -135,7 +141,8 @@ export class MessageRepository {
|
|
|
135
141
|
|
|
136
142
|
if (operation === "relink" && parentOrRoot === newParentOrRoot) return;
|
|
137
143
|
|
|
138
|
-
|
|
144
|
+
// `link` receives a fresh ID from `addOrUpdateMessage`; only `relink` can introduce a cycle.
|
|
145
|
+
if (operation === "relink") {
|
|
139
146
|
for (
|
|
140
147
|
let current: RepositoryMessage | null = newParent;
|
|
141
148
|
current;
|
|
@@ -143,7 +150,7 @@ export class MessageRepository {
|
|
|
143
150
|
) {
|
|
144
151
|
if (current.current.id === child.current.id) {
|
|
145
152
|
throw new Error(
|
|
146
|
-
"MessageRepository(performOp/
|
|
153
|
+
"MessageRepository(performOp/relink): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui.",
|
|
147
154
|
);
|
|
148
155
|
}
|
|
149
156
|
}
|
|
@@ -396,16 +403,17 @@ export class MessageRepository {
|
|
|
396
403
|
const previousHead = this.head;
|
|
397
404
|
|
|
398
405
|
if (message.children.length > 0) {
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
406
|
+
const pending = [...message.children];
|
|
407
|
+
while (pending.length > 0) {
|
|
408
|
+
const childId = pending.pop()!;
|
|
409
|
+
const childMessage = this.messages.get(childId);
|
|
410
|
+
if (childMessage) {
|
|
411
|
+
for (const descendantId of childMessage.children) {
|
|
412
|
+
pending.push(descendantId);
|
|
405
413
|
}
|
|
414
|
+
this.messages.delete(childId);
|
|
406
415
|
}
|
|
407
|
-
}
|
|
408
|
-
deleteDescendants(message);
|
|
416
|
+
}
|
|
409
417
|
|
|
410
418
|
message.children = [];
|
|
411
419
|
message.next = null;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ThreadRuntimeCore } from "../interfaces/thread-runtime-core";
|
|
2
|
+
|
|
3
|
+
// Invalidation must stay re-entrant: StrictMode's simulated unmount runs the
|
|
4
|
+
// effect cleanup while the runtime object survives into the next mount, so a
|
|
5
|
+
// permanent disposed mark would swallow every later append.
|
|
6
|
+
const generations = new WeakMap<ThreadRuntimeCore, number>();
|
|
7
|
+
|
|
8
|
+
export const captureThreadRuntimeGeneration = (runtime: ThreadRuntimeCore) =>
|
|
9
|
+
generations.get(runtime) ?? 0;
|
|
10
|
+
|
|
11
|
+
export const isThreadRuntimeGenerationCurrent = (
|
|
12
|
+
runtime: ThreadRuntimeCore,
|
|
13
|
+
generation: number,
|
|
14
|
+
) => captureThreadRuntimeGeneration(runtime) === generation;
|
|
15
|
+
|
|
16
|
+
export const invalidateThreadRuntime = (runtime: ThreadRuntimeCore) => {
|
|
17
|
+
generations.set(runtime, captureThreadRuntimeGeneration(runtime) + 1);
|
|
18
|
+
};
|
|
@@ -14,5 +14,7 @@ export const pickExternalStoreSharedOptions = (
|
|
|
14
14
|
unstable_capabilities: options.unstable_capabilities,
|
|
15
15
|
suggestions: options.suggestions,
|
|
16
16
|
}) satisfies {
|
|
17
|
-
[
|
|
17
|
+
[
|
|
18
|
+
K in keyof Required<ExternalStoreSharedOptions>
|
|
19
|
+
]: ExternalStoreSharedOptions[K];
|
|
18
20
|
};
|
|
@@ -5,6 +5,8 @@ import type {
|
|
|
5
5
|
ThreadListRuntimeCore,
|
|
6
6
|
} from "../../runtime/interfaces/thread-list-runtime-core";
|
|
7
7
|
import type { ExternalStoreThreadListAdapter } from "./external-store-adapter";
|
|
8
|
+
import { invalidateThreadRuntime } from "../../runtime/utils/thread-runtime-lifecycle";
|
|
9
|
+
import { notifySubscribers } from "../../subscribable/subscribable";
|
|
8
10
|
|
|
9
11
|
export type ExternalStoreThreadFactory = () => ExternalStoreThreadRuntimeCore;
|
|
10
12
|
|
|
@@ -150,6 +152,7 @@ export class ExternalStoreThreadListRuntimeCore implements ThreadListRuntimeCore
|
|
|
150
152
|
|
|
151
153
|
// `initialLoad ||`: `_mainThread!` must be assigned on construction.
|
|
152
154
|
if (initialLoad || previousThreadId !== newThreadId) {
|
|
155
|
+
if (!initialLoad) invalidateThreadRuntime(this._mainThread);
|
|
153
156
|
this._mainThreadId = newThreadId;
|
|
154
157
|
this._mainThread = this.threadFactory();
|
|
155
158
|
}
|
|
@@ -268,6 +271,6 @@ export class ExternalStoreThreadListRuntimeCore implements ThreadListRuntimeCore
|
|
|
268
271
|
}
|
|
269
272
|
|
|
270
273
|
private _notifySubscribers() {
|
|
271
|
-
|
|
274
|
+
notifySubscribers(this._subscriptions);
|
|
272
275
|
}
|
|
273
276
|
}
|