@assistant-ui/core 0.3.12 → 0.3.14
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 +27 -15
- package/dist/adapters/voice.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.js +6 -6
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +2 -1
- package/dist/model-context/frame/host.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 +826 -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/client/interactable-model-context.d.ts.map +1 -1
- package/dist/react/client/interactable-model-context.js +5 -1
- package/dist/react/client/interactable-model-context.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 +13 -18
- 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/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 +22 -10
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +109 -71
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +8 -2
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +40 -13
- 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 +134 -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 +22 -12
- 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 +13 -3
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts +25 -0
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +72 -18
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +15 -0
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +34 -3
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.js +1 -6
- package/dist/runtime/base/default-edit-composer-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 +11 -8
- 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/external-thread-queue-adapter.d.ts +15 -0
- package/dist/runtime/queue/external-thread-queue-adapter.d.ts.map +1 -1
- package/dist/runtime/queue/message-queue.d.ts.map +1 -1
- package/dist/runtime/queue/message-queue.js +25 -11
- package/dist/runtime/queue/message-queue.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-adapter.d.ts +7 -0
- package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
- 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 +11 -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 +78 -20
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- 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 +55 -14
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +1 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +3 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.js +3 -0
- package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/types.d.ts +29 -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.d.ts +7 -0
- package/dist/store/clients/external-thread.d.ts.map +1 -1
- package/dist/store/clients/external-thread.js +460 -369
- package/dist/store/clients/external-thread.js.map +1 -1
- package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
- package/dist/store/clients/runtime-adapter.js +5 -2
- package/dist/store/clients/runtime-adapter.js.map +1 -1
- package/dist/store/clients/single-thread-list.d.ts.map +1 -1
- package/dist/store/clients/single-thread-list.js +31 -27
- package/dist/store/clients/single-thread-list.js.map +1 -1
- package/dist/store/clients/suggestions.d.ts +3 -1
- package/dist/store/clients/suggestions.d.ts.map +1 -1
- package/dist/store/clients/suggestions.js +65 -37
- 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 +6 -4
- package/dist/store/index.js +5 -3
- 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 +12 -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 +104 -57
- 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/runtime-clients/thread-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +98 -82
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scope-registration.d.ts +2 -2
- package/dist/store/scopes/composer.d.ts +9 -4
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/suggestions.d.ts +6 -1
- package/dist/store/scopes/suggestions.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 +25 -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/error.d.ts +15 -1
- package/dist/types/error.d.ts.map +1 -1
- package/dist/types/error.js +18 -1
- package/dist/types/error.js.map +1 -1
- package/dist/types/message.d.ts +2 -0
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js.map +1 -1
- package/dist/utils/composite-context-provider.d.ts +1 -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/package.json +7 -7
- 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 +69 -0
- package/src/adapters/voice.ts +27 -27
- package/src/index.ts +2 -0
- package/src/model-context/frame/host.test.ts +23 -0
- package/src/model-context/frame/host.ts +2 -1
- 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 +1026 -0
- package/src/react/client/RemoteThreadList.ts +1067 -0
- package/src/react/client/Tools.ts +36 -29
- package/src/react/client/interactable-model-context.ts +6 -1
- 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.ts +2 -7
- 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/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 +159 -124
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +59 -20
- package/src/react/runtimes/RemoteThreadResource.test.ts +141 -0
- package/src/react/runtimes/RemoteThreadResource.ts +231 -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 +625 -0
- package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +481 -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.tsx +36 -21
- 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 +124 -0
- package/src/react/runtimes/useExternalStoreRuntime.ts +7 -0
- package/src/react/runtimes/useExternalStoreSharedOptions.ts +3 -1
- package/src/react/runtimes/useLocalRuntime.test.tsx +130 -4
- 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 +28 -3
- package/src/runtime/base/base-composer-runtime-core.ts +106 -13
- package/src/runtime/base/base-thread-runtime-core.test.ts +191 -0
- package/src/runtime/base/base-thread-runtime-core.ts +47 -2
- package/src/runtime/base/default-edit-composer-runtime-core.ts +1 -15
- package/src/runtime/base/default-thread-composer-runtime-core.ts +13 -15
- package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
- package/src/runtime/queue/external-thread-queue-adapter.ts +17 -0
- package/src/runtime/queue/message-queue.ts +28 -10
- package/src/runtime/utils/thread-runtime-lifecycle.ts +18 -0
- package/src/runtimes/external-store/external-store-adapter.ts +7 -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 +187 -48
- package/src/runtimes/local/local-thread-runtime-core.test.ts +373 -4
- package/src/runtimes/local/local-thread-runtime-core.ts +83 -15
- package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +4 -0
- package/src/runtimes/remote-thread-list/empty-thread-core.ts +4 -0
- package/src/runtimes/remote-thread-list/types.ts +30 -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 +119 -16
- package/src/store/clients/model-context-client.test.ts +16 -8
- package/src/store/clients/runtime-adapter.ts +5 -2
- package/src/store/clients/single-thread-list.ts +2 -1
- package/src/store/clients/suggestions.ts +39 -13
- 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.ts +11 -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 +28 -35
- package/src/store/runtime-clients/thread-list-runtime-client.ts +9 -6
- package/src/store/runtime-clients/thread-runtime-client.ts +5 -0
- package/src/store/scopes/composer.ts +9 -4
- package/src/store/scopes/suggestions.ts +6 -0
- package/src/store/scopes/thread-list-item.ts +7 -6
- package/src/store/scopes/thread.ts +25 -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/RemoteThreadListThreadListRuntimeCore-switchToThread-unarchive.test.ts +25 -0
- package/src/tests/append-interactable-snapshots.test.ts +350 -0
- package/src/tests/auiV0Encode.test.ts +66 -0
- package/src/tests/base-composer-runtime-core-send.test.ts +156 -0
- package/src/tests/base-composer-runtime-core.test.ts +136 -1
- package/src/tests/composer-can-cancel.test.ts +101 -0
- package/src/tests/default-edit-composer-runtime-core.test.ts +0 -68
- package/src/tests/external-store-thread-list-runtime-core.test.ts +101 -0
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +491 -1
- package/src/tests/external-store-thread-runtime-core.test.ts +124 -0
- package/src/tests/external-thread-attachments.test.tsx +214 -0
- package/src/tests/external-thread-parity.test.tsx +54 -0
- package/src/tests/external-thread-refetch.test.tsx +117 -0
- package/src/tests/external-thread-suggestions.test.tsx +59 -0
- package/src/tests/interactables-toolui-migration.test.tsx +66 -0
- package/src/tests/message-queue.test.ts +54 -0
- package/src/tests/session-reset-notification.test.ts +145 -0
- package/src/tests/thread-message-like.test.ts +39 -0
- package/src/tests/thread-switch-events.test.tsx +234 -0
- package/src/tests/tools-scope-migration.test.tsx +58 -0
- package/src/types/error.ts +24 -0
- package/src/types/message.ts +2 -0
- 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/tests/default-thread-composer-runtime-core.test.ts +0 -82
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type PendingAttachment,
|
|
7
7
|
} from "../../types/attachment";
|
|
8
8
|
import type { MessageRole, AppendMessage } from "../../types/message";
|
|
9
|
+
import { isMessageNotSentError } from "../../types/error";
|
|
9
10
|
import type { QuoteInfo } from "../../types/quote";
|
|
10
11
|
import type { Unsubscribe } from "../../types/unsubscribe";
|
|
11
12
|
import type { RunConfig } from "../../types/message";
|
|
@@ -118,15 +119,22 @@ export abstract class BaseComposerRuntimeCore
|
|
|
118
119
|
if (this._text === value) return;
|
|
119
120
|
|
|
120
121
|
this._text = value;
|
|
121
|
-
|
|
122
|
-
this._dictationBaseText = value;
|
|
123
|
-
this._currentInterimText = "";
|
|
124
|
-
const { status, inputDisabled } = this._dictation;
|
|
125
|
-
this._dictation = inputDisabled ? { status, inputDisabled } : { status };
|
|
126
|
-
}
|
|
122
|
+
this._rebaseDictation(value);
|
|
127
123
|
this._notifySubscribers();
|
|
128
124
|
}
|
|
129
125
|
|
|
126
|
+
// A live dictation session appends to the text it last saw, so any write
|
|
127
|
+
// that bypasses `setText` has to move that baseline or the next transcript
|
|
128
|
+
// overwrites what was just written.
|
|
129
|
+
private _rebaseDictation(value: string) {
|
|
130
|
+
if (!this._dictation) return;
|
|
131
|
+
|
|
132
|
+
this._dictationBaseText = value;
|
|
133
|
+
this._currentInterimText = "";
|
|
134
|
+
const { status, inputDisabled } = this._dictation;
|
|
135
|
+
this._dictation = inputDisabled ? { status, inputDisabled } : { status };
|
|
136
|
+
}
|
|
137
|
+
|
|
130
138
|
public setRole(role: MessageRole) {
|
|
131
139
|
if (this._role === role) return;
|
|
132
140
|
|
|
@@ -232,6 +240,8 @@ export abstract class BaseComposerRuntimeCore
|
|
|
232
240
|
const originalAttachments = this.attachments;
|
|
233
241
|
const text = this.text;
|
|
234
242
|
const quote = this._quote;
|
|
243
|
+
const role = this.role;
|
|
244
|
+
const runConfig = this.runConfig;
|
|
235
245
|
this._quote = undefined;
|
|
236
246
|
this._text = "";
|
|
237
247
|
this._isSending = true;
|
|
@@ -245,6 +255,7 @@ export abstract class BaseComposerRuntimeCore
|
|
|
245
255
|
if (generation === this._sendGeneration) {
|
|
246
256
|
if (!this.text.trim() && this._quote === undefined) {
|
|
247
257
|
this._text = text;
|
|
258
|
+
this._rebaseDictation(text);
|
|
248
259
|
this._quote = quote;
|
|
249
260
|
this._notifySubscribers();
|
|
250
261
|
}
|
|
@@ -282,18 +293,101 @@ export abstract class BaseComposerRuntimeCore
|
|
|
282
293
|
|
|
283
294
|
const message: Omit<AppendMessage, "parentId" | "sourceId"> = {
|
|
284
295
|
createdAt: new Date(),
|
|
285
|
-
role
|
|
296
|
+
role,
|
|
286
297
|
content: text ? [{ type: "text", text }] : [],
|
|
287
298
|
attachments: finalAttachments,
|
|
288
|
-
runConfig
|
|
299
|
+
runConfig,
|
|
289
300
|
metadata: { custom: { ...(quote ? { quote } : {}) } },
|
|
290
301
|
};
|
|
291
302
|
|
|
292
|
-
const
|
|
293
|
-
|
|
303
|
+
const draft = { text, quote, attachments: finalAttachments };
|
|
304
|
+
let sendTask: void | Promise<void>;
|
|
305
|
+
try {
|
|
306
|
+
sendTask = this.handleSend(message, options);
|
|
307
|
+
} catch (error) {
|
|
308
|
+
this._restoreUnsentDraft(error, generation, draft);
|
|
309
|
+
throw error;
|
|
310
|
+
}
|
|
311
|
+
if (sendTask)
|
|
312
|
+
void sendTask.catch((error) => {
|
|
313
|
+
this._restoreUnsentDraft(error, generation, draft);
|
|
314
|
+
});
|
|
294
315
|
this._notifyEventSubscribers("send", {});
|
|
295
316
|
}
|
|
296
317
|
|
|
318
|
+
/**
|
|
319
|
+
* Take a message back into the composer when it has nowhere else to live:
|
|
320
|
+
* a send the runtime never dispatched, or a message a cancelled run is
|
|
321
|
+
* removing from the thread. Reports whether the composer accepted it, so a
|
|
322
|
+
* caller that is also removing the message can keep it instead of dropping
|
|
323
|
+
* it. Refused, and left untouched, while the composer holds anything of its
|
|
324
|
+
* own.
|
|
325
|
+
*/
|
|
326
|
+
public restoreDraft(draft: {
|
|
327
|
+
text: string;
|
|
328
|
+
quote?: QuoteInfo | undefined;
|
|
329
|
+
attachments?: readonly Attachment[] | undefined;
|
|
330
|
+
}): boolean {
|
|
331
|
+
if (
|
|
332
|
+
this._text.trim() ||
|
|
333
|
+
this._quote !== undefined ||
|
|
334
|
+
this._attachments.length > 0
|
|
335
|
+
)
|
|
336
|
+
return false;
|
|
337
|
+
|
|
338
|
+
this._text = draft.text;
|
|
339
|
+
this._rebaseDictation(draft.text);
|
|
340
|
+
this._quote = draft.quote;
|
|
341
|
+
this._attachments = draft.attachments ?? [];
|
|
342
|
+
this._notifySubscribers();
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Inverse of `restoreDraft`: clears the composer while it still holds
|
|
348
|
+
* exactly the given draft. A draft the user has edited since is left
|
|
349
|
+
* untouched.
|
|
350
|
+
*/
|
|
351
|
+
public retractDraft(draft: {
|
|
352
|
+
text: string;
|
|
353
|
+
quote?: QuoteInfo | undefined;
|
|
354
|
+
attachments?: readonly Attachment[] | undefined;
|
|
355
|
+
}): void {
|
|
356
|
+
const attachmentsUntouched =
|
|
357
|
+
draft.attachments !== undefined
|
|
358
|
+
? this._attachments === draft.attachments
|
|
359
|
+
: this._attachments.length === 0;
|
|
360
|
+
if (
|
|
361
|
+
this._text !== draft.text ||
|
|
362
|
+
this._quote !== draft.quote ||
|
|
363
|
+
!attachmentsUntouched
|
|
364
|
+
)
|
|
365
|
+
return;
|
|
366
|
+
|
|
367
|
+
this._text = "";
|
|
368
|
+
this._rebaseDictation("");
|
|
369
|
+
this._quote = undefined;
|
|
370
|
+
this._attachments = [];
|
|
371
|
+
this._notifySubscribers();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// The generation check is what a reset and a later send use to invalidate a
|
|
375
|
+
// draft, so of several queued drafts only the most recent one is still
|
|
376
|
+
// restorable.
|
|
377
|
+
private _restoreUnsentDraft(
|
|
378
|
+
error: unknown,
|
|
379
|
+
generation: number,
|
|
380
|
+
draft: {
|
|
381
|
+
text: string;
|
|
382
|
+
quote: QuoteInfo | undefined;
|
|
383
|
+
attachments: readonly CompleteAttachment[];
|
|
384
|
+
},
|
|
385
|
+
) {
|
|
386
|
+
if (!isMessageNotSentError(error)) return;
|
|
387
|
+
if (generation !== this._sendGeneration) return;
|
|
388
|
+
this.restoreDraft(draft);
|
|
389
|
+
}
|
|
390
|
+
|
|
297
391
|
public cancel() {
|
|
298
392
|
this.handleCancel();
|
|
299
393
|
}
|
|
@@ -626,9 +720,8 @@ export abstract class BaseComposerRuntimeCore
|
|
|
626
720
|
|
|
627
721
|
const session = this._dictationSession;
|
|
628
722
|
const sessionId = this._activeDictationSessionId;
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
});
|
|
723
|
+
const cleanup = () => this._cleanupDictation({ sessionId });
|
|
724
|
+
void session.stop().then(cleanup, cleanup);
|
|
632
725
|
}
|
|
633
726
|
|
|
634
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
|
+
});
|
|
@@ -35,6 +35,7 @@ import type { AttachmentAdapter } from "../../adapters/attachment";
|
|
|
35
35
|
import type { RealtimeVoiceAdapter } from "../../adapters/voice";
|
|
36
36
|
import type { ThreadMessageLike } from "../utils/thread-message-like";
|
|
37
37
|
import { notifyEventListeners } from "../../utils/notify-event-listeners";
|
|
38
|
+
import { gateInteractableComposerMetadata } from "../../model-context/interactable-composer-metadata";
|
|
38
39
|
|
|
39
40
|
type BaseThreadAdapters = {
|
|
40
41
|
speech?: SpeechSynthesisAdapter | undefined;
|
|
@@ -68,6 +69,7 @@ export abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
|
|
|
68
69
|
public abstract cancelRun(): void;
|
|
69
70
|
public abstract exportExternalState(): any;
|
|
70
71
|
public abstract importExternalState(state: any): void;
|
|
72
|
+
public abstract unstable_notifySessionReset(): void;
|
|
71
73
|
|
|
72
74
|
protected _voiceMessages: ThreadMessage[] = [];
|
|
73
75
|
protected _voiceGeneration = 0;
|
|
@@ -123,6 +125,41 @@ export abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
|
|
|
123
125
|
return this._contextProvider.getModelContext();
|
|
124
126
|
}
|
|
125
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Stamps provider-contributed composer metadata onto an outgoing message.
|
|
130
|
+
* Called at dispatch rather than in the composer, so programmatic sends are
|
|
131
|
+
* covered too, and exactly once per message: a queued send is stamped when
|
|
132
|
+
* it leaves the lane, never when it enters.
|
|
133
|
+
*
|
|
134
|
+
* Only user messages are stamped, matching the readers: both the version
|
|
135
|
+
* fold and the model injection skip every other role.
|
|
136
|
+
*
|
|
137
|
+
* @param anchorId Message the gated branch prefix ends at. A queued send
|
|
138
|
+
* passes the current tail, having waited through a run that grew the prefix
|
|
139
|
+
* past the parent it was created with.
|
|
140
|
+
*/
|
|
141
|
+
protected enrichAppendMetadata(
|
|
142
|
+
message: AppendMessage,
|
|
143
|
+
anchorId: string | null = message.parentId,
|
|
144
|
+
): AppendMessage {
|
|
145
|
+
if (message.role !== "user") return message;
|
|
146
|
+
const messages = this.messages;
|
|
147
|
+
const parentIndex =
|
|
148
|
+
anchorId === null ? -1 : messages.findIndex((m) => m.id === anchorId);
|
|
149
|
+
const composerMetadata = gateInteractableComposerMetadata(
|
|
150
|
+
this.getModelContext().unstable_composerMetadata,
|
|
151
|
+
messages.slice(0, parentIndex + 1),
|
|
152
|
+
);
|
|
153
|
+
if (!composerMetadata) return message;
|
|
154
|
+
return {
|
|
155
|
+
...message,
|
|
156
|
+
metadata: {
|
|
157
|
+
...message.metadata,
|
|
158
|
+
custom: { ...message.metadata?.custom, ...composerMetadata },
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
126
163
|
private _editComposers = new Map<string, DefaultEditComposerRuntimeCore>();
|
|
127
164
|
public getEditComposer(messageId: string) {
|
|
128
165
|
return this._editComposers.get(messageId);
|
|
@@ -319,7 +356,11 @@ export abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
|
|
|
319
356
|
unsubs.push(
|
|
320
357
|
session.onVolumeChange((volume) => {
|
|
321
358
|
this._voiceVolume = volume;
|
|
322
|
-
|
|
359
|
+
notifyEventListeners(
|
|
360
|
+
this._voiceVolumeSubscribers,
|
|
361
|
+
undefined,
|
|
362
|
+
"Voice volume",
|
|
363
|
+
);
|
|
323
364
|
}),
|
|
324
365
|
);
|
|
325
366
|
|
|
@@ -418,7 +459,11 @@ export abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
|
|
|
418
459
|
this._voiceSession = undefined;
|
|
419
460
|
this.voice = undefined;
|
|
420
461
|
this._voiceVolume = 0;
|
|
421
|
-
|
|
462
|
+
notifyEventListeners(
|
|
463
|
+
this._voiceVolumeSubscribers,
|
|
464
|
+
undefined,
|
|
465
|
+
"Voice volume",
|
|
466
|
+
);
|
|
422
467
|
this._voiceMessages = [];
|
|
423
468
|
this._markVoiceMessagesDirty();
|
|
424
469
|
this._notifySubscribers();
|
|
@@ -7,7 +7,6 @@ import type { DictationAdapter } from "../../adapters/speech";
|
|
|
7
7
|
import type { SendOptions } from "../interfaces/composer-runtime-core";
|
|
8
8
|
import type { ThreadRuntimeCore } from "../interfaces/thread-runtime-core";
|
|
9
9
|
import { BaseComposerRuntimeCore } from "./base-composer-runtime-core";
|
|
10
|
-
import { gateInteractableComposerMetadata } from "../../model-context/interactable-composer-metadata";
|
|
11
10
|
|
|
12
11
|
export class DefaultEditComposerRuntimeCore extends BaseComposerRuntimeCore {
|
|
13
12
|
public get canCancel() {
|
|
@@ -97,21 +96,8 @@ export class DefaultEditComposerRuntimeCore extends BaseComposerRuntimeCore {
|
|
|
97
96
|
...this._nonTextPassthrough,
|
|
98
97
|
] as AppendMessage["content"])
|
|
99
98
|
: message.content;
|
|
100
|
-
// Gate live state against the new branch's prefix (messages up to the
|
|
101
|
-
// parent): an unchanged interactable re-stamps the prior baseline, an
|
|
102
|
-
// interactable edited since the original message stamps its newest state.
|
|
103
|
-
const messages = this.runtime.messages;
|
|
104
|
-
const parentIndex =
|
|
105
|
-
this._parentId === null
|
|
106
|
-
? -1
|
|
107
|
-
: messages.findIndex((m) => m.id === this._parentId);
|
|
108
|
-
const composerMetadata = gateInteractableComposerMetadata(
|
|
109
|
-
this.runtime.getModelContext().unstable_composerMetadata,
|
|
110
|
-
messages.slice(0, parentIndex + 1),
|
|
111
|
-
);
|
|
112
|
-
const enriched = this.enrichWithComposerMetadata(message, composerMetadata);
|
|
113
99
|
const appendTask = this.runtime.append({
|
|
114
|
-
...
|
|
100
|
+
...message,
|
|
115
101
|
content,
|
|
116
102
|
parentId: this._parentId,
|
|
117
103
|
sourceId: this._sourceId,
|
|
@@ -6,21 +6,26 @@ 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,
|
|
12
13
|
type QueueItemState,
|
|
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
|
+
};
|
|
16
22
|
|
|
17
23
|
export class DefaultThreadComposerRuntimeCore
|
|
18
24
|
extends BaseComposerRuntimeCore
|
|
19
25
|
implements ThreadComposerRuntimeCore
|
|
20
26
|
{
|
|
21
|
-
private _canCancel = false;
|
|
22
27
|
public get canCancel() {
|
|
23
|
-
return this.
|
|
28
|
+
return isCancelable(this.runtime);
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
public get canSend() {
|
|
@@ -95,12 +100,14 @@ export class DefaultThreadComposerRuntimeCore
|
|
|
95
100
|
}
|
|
96
101
|
|
|
97
102
|
public connect() {
|
|
103
|
+
let lastCanCancel = false;
|
|
98
104
|
let lastIsSendDisabled = this.runtime.isSendDisabled;
|
|
99
105
|
let lastQueue = this.queue;
|
|
100
106
|
return this.runtime.subscribe(() => {
|
|
101
107
|
let changed = false;
|
|
102
|
-
|
|
103
|
-
|
|
108
|
+
const nextCanCancel = this.canCancel;
|
|
109
|
+
if (lastCanCancel !== nextCanCancel) {
|
|
110
|
+
lastCanCancel = nextCanCancel;
|
|
104
111
|
changed = true;
|
|
105
112
|
}
|
|
106
113
|
if (lastIsSendDisabled !== this.runtime.isSendDisabled) {
|
|
@@ -119,17 +126,8 @@ export class DefaultThreadComposerRuntimeCore
|
|
|
119
126
|
message: Omit<AppendMessage, "parentId" | "sourceId">,
|
|
120
127
|
options?: SendOptions,
|
|
121
128
|
) {
|
|
122
|
-
// Merge provider-contributed metadata onto the outgoing user message
|
|
123
|
-
// (same metadata.custom append path quotes ride). The interactables gate
|
|
124
|
-
// runs here because it needs thread history, unavailable to the provider.
|
|
125
|
-
const composerMetadata = gateInteractableComposerMetadata(
|
|
126
|
-
this.runtime.getModelContext().unstable_composerMetadata,
|
|
127
|
-
this.runtime.messages,
|
|
128
|
-
);
|
|
129
|
-
const enriched = this.enrichWithComposerMetadata(message, composerMetadata);
|
|
130
|
-
|
|
131
129
|
return this.runtime.append({
|
|
132
|
-
...(
|
|
130
|
+
...(message as AppendMessage),
|
|
133
131
|
parentId: this.runtime.messages.at(-1)?.id ?? null,
|
|
134
132
|
sourceId: null,
|
|
135
133
|
startRun: options?.startRun,
|
|
@@ -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;
|
|
@@ -27,4 +27,21 @@ export type ExternalThreadQueueAdapter = {
|
|
|
27
27
|
move: (queueItemId: string, placement: QueuePlacement) => void;
|
|
28
28
|
edit: (queueItemId: string, message: AppendMessage) => void;
|
|
29
29
|
remove: (queueItemId: string) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Installed by the owning runtime, applied to a message as it leaves a lane.
|
|
32
|
+
* A message can wait through an entire run, so state the runtime attaches at
|
|
33
|
+
* send time is recomputed against the thread it actually lands on. Adapters
|
|
34
|
+
* from `createMessageQueue` provide this; a hand-rolled adapter that omits
|
|
35
|
+
* it dispatches whatever was enqueued.
|
|
36
|
+
*/
|
|
37
|
+
__internal_setDispatchTransform?:
|
|
38
|
+
| ((transform: (message: AppendMessage) => AppendMessage) => void)
|
|
39
|
+
| undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Called by the owning runtime when the user cancels the run, before the run
|
|
42
|
+
* is aborted. Pauses the queue so the cancelled run's settle keeps the
|
|
43
|
+
* pending items instead of dispatching the next one; the next send re-arms
|
|
44
|
+
* draining. A hand-rolled adapter that omits it drains on cancel.
|
|
45
|
+
*/
|
|
46
|
+
__internal_notifyCancelled?: (() => void) | undefined;
|
|
30
47
|
};
|
|
@@ -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,
|
|
@@ -79,13 +80,15 @@ export const createMessageQueue = (
|
|
|
79
80
|
|
|
80
81
|
let running = false;
|
|
81
82
|
let paused = false;
|
|
83
|
+
let dispatchTransform: (message: AppendMessage) => AppendMessage = (m) => m;
|
|
82
84
|
// swallow the cancelled run's settle when steering so it does not double-advance
|
|
83
85
|
let suppressIdle = 0;
|
|
84
86
|
// settles from cancelled runs that must drop `running` without advancing
|
|
85
87
|
let cancelSettles = 0;
|
|
88
|
+
let interrupting = false;
|
|
86
89
|
|
|
87
90
|
const notify = () => {
|
|
88
|
-
|
|
91
|
+
notifyEventListeners(subscribers, undefined, "Message queue");
|
|
89
92
|
};
|
|
90
93
|
|
|
91
94
|
const setLanes = (next: Record<Lane, readonly QueueItemState[]>) => {
|
|
@@ -117,7 +120,7 @@ export const createMessageQueue = (
|
|
|
117
120
|
setLanes({ ...lanes, [lane]: lanes[lane].slice(1) });
|
|
118
121
|
if (!message) return;
|
|
119
122
|
running = true;
|
|
120
|
-
driver.run(message, { steer: false });
|
|
123
|
+
driver.run(dispatchTransform(message), { steer: false });
|
|
121
124
|
};
|
|
122
125
|
|
|
123
126
|
const interrupt = (message: AppendMessage) => {
|
|
@@ -126,9 +129,17 @@ export const createMessageQueue = (
|
|
|
126
129
|
// already cancel-notified
|
|
127
130
|
suppressIdle += Math.max(cancelSettles, 1);
|
|
128
131
|
cancelSettles = 0;
|
|
129
|
-
driver
|
|
132
|
+
// a driver whose cancel routes through the runtime notifies this queue
|
|
133
|
+
// back; the interrupt already accounted for that settle and is dispatching
|
|
134
|
+
// in its place
|
|
135
|
+
interrupting = true;
|
|
136
|
+
try {
|
|
137
|
+
driver.cancel!();
|
|
138
|
+
} finally {
|
|
139
|
+
interrupting = false;
|
|
140
|
+
}
|
|
130
141
|
running = true;
|
|
131
|
-
driver.run(message, { steer: true });
|
|
142
|
+
driver.run(dispatchTransform(message), { steer: true });
|
|
132
143
|
};
|
|
133
144
|
|
|
134
145
|
const push = (lane: Lane, message: AppendMessage) => {
|
|
@@ -241,6 +252,14 @@ export const createMessageQueue = (
|
|
|
241
252
|
});
|
|
242
253
|
};
|
|
243
254
|
|
|
255
|
+
const notifyCancelled = () => {
|
|
256
|
+
if (interrupting) return;
|
|
257
|
+
if (running && cancelSettles === 0) {
|
|
258
|
+
paused = true;
|
|
259
|
+
cancelSettles = 1;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
244
263
|
const adapter: ExternalThreadQueueAdapter = {
|
|
245
264
|
items: lanes.queue,
|
|
246
265
|
steerItems: lanes.steer,
|
|
@@ -249,6 +268,10 @@ export const createMessageQueue = (
|
|
|
249
268
|
move,
|
|
250
269
|
edit,
|
|
251
270
|
remove,
|
|
271
|
+
__internal_setDispatchTransform: (transform) => {
|
|
272
|
+
dispatchTransform = transform;
|
|
273
|
+
},
|
|
274
|
+
__internal_notifyCancelled: notifyCancelled,
|
|
252
275
|
};
|
|
253
276
|
|
|
254
277
|
return {
|
|
@@ -270,12 +293,7 @@ export const createMessageQueue = (
|
|
|
270
293
|
running = false;
|
|
271
294
|
advance();
|
|
272
295
|
},
|
|
273
|
-
notifyCancelled
|
|
274
|
-
if (running && cancelSettles === 0) {
|
|
275
|
-
paused = true;
|
|
276
|
-
cancelSettles = 1;
|
|
277
|
-
}
|
|
278
|
-
},
|
|
296
|
+
notifyCancelled,
|
|
279
297
|
clear: () => {
|
|
280
298
|
messages.clear();
|
|
281
299
|
setLanes({ queue: EMPTY_QUEUE_ITEMS, steer: EMPTY_QUEUE_ITEMS });
|