@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
package/src/adapters/speech.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Unsubscribe } from "../types/unsubscribe";
|
|
2
|
+
import { notifyEventListeners } from "../utils/notify-event-listeners";
|
|
2
3
|
|
|
3
4
|
export namespace SpeechSynthesisAdapter {
|
|
4
5
|
export type Status =
|
|
@@ -22,21 +23,6 @@ export type SpeechSynthesisAdapter = {
|
|
|
22
23
|
speak: (text: string) => SpeechSynthesisAdapter.Utterance;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
|
-
const notifySpeechSynthesisListeners = (
|
|
26
|
-
listeners: Iterable<() => void>,
|
|
27
|
-
): void => {
|
|
28
|
-
for (const listener of listeners) {
|
|
29
|
-
try {
|
|
30
|
-
listener();
|
|
31
|
-
} catch (error) {
|
|
32
|
-
console.error(
|
|
33
|
-
"[assistant-ui] Speech synthesis listener threw an error",
|
|
34
|
-
error,
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
|
|
40
26
|
export namespace DictationAdapter {
|
|
41
27
|
export type Status =
|
|
42
28
|
| {
|
|
@@ -79,7 +65,7 @@ export class WebSpeechSynthesisAdapter implements SpeechSynthesisAdapter {
|
|
|
79
65
|
if (res.status.type === "ended") return;
|
|
80
66
|
|
|
81
67
|
res.status = { type: "ended", reason, error };
|
|
82
|
-
|
|
68
|
+
notifyEventListeners(subscribers, undefined, "Speech synthesis");
|
|
83
69
|
};
|
|
84
70
|
|
|
85
71
|
utterance.addEventListener("end", () => handleEnd("finished"));
|
|
@@ -97,7 +83,9 @@ export class WebSpeechSynthesisAdapter implements SpeechSynthesisAdapter {
|
|
|
97
83
|
if (res.status.type === "ended") {
|
|
98
84
|
let cancelled = false;
|
|
99
85
|
queueMicrotask(() => {
|
|
100
|
-
if (!cancelled)
|
|
86
|
+
if (!cancelled) {
|
|
87
|
+
notifyEventListeners([callback], undefined, "Speech synthesis");
|
|
88
|
+
}
|
|
101
89
|
});
|
|
102
90
|
return () => {
|
|
103
91
|
cancelled = true;
|
|
@@ -270,7 +258,7 @@ export class WebSpeechDictationAdapter implements DictationAdapter {
|
|
|
270
258
|
};
|
|
271
259
|
|
|
272
260
|
recognition.addEventListener("speechstart", () => {
|
|
273
|
-
|
|
261
|
+
notifyEventListeners(speechStartCallbacks, undefined, "Dictation");
|
|
274
262
|
});
|
|
275
263
|
|
|
276
264
|
recognition.addEventListener("start", () => {
|
|
@@ -292,9 +280,17 @@ export class WebSpeechDictationAdapter implements DictationAdapter {
|
|
|
292
280
|
|
|
293
281
|
if (result.isFinal) {
|
|
294
282
|
finalTranscript += transcript;
|
|
295
|
-
|
|
283
|
+
notifyEventListeners(
|
|
284
|
+
speechCallbacks,
|
|
285
|
+
() => ({ transcript, isFinal: true }),
|
|
286
|
+
"Dictation",
|
|
287
|
+
);
|
|
296
288
|
} else {
|
|
297
|
-
|
|
289
|
+
notifyEventListeners(
|
|
290
|
+
speechCallbacks,
|
|
291
|
+
() => ({ transcript, isFinal: false }),
|
|
292
|
+
"Dictation",
|
|
293
|
+
);
|
|
298
294
|
}
|
|
299
295
|
}
|
|
300
296
|
});
|
|
@@ -309,8 +305,11 @@ export class WebSpeechDictationAdapter implements DictationAdapter {
|
|
|
309
305
|
updateStatus({ type: "ended", reason: "stopped" });
|
|
310
306
|
}
|
|
311
307
|
if (finalTranscript) {
|
|
312
|
-
|
|
313
|
-
|
|
308
|
+
notifyEventListeners(
|
|
309
|
+
speechEndCallbacks,
|
|
310
|
+
() => ({ transcript: finalTranscript }),
|
|
311
|
+
"Dictation",
|
|
312
|
+
);
|
|
314
313
|
finalTranscript = "";
|
|
315
314
|
}
|
|
316
315
|
});
|
|
@@ -39,6 +39,8 @@ export interface MessageFormatAdapter<
|
|
|
39
39
|
|
|
40
40
|
export type GenericThreadHistoryAdapter<TMessage> = {
|
|
41
41
|
load(): Promise<MessageFormatRepository<TMessage>>;
|
|
42
|
+
/** Snapshot the current thread so later writes survive a switch. */
|
|
43
|
+
pin?(): void;
|
|
42
44
|
append(item: MessageFormatItem<TMessage>): Promise<void>;
|
|
43
45
|
update?(
|
|
44
46
|
item: MessageFormatItem<TMessage>,
|
|
@@ -73,6 +73,140 @@ describe("createVoiceSession", () => {
|
|
|
73
73
|
expect(controls.mute).not.toHaveBeenCalled();
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
+
it("disconnects immediately when created with an already-aborted signal", async () => {
|
|
77
|
+
const abortController = new AbortController();
|
|
78
|
+
abortController.abort();
|
|
79
|
+
const setup = vi.fn(async () => ({
|
|
80
|
+
disconnect: vi.fn(),
|
|
81
|
+
mute: vi.fn(),
|
|
82
|
+
unmute: vi.fn(),
|
|
83
|
+
}));
|
|
84
|
+
|
|
85
|
+
const session = createVoiceSession(
|
|
86
|
+
{ abortSignal: abortController.signal },
|
|
87
|
+
setup,
|
|
88
|
+
);
|
|
89
|
+
await Promise.resolve();
|
|
90
|
+
|
|
91
|
+
expect(setup).not.toHaveBeenCalled();
|
|
92
|
+
expect(session.status).toEqual({ type: "ended", reason: "cancelled" });
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("removes the abort listener after disconnecting", async () => {
|
|
96
|
+
const abortController = new AbortController();
|
|
97
|
+
const controls = {
|
|
98
|
+
disconnect: vi.fn(),
|
|
99
|
+
mute: vi.fn(),
|
|
100
|
+
unmute: vi.fn(),
|
|
101
|
+
};
|
|
102
|
+
const session = createVoiceSession(
|
|
103
|
+
{ abortSignal: abortController.signal },
|
|
104
|
+
async () => controls,
|
|
105
|
+
);
|
|
106
|
+
await Promise.resolve();
|
|
107
|
+
const statusListener = vi.fn();
|
|
108
|
+
session.onStatusChange(statusListener);
|
|
109
|
+
|
|
110
|
+
session.disconnect();
|
|
111
|
+
session.disconnect();
|
|
112
|
+
abortController.abort();
|
|
113
|
+
|
|
114
|
+
expect(session.status).toEqual({ type: "ended", reason: "cancelled" });
|
|
115
|
+
expect(statusListener).toHaveBeenCalledOnce();
|
|
116
|
+
expect(statusListener).toHaveBeenCalledWith({
|
|
117
|
+
type: "ended",
|
|
118
|
+
reason: "cancelled",
|
|
119
|
+
});
|
|
120
|
+
expect(controls.disconnect).toHaveBeenCalledOnce();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("ends a running session when the abort signal fires", async () => {
|
|
124
|
+
const abortController = new AbortController();
|
|
125
|
+
const controls = {
|
|
126
|
+
disconnect: vi.fn(),
|
|
127
|
+
mute: vi.fn(),
|
|
128
|
+
unmute: vi.fn(),
|
|
129
|
+
};
|
|
130
|
+
let helpers: VoiceSessionHelpers | undefined;
|
|
131
|
+
const session = createVoiceSession(
|
|
132
|
+
{ abortSignal: abortController.signal },
|
|
133
|
+
async (sessionHelpers) => {
|
|
134
|
+
helpers = sessionHelpers;
|
|
135
|
+
return controls;
|
|
136
|
+
},
|
|
137
|
+
);
|
|
138
|
+
await Promise.resolve();
|
|
139
|
+
if (!helpers) throw new Error("Voice session setup did not start");
|
|
140
|
+
|
|
141
|
+
helpers.setStatus({ type: "running" });
|
|
142
|
+
const statusListener = vi.fn();
|
|
143
|
+
session.onStatusChange(statusListener);
|
|
144
|
+
|
|
145
|
+
abortController.abort();
|
|
146
|
+
|
|
147
|
+
expect(session.status).toEqual({ type: "ended", reason: "cancelled" });
|
|
148
|
+
expect(statusListener).toHaveBeenCalledOnce();
|
|
149
|
+
expect(statusListener).toHaveBeenCalledWith({
|
|
150
|
+
type: "ended",
|
|
151
|
+
reason: "cancelled",
|
|
152
|
+
});
|
|
153
|
+
expect(controls.disconnect).toHaveBeenCalledOnce();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("keeps abort teardown available after the session ends", async () => {
|
|
157
|
+
const abortController = new AbortController();
|
|
158
|
+
const controls = {
|
|
159
|
+
disconnect: vi.fn(),
|
|
160
|
+
mute: vi.fn(),
|
|
161
|
+
unmute: vi.fn(),
|
|
162
|
+
};
|
|
163
|
+
let helpers: VoiceSessionHelpers | undefined;
|
|
164
|
+
const session = createVoiceSession(
|
|
165
|
+
{ abortSignal: abortController.signal },
|
|
166
|
+
async (sessionHelpers) => {
|
|
167
|
+
helpers = sessionHelpers;
|
|
168
|
+
return controls;
|
|
169
|
+
},
|
|
170
|
+
);
|
|
171
|
+
await Promise.resolve();
|
|
172
|
+
if (!helpers) throw new Error("Voice session setup did not start");
|
|
173
|
+
|
|
174
|
+
helpers.end("error");
|
|
175
|
+
abortController.abort();
|
|
176
|
+
|
|
177
|
+
expect(session.status).toEqual({
|
|
178
|
+
type: "ended",
|
|
179
|
+
reason: "error",
|
|
180
|
+
error: undefined,
|
|
181
|
+
});
|
|
182
|
+
expect(controls.disconnect).toHaveBeenCalledOnce();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("cleans up when the adapter disconnect throws", async () => {
|
|
186
|
+
const disconnectError = new Error("disconnect failed");
|
|
187
|
+
let helpers: VoiceSessionHelpers | undefined;
|
|
188
|
+
const session = createVoiceSession({}, async (sessionHelpers) => {
|
|
189
|
+
helpers = sessionHelpers;
|
|
190
|
+
return {
|
|
191
|
+
disconnect: () => {
|
|
192
|
+
throw disconnectError;
|
|
193
|
+
},
|
|
194
|
+
mute: vi.fn(),
|
|
195
|
+
unmute: vi.fn(),
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
await Promise.resolve();
|
|
199
|
+
if (!helpers) throw new Error("Voice session setup did not start");
|
|
200
|
+
const transcriptListener = vi.fn();
|
|
201
|
+
session.onTranscript(transcriptListener);
|
|
202
|
+
|
|
203
|
+
expect(() => session.disconnect()).toThrow(disconnectError);
|
|
204
|
+
expect(helpers.isDisposed()).toBe(true);
|
|
205
|
+
|
|
206
|
+
helpers.emitTranscript({ role: "assistant", text: "stale" });
|
|
207
|
+
expect(transcriptListener).not.toHaveBeenCalled();
|
|
208
|
+
});
|
|
209
|
+
|
|
76
210
|
it("continues notifying listeners when one throws", () => {
|
|
77
211
|
const listenerError = new Error("listener failed");
|
|
78
212
|
const consoleError = vi
|
package/src/adapters/voice.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Unsubscribe } from "../types/unsubscribe";
|
|
2
|
+
import { notifyEventListeners } from "../utils/notify-event-listeners";
|
|
2
3
|
|
|
3
4
|
export namespace RealtimeVoiceAdapter {
|
|
4
5
|
export type Status =
|
|
@@ -57,22 +58,6 @@ export type VoiceSessionHelpers = {
|
|
|
57
58
|
isDisposed: () => boolean;
|
|
58
59
|
};
|
|
59
60
|
|
|
60
|
-
const notifyListeners = <T>(
|
|
61
|
-
listeners: ReadonlySet<(value: T) => void>,
|
|
62
|
-
value: T,
|
|
63
|
-
) => {
|
|
64
|
-
for (const listener of listeners) {
|
|
65
|
-
try {
|
|
66
|
-
listener(value);
|
|
67
|
-
} catch (error) {
|
|
68
|
-
console.error(
|
|
69
|
-
"[assistant-ui] Voice session listener threw an error",
|
|
70
|
-
error,
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
61
|
export function createVoiceSession(
|
|
77
62
|
options: { abortSignal?: AbortSignal },
|
|
78
63
|
setup: (helpers: VoiceSessionHelpers) => Promise<VoiceSessionControls>,
|
|
@@ -87,7 +72,17 @@ export function createVoiceSession(
|
|
|
87
72
|
let currentStatus: RealtimeVoiceAdapter.Status = { type: "starting" };
|
|
88
73
|
let isMuted = false;
|
|
89
74
|
let disposed = false;
|
|
75
|
+
let disconnected = false;
|
|
90
76
|
let controls: VoiceSessionControls | null = null;
|
|
77
|
+
const abortSignal = options.abortSignal;
|
|
78
|
+
let abortHandler: (() => void) | undefined;
|
|
79
|
+
|
|
80
|
+
const detachAbortHandler = () => {
|
|
81
|
+
if (abortHandler) {
|
|
82
|
+
abortSignal?.removeEventListener("abort", abortHandler);
|
|
83
|
+
abortHandler = undefined;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
91
86
|
|
|
92
87
|
const cleanup = () => {
|
|
93
88
|
disposed = true;
|
|
@@ -101,25 +96,25 @@ export function createVoiceSession(
|
|
|
101
96
|
setStatus: (status) => {
|
|
102
97
|
if (disposed) return;
|
|
103
98
|
currentStatus = status;
|
|
104
|
-
|
|
99
|
+
notifyEventListeners(statusCbs, status, "Voice session");
|
|
105
100
|
},
|
|
106
101
|
end: (reason, error?) => {
|
|
107
102
|
if (disposed) return;
|
|
108
103
|
currentStatus = { type: "ended", reason, error };
|
|
109
|
-
|
|
104
|
+
notifyEventListeners(statusCbs, currentStatus, "Voice session");
|
|
110
105
|
cleanup();
|
|
111
106
|
},
|
|
112
107
|
emitTranscript: (item) => {
|
|
113
108
|
if (disposed) return;
|
|
114
|
-
|
|
109
|
+
notifyEventListeners(transcriptCbs, item, "Voice session");
|
|
115
110
|
},
|
|
116
111
|
emitMode: (mode) => {
|
|
117
112
|
if (disposed) return;
|
|
118
|
-
|
|
113
|
+
notifyEventListeners(modeCbs, mode, "Voice session");
|
|
119
114
|
},
|
|
120
115
|
emitVolume: (volume) => {
|
|
121
116
|
if (disposed) return;
|
|
122
|
-
|
|
117
|
+
notifyEventListeners(volumeCbs, volume, "Voice session");
|
|
123
118
|
},
|
|
124
119
|
isDisposed: () => disposed,
|
|
125
120
|
};
|
|
@@ -132,8 +127,18 @@ export function createVoiceSession(
|
|
|
132
127
|
return isMuted;
|
|
133
128
|
},
|
|
134
129
|
disconnect: () => {
|
|
135
|
-
|
|
136
|
-
|
|
130
|
+
if (disconnected) return;
|
|
131
|
+
disconnected = true;
|
|
132
|
+
detachAbortHandler();
|
|
133
|
+
if (currentStatus.type !== "ended") {
|
|
134
|
+
currentStatus = { type: "ended", reason: "cancelled" };
|
|
135
|
+
notifyEventListeners(statusCbs, currentStatus, "Voice session");
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
controls?.disconnect();
|
|
139
|
+
} finally {
|
|
140
|
+
cleanup();
|
|
141
|
+
}
|
|
137
142
|
},
|
|
138
143
|
mute: () => {
|
|
139
144
|
controls?.mute();
|
|
@@ -161,10 +166,13 @@ export function createVoiceSession(
|
|
|
161
166
|
},
|
|
162
167
|
};
|
|
163
168
|
|
|
164
|
-
if (
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
169
|
+
if (abortSignal) {
|
|
170
|
+
abortHandler = () => session.disconnect();
|
|
171
|
+
abortSignal.addEventListener("abort", abortHandler, { once: true });
|
|
172
|
+
if (abortSignal.aborted) {
|
|
173
|
+
session.disconnect();
|
|
174
|
+
return session;
|
|
175
|
+
}
|
|
168
176
|
}
|
|
169
177
|
|
|
170
178
|
const doSetup = async () => {
|
package/src/index.ts
CHANGED
package/src/internal.ts
CHANGED
|
@@ -33,6 +33,7 @@ export {
|
|
|
33
33
|
// Message utilities
|
|
34
34
|
export { getThreadMessageText } from "./utils/text";
|
|
35
35
|
export { toMessagePartStatus } from "./utils/normalizePartStatus";
|
|
36
|
+
export { notifyEventListeners } from "./utils/notify-event-listeners";
|
|
36
37
|
export { resolveToolApprovalResponse } from "./runtime/utils/resolveToolApprovalResponse";
|
|
37
38
|
export { consumeSuggestionResult } from "./adapters/suggestion";
|
|
38
39
|
|
|
@@ -46,7 +46,15 @@ const createHost = () => {
|
|
|
46
46
|
const execute = host.getModelContext().tools?.search?.execute;
|
|
47
47
|
if (!execute) throw new Error("Expected the search tool to be available");
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
const getToolCallId = () => {
|
|
50
|
+
const call = postMessage.mock.calls.find(
|
|
51
|
+
([data]) => data.message.type === "tool-call",
|
|
52
|
+
);
|
|
53
|
+
if (!call) throw new Error("Expected a tool call to be posted");
|
|
54
|
+
return call[0].message.id as string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
return { dispatchMessage, execute, getToolCallId, host, postMessage };
|
|
50
58
|
};
|
|
51
59
|
|
|
52
60
|
beforeEach(() => {
|
|
@@ -60,14 +68,14 @@ afterEach(() => {
|
|
|
60
68
|
|
|
61
69
|
describe("AssistantFrameHost", () => {
|
|
62
70
|
it("resolves tool calls from frame results", async () => {
|
|
63
|
-
const { dispatchMessage, execute, host } = createHost();
|
|
71
|
+
const { dispatchMessage, execute, getToolCallId, host } = createHost();
|
|
64
72
|
const result = Promise.resolve(
|
|
65
73
|
execute({ query: "weather" }, executionContext),
|
|
66
74
|
);
|
|
67
75
|
|
|
68
76
|
dispatchMessage({
|
|
69
77
|
type: "tool-result",
|
|
70
|
-
id:
|
|
78
|
+
id: getToolCallId(),
|
|
71
79
|
result: "sunny",
|
|
72
80
|
});
|
|
73
81
|
|
|
@@ -77,19 +85,27 @@ describe("AssistantFrameHost", () => {
|
|
|
77
85
|
});
|
|
78
86
|
|
|
79
87
|
it("rejects pending tool calls when disposed", async () => {
|
|
80
|
-
const { execute, host } = createHost();
|
|
88
|
+
const { execute, getToolCallId, host, postMessage } = createHost();
|
|
81
89
|
const result = Promise.resolve(execute({}, executionContext));
|
|
90
|
+
const toolCallId = getToolCallId();
|
|
82
91
|
|
|
83
92
|
host.dispose();
|
|
84
93
|
|
|
85
94
|
await expect(result).rejects.toThrow(
|
|
86
95
|
"AssistantFrameHost has been disposed",
|
|
87
96
|
);
|
|
97
|
+
expect(postMessage).toHaveBeenLastCalledWith(
|
|
98
|
+
{
|
|
99
|
+
channel: FRAME_MESSAGE_CHANNEL,
|
|
100
|
+
message: { type: "tool-cancel", id: toolCallId },
|
|
101
|
+
},
|
|
102
|
+
"*",
|
|
103
|
+
);
|
|
88
104
|
expect(vi.getTimerCount()).toBe(0);
|
|
89
105
|
});
|
|
90
106
|
|
|
91
107
|
it("rejects pending tool calls when execution is aborted", async () => {
|
|
92
|
-
const { execute, host } = createHost();
|
|
108
|
+
const { execute, getToolCallId, host, postMessage } = createHost();
|
|
93
109
|
const abortController = new AbortController();
|
|
94
110
|
const abortError = new Error("Run cancelled");
|
|
95
111
|
abortError.name = "AbortError";
|
|
@@ -104,15 +120,58 @@ describe("AssistantFrameHost", () => {
|
|
|
104
120
|
);
|
|
105
121
|
const onRejected = vi.fn();
|
|
106
122
|
void result.catch(onRejected);
|
|
123
|
+
const toolCallId = getToolCallId();
|
|
107
124
|
|
|
108
125
|
abortController.abort(abortError);
|
|
109
126
|
await Promise.resolve();
|
|
110
127
|
|
|
111
128
|
expect(onRejected).toHaveBeenCalledWith(abortError);
|
|
129
|
+
expect(postMessage).toHaveBeenLastCalledWith(
|
|
130
|
+
{
|
|
131
|
+
channel: FRAME_MESSAGE_CHANNEL,
|
|
132
|
+
message: { type: "tool-cancel", id: toolCallId },
|
|
133
|
+
},
|
|
134
|
+
"*",
|
|
135
|
+
);
|
|
136
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
137
|
+
host.dispose();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("cancels tool calls when they time out", async () => {
|
|
141
|
+
const { execute, getToolCallId, host, postMessage } = createHost();
|
|
142
|
+
const result = Promise.resolve(execute({}, executionContext));
|
|
143
|
+
const toolCallId = getToolCallId();
|
|
144
|
+
const rejection = expect(result).rejects.toThrow(
|
|
145
|
+
'Tool call "search" timed out',
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
await vi.advanceTimersByTimeAsync(30000);
|
|
149
|
+
|
|
150
|
+
await rejection;
|
|
151
|
+
expect(postMessage).toHaveBeenLastCalledWith(
|
|
152
|
+
{
|
|
153
|
+
channel: FRAME_MESSAGE_CHANNEL,
|
|
154
|
+
message: { type: "tool-cancel", id: toolCallId },
|
|
155
|
+
},
|
|
156
|
+
"*",
|
|
157
|
+
);
|
|
112
158
|
expect(vi.getTimerCount()).toBe(0);
|
|
113
159
|
host.dispose();
|
|
114
160
|
});
|
|
115
161
|
|
|
162
|
+
it("uses unique tool IDs across host instances", () => {
|
|
163
|
+
const first = createHost();
|
|
164
|
+
const second = createHost();
|
|
165
|
+
|
|
166
|
+
void first.execute({}, executionContext).catch(() => undefined);
|
|
167
|
+
void second.execute({}, executionContext).catch(() => undefined);
|
|
168
|
+
|
|
169
|
+
expect(first.getToolCallId()).not.toBe(second.getToolCallId());
|
|
170
|
+
|
|
171
|
+
first.host.dispose();
|
|
172
|
+
second.host.dispose();
|
|
173
|
+
});
|
|
174
|
+
|
|
116
175
|
it("does not post tool calls when execution is already aborted", async () => {
|
|
117
176
|
const { execute, host, postMessage } = createHost();
|
|
118
177
|
const abortController = new AbortController();
|
|
@@ -144,4 +203,27 @@ describe("AssistantFrameHost", () => {
|
|
|
144
203
|
);
|
|
145
204
|
expect(postMessage).toHaveBeenCalledOnce();
|
|
146
205
|
});
|
|
206
|
+
|
|
207
|
+
it("isolates subscriber errors while applying context updates", () => {
|
|
208
|
+
const { dispatchMessage, host } = createHost();
|
|
209
|
+
const error = new Error("subscriber failed");
|
|
210
|
+
const laterSubscriber = vi.fn();
|
|
211
|
+
|
|
212
|
+
host.subscribe(() => {
|
|
213
|
+
throw error;
|
|
214
|
+
});
|
|
215
|
+
host.subscribe(laterSubscriber);
|
|
216
|
+
|
|
217
|
+
expect(() =>
|
|
218
|
+
dispatchMessage({
|
|
219
|
+
type: "model-context-update",
|
|
220
|
+
context: { system: "frame instructions" },
|
|
221
|
+
}),
|
|
222
|
+
).toThrow(error);
|
|
223
|
+
|
|
224
|
+
expect(host.getModelContext().system).toBe("frame instructions");
|
|
225
|
+
expect(laterSubscriber).toHaveBeenCalledOnce();
|
|
226
|
+
|
|
227
|
+
host.dispose();
|
|
228
|
+
});
|
|
147
229
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ModelContextProvider, ModelContext } from "../types";
|
|
2
2
|
import type { Unsubscribe } from "../../types/unsubscribe";
|
|
3
3
|
import type { Tool } from "assistant-stream";
|
|
4
|
+
import { notifySubscribers as notifyStateSubscribers } from "../../subscribable/subscribable";
|
|
5
|
+
import { generateId } from "../../utils/id";
|
|
4
6
|
import {
|
|
5
7
|
type FrameMessage,
|
|
6
8
|
FRAME_MESSAGE_CHANNEL,
|
|
@@ -57,7 +59,6 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
57
59
|
reject: (error: any) => void;
|
|
58
60
|
}
|
|
59
61
|
>();
|
|
60
|
-
private _requestCounter = 0;
|
|
61
62
|
private _iframeWindow: Window;
|
|
62
63
|
private _targetOrigin: string;
|
|
63
64
|
private _disposed = false;
|
|
@@ -129,7 +130,7 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
129
130
|
return this.sendRequest(
|
|
130
131
|
{
|
|
131
132
|
type: "tool-call",
|
|
132
|
-
id: `tool-${
|
|
133
|
+
id: `tool-${generateId()}`,
|
|
133
134
|
toolName,
|
|
134
135
|
args,
|
|
135
136
|
},
|
|
@@ -158,6 +159,7 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
158
159
|
if (!abortSignal) return;
|
|
159
160
|
const pending = this._pendingRequests.get(message.id);
|
|
160
161
|
if (pending) {
|
|
162
|
+
this.cancelToolCall(message.id);
|
|
161
163
|
pending.reject(getAbortReason(abortSignal));
|
|
162
164
|
this._pendingRequests.delete(message.id);
|
|
163
165
|
}
|
|
@@ -181,6 +183,7 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
181
183
|
timeoutId = setTimeout(() => {
|
|
182
184
|
const pending = this._pendingRequests.get(message.id);
|
|
183
185
|
if (pending) {
|
|
186
|
+
this.cancelToolCall(message.id);
|
|
184
187
|
pending.reject(new Error(timeoutMessage));
|
|
185
188
|
this._pendingRequests.delete(message.id);
|
|
186
189
|
}
|
|
@@ -194,6 +197,16 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
194
197
|
});
|
|
195
198
|
}
|
|
196
199
|
|
|
200
|
+
private cancelToolCall(id: string) {
|
|
201
|
+
this._iframeWindow.postMessage(
|
|
202
|
+
{
|
|
203
|
+
channel: FRAME_MESSAGE_CHANNEL,
|
|
204
|
+
message: { type: "tool-cancel", id } satisfies FrameMessage,
|
|
205
|
+
},
|
|
206
|
+
this._targetOrigin,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
197
210
|
private requestContext() {
|
|
198
211
|
this._iframeWindow.postMessage(
|
|
199
212
|
{
|
|
@@ -207,7 +220,7 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
207
220
|
}
|
|
208
221
|
|
|
209
222
|
private notifySubscribers() {
|
|
210
|
-
this._subscribers
|
|
223
|
+
notifyStateSubscribers(this._subscribers);
|
|
211
224
|
}
|
|
212
225
|
|
|
213
226
|
getModelContext(): ModelContext {
|
|
@@ -224,7 +237,8 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
224
237
|
window.removeEventListener("message", this.handleMessage);
|
|
225
238
|
this._subscribers.clear();
|
|
226
239
|
const error = new Error("AssistantFrameHost has been disposed");
|
|
227
|
-
for (const pending of this._pendingRequests
|
|
240
|
+
for (const [id, pending] of this._pendingRequests) {
|
|
241
|
+
this.cancelToolCall(id);
|
|
228
242
|
pending.reject(error);
|
|
229
243
|
}
|
|
230
244
|
this._pendingRequests.clear();
|