@assistant-ui/core 0.3.17 → 0.3.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/attachment.d.ts.map +1 -1
- package/dist/adapters/attachment.js +5 -4
- package/dist/adapters/attachment.js.map +1 -1
- package/dist/adapters/speech.d.ts.map +1 -1
- package/dist/adapters/speech.js +13 -3
- package/dist/adapters/speech.js.map +1 -1
- package/dist/adapters/thread-history.d.ts +4 -0
- package/dist/adapters/thread-history.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +4 -3
- package/dist/internal.js +3 -2
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +35 -14
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/frame/provider.d.ts +2 -0
- package/dist/model-context/frame/provider.d.ts.map +1 -1
- package/dist/model-context/frame/provider.js +30 -7
- package/dist/model-context/frame/provider.js.map +1 -1
- package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -1
- package/dist/model-context/interactable-composer-metadata.js +27 -18
- package/dist/model-context/interactable-composer-metadata.js.map +1 -1
- package/dist/model-context/registry.d.ts.map +1 -1
- package/dist/model-context/registry.js +3 -5
- package/dist/model-context/registry.js.map +1 -1
- package/dist/model-context/types.d.ts.map +1 -1
- package/dist/model-context/types.js +5 -4
- package/dist/model-context/types.js.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js +45 -7
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/DataRenderers.d.ts.map +1 -1
- package/dist/react/client/DataRenderers.js +20 -15
- package/dist/react/client/DataRenderers.js.map +1 -1
- package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
- package/dist/react/client/InMemoryThreadList.js +62 -56
- package/dist/react/client/InMemoryThreadList.js.map +1 -1
- package/dist/react/client/Interactables.d.ts.map +1 -1
- package/dist/react/client/Interactables.js +35 -32
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/RemoteThreadList.d.ts +1 -0
- package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
- package/dist/react/client/RemoteThreadList.js +154 -143
- package/dist/react/client/RemoteThreadList.js.map +1 -1
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +18 -16
- 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 +3 -2
- package/dist/react/client/interactable-model-context.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +2 -2
- package/dist/react/interactables-legacy/Interactables.js +242 -121
- package/dist/react/interactables-legacy/Interactables.js.map +1 -1
- package/dist/react/interactables-legacy/useAssistantInteractable.d.ts.map +1 -1
- package/dist/react/interactables-legacy/useAssistantInteractable.js +3 -0
- package/dist/react/interactables-legacy/useAssistantInteractable.js.map +1 -1
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -1
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +11 -9
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -1
- package/dist/react/model-context/makeAssistantTool.d.ts +2 -2
- package/dist/react/model-context/makeAssistantTool.js +1 -1
- package/dist/react/model-context/makeAssistantTool.js.map +1 -1
- package/dist/react/model-context/useAssistantTool.d.ts +2 -2
- package/dist/react/model-context/useAssistantTool.js +1 -1
- package/dist/react/model-context/useAssistantTool.js.map +1 -1
- package/dist/react/model-context/useInteractable.d.ts.map +1 -1
- package/dist/react/model-context/useInteractable.js +4 -1
- package/dist/react/model-context/useInteractable.js.map +1 -1
- package/dist/react/model-context/useInteractableVersions.js +1 -1
- package/dist/react/model-context/useToolArgsStatus.d.ts.map +1 -1
- package/dist/react/model-context/useToolArgsStatus.js +2 -1
- package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.d.ts +11 -2
- package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.js +3 -2
- package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
- package/dist/react/primitives/part/PartMessages.d.ts +1 -0
- package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
- package/dist/react/primitives/part/PartMessages.js +1 -0
- package/dist/react/primitives/part/PartMessages.js.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.js +6 -5
- package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +16 -8
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +5 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +105 -104
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.d.ts +1 -0
- package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.js +13 -11
- package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +5 -24
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +354 -226
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +1 -0
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +22 -2
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +40 -15
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js +62 -15
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts +2 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +6 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/sdkIdentity.d.ts +6 -0
- package/dist/react/runtimes/cloud/sdkIdentity.d.ts.map +1 -0
- package/dist/react/runtimes/cloud/sdkIdentity.js +9 -0
- package/dist/react/runtimes/cloud/sdkIdentity.js.map +1 -0
- package/dist/react/runtimes/external-message-converter.d.ts +12 -2
- package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
- package/dist/react/runtimes/external-message-converter.js +26 -61
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreRuntime.js +75 -46
- package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.js +64 -24
- package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
- package/dist/react/utils/groupParts.d.ts +6 -1
- package/dist/react/utils/groupParts.d.ts.map +1 -1
- package/dist/react/utils/groupParts.js +6 -0
- package/dist/react/utils/groupParts.js.map +1 -1
- package/dist/react/utils/useJSONEqual.d.ts +3 -1
- package/dist/react/utils/useJSONEqual.d.ts.map +1 -1
- package/dist/react/utils/useJSONEqual.js +6 -1
- package/dist/react/utils/useJSONEqual.js.map +1 -1
- package/dist/react/utils/useJSONSchemaDependency.d.ts +7 -0
- package/dist/react/utils/useJSONSchemaDependency.d.ts.map +1 -0
- package/dist/react/utils/useJSONSchemaDependency.js +20 -0
- package/dist/react/utils/useJSONSchemaDependency.js.map +1 -0
- package/dist/runtime/api/thread-list-item-runtime.d.ts +7 -3
- package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.js +2 -2
- package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts +3 -0
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +18 -14
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +4 -0
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +3 -6
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -0
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +62 -22
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -0
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +161 -69
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/composer-runtime-core.d.ts +12 -5
- package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +4 -1
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.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/queue/message-queue.d.ts +5 -0
- package/dist/runtime/queue/message-queue.d.ts.map +1 -1
- package/dist/runtime/queue/message-queue.js +61 -6
- package/dist/runtime/queue/message-queue.js.map +1 -1
- package/dist/runtime/utils/auto-status.d.ts +6 -2
- package/dist/runtime/utils/auto-status.d.ts.map +1 -1
- package/dist/runtime/utils/auto-status.js +12 -4
- package/dist/runtime/utils/auto-status.js.map +1 -1
- package/dist/runtime/utils/external-message-conversion.d.ts +16 -4
- package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -1
- package/dist/runtime/utils/external-message-conversion.js +49 -13
- package/dist/runtime/utils/external-message-conversion.js.map +1 -1
- package/dist/runtime/utils/message-repository.d.ts +1 -0
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +18 -9
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/thread-message-like.d.ts +2 -1
- package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
- package/dist/runtime/utils/thread-message-like.js +5 -3
- package/dist/runtime/utils/thread-message-like.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 +21 -27
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +8 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/internal.d.ts +3 -3
- package/dist/runtimes/internal.js +2 -2
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +4 -1
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +18 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.js +130 -42
- package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
- package/dist/runtimes/remote-thread-list/title-generation.d.ts +49 -0
- package/dist/runtimes/remote-thread-list/title-generation.d.ts.map +1 -0
- package/dist/runtimes/remote-thread-list/title-generation.js +197 -0
- package/dist/runtimes/remote-thread-list/title-generation.js.map +1 -0
- package/dist/runtimes/remote-thread-list/title.d.ts +3 -1
- package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/title.js +9 -1
- package/dist/runtimes/remote-thread-list/title.js.map +1 -1
- package/dist/runtimes/remote-thread-list/types.d.ts +10 -0
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +2 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/external-thread.d.ts.map +1 -1
- package/dist/store/clients/external-thread.js +260 -203
- package/dist/store/clients/external-thread.js.map +1 -1
- package/dist/store/clients/model-context-client.d.ts.map +1 -1
- package/dist/store/clients/model-context-client.js +2 -1
- package/dist/store/clients/model-context-client.js.map +1 -1
- package/dist/store/clients/single-thread-list.d.ts.map +1 -1
- package/dist/store/clients/single-thread-list.js +1 -0
- package/dist/store/clients/single-thread-list.js.map +1 -1
- package/dist/store/clients/suggestions.d.ts.map +1 -1
- package/dist/store/clients/suggestions.js +5 -4
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/clients/thread-tasks.d.ts +13 -0
- package/dist/store/clients/thread-tasks.d.ts.map +1 -0
- package/dist/store/clients/thread-tasks.js +69 -0
- package/dist/store/clients/thread-tasks.js.map +1 -0
- package/dist/store/index.d.ts +3 -2
- package/dist/store/index.js +3 -3
- package/dist/store/primitive-predicates.d.ts.map +1 -1
- package/dist/store/primitive-predicates.js +4 -4
- package/dist/store/primitive-predicates.js.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.d.ts +1 -0
- package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js +97 -61
- package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.d.ts +1 -0
- package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.js +221 -144
- package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -1
- 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 +54 -52
- 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 +246 -126
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scope-registration.d.ts +2 -0
- package/dist/store/scope-registration.d.ts.map +1 -1
- package/dist/store/scopes/composer.d.ts +10 -2
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/message.d.ts +30 -1
- package/dist/store/scopes/message.d.ts.map +1 -1
- package/dist/store/scopes/task.d.ts +36 -0
- package/dist/store/scopes/task.d.ts.map +1 -0
- package/dist/store/scopes/task.js +0 -0
- package/dist/store/scopes/thread-list-item.d.ts +2 -2
- package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
- package/dist/store/scopes/thread.d.ts +28 -0
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/dist/store/scopes/threads.d.ts +1 -0
- 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 -15
- package/dist/subscribable/subscribable.js.map +1 -1
- package/dist/types/attachment.d.ts +2 -1
- package/dist/types/attachment.d.ts.map +1 -1
- package/dist/types/attachment.js +2 -1
- package/dist/types/attachment.js.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/message.d.ts +8 -1
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js.map +1 -1
- package/dist/utils/abortable-iterable.d.ts +19 -0
- package/dist/utils/abortable-iterable.d.ts.map +1 -0
- package/dist/utils/abortable-iterable.js +88 -0
- package/dist/utils/abortable-iterable.js.map +1 -0
- package/dist/utils/composite-context-provider.d.ts.map +1 -1
- package/dist/utils/composite-context-provider.js +20 -2
- package/dist/utils/composite-context-provider.js.map +1 -1
- package/dist/utils/getGroupStatus.d.ts +18 -2
- package/dist/utils/getGroupStatus.d.ts.map +1 -1
- package/dist/utils/getGroupStatus.js +32 -7
- package/dist/utils/getGroupStatus.js.map +1 -1
- package/dist/utils/record.d.ts +11 -0
- package/dist/utils/record.d.ts.map +1 -0
- package/dist/utils/record.js +12 -0
- package/dist/utils/record.js.map +1 -0
- package/dist/utils/wire-media.d.ts.map +1 -1
- package/dist/utils/wire-media.js +2 -2
- package/dist/utils/wire-media.js.map +1 -1
- package/package.json +11 -11
- package/src/adapters/attachment.test.ts +50 -1
- package/src/adapters/attachment.ts +7 -4
- package/src/adapters/speech.test.ts +236 -0
- package/src/adapters/speech.ts +17 -10
- package/src/adapters/thread-history.ts +3 -0
- package/src/index.ts +2 -0
- package/src/internal.ts +4 -0
- package/src/model-context/frame/host.test.ts +137 -1
- package/src/model-context/frame/host.ts +49 -16
- package/src/model-context/frame/provider.test.ts +71 -0
- package/src/model-context/frame/provider.ts +37 -7
- package/src/model-context/interactable-composer-metadata.test.ts +58 -0
- package/src/model-context/interactable-composer-metadata.ts +19 -13
- package/src/model-context/registry.test.ts +12 -0
- package/src/model-context/registry.ts +3 -2
- package/src/model-context/types.test.ts +25 -0
- package/src/model-context/types.ts +9 -4
- package/src/react/RuntimeAdapter.test.ts +34 -0
- package/src/react/adapters/LocalStorageThreadListAdapter.test.ts +244 -0
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +104 -7
- package/src/react/client/DataRenderers.test.tsx +45 -0
- package/src/react/client/DataRenderers.ts +13 -9
- package/src/react/client/InMemoryThreadList.ts +1 -0
- package/src/react/client/Interactables.test.ts +72 -1
- package/src/react/client/Interactables.ts +22 -14
- package/src/react/client/RemoteThreadList.background.test.ts +148 -6
- package/src/react/client/RemoteThreadList.concurrent.test.tsx +42 -1
- package/src/react/client/RemoteThreadList.test.ts +386 -4
- package/src/react/client/RemoteThreadList.ts +181 -112
- package/src/react/client/Tools.ts +22 -11
- package/src/react/client/interactable-model-context.test.ts +44 -0
- package/src/react/client/interactable-model-context.ts +3 -2
- package/src/react/index.ts +5 -1
- package/src/react/interactables-legacy/Interactables.ts +16 -16
- package/src/react/interactables-legacy/useAssistantInteractable.test.tsx +132 -0
- package/src/react/interactables-legacy/useAssistantInteractable.ts +10 -1
- package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +9 -10
- package/src/react/model-context/makeAssistantTool.ts +2 -2
- package/src/react/model-context/useAssistantTool.ts +2 -2
- package/src/react/model-context/useInteractable.test.tsx +177 -0
- package/src/react/model-context/useInteractable.ts +3 -0
- package/src/react/model-context/useToolArgsStatus.test.tsx +30 -0
- package/src/react/model-context/useToolArgsStatus.ts +2 -1
- package/src/react/primitive-hooks/useActionBarCopy.test.ts +0 -1
- package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +0 -1
- package/src/react/primitives/message/MessageGroupedParts.test.tsx +96 -0
- package/src/react/primitives/message/MessageGroupedParts.tsx +15 -4
- package/src/react/primitives/part/PartMessages.test.tsx +104 -1
- package/src/react/primitives/part/PartMessages.tsx +1 -0
- package/src/react/primitives/thread/ThreadMessages.test.tsx +142 -0
- package/src/react/primitives/thread/ThreadMessages.tsx +8 -5
- package/src/react/providers/ReadonlyThreadProvider.test.tsx +56 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.destroy.test.tsx +172 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +33 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +7 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +28 -5
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.load-error.test.ts +132 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +105 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +143 -112
- package/src/react/runtimes/RemoteThreadResource.test.ts +9 -0
- package/src/react/runtimes/RemoteThreadResource.ts +19 -12
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +20 -14
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +703 -6
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +492 -402
- package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.test.ts +77 -0
- package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +27 -1
- package/src/react/runtimes/cloud/auiV0.ts +160 -25
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +36 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +8 -1
- package/src/react/runtimes/cloud/sdkIdentity.ts +9 -0
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +18 -4
- package/src/react/runtimes/external-message-converter.test.ts +136 -1
- package/src/react/runtimes/external-message-converter.ts +39 -93
- package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +41 -0
- package/src/react/runtimes/useExternalStoreRuntime.ts +10 -4
- package/src/react/runtimes/useLocalRuntime.test.tsx +20 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.load-error.test.tsx +108 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.ts +34 -1
- package/src/react/utils/groupParts.ts +12 -1
- package/src/react/utils/useJSONEqual.ts +9 -0
- package/src/react/utils/useJSONSchemaDependency.ts +22 -0
- package/src/runtime/api/message-runtime.test.ts +75 -0
- package/src/runtime/api/thread-list-item-runtime.ts +10 -3
- package/src/runtime/api/thread-list-runtime.ts +21 -11
- package/src/runtime/api/thread-runtime.test.ts +136 -0
- package/src/runtime/api/thread-runtime.ts +10 -5
- package/src/runtime/base/base-composer-runtime-core.ts +105 -24
- package/src/runtime/base/base-thread-runtime-core.test.ts +1063 -2
- package/src/runtime/base/base-thread-runtime-core.ts +228 -87
- package/src/runtime/interfaces/composer-runtime-core.ts +10 -5
- package/src/runtime/interfaces/thread-list-runtime-core.ts +5 -1
- package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
- package/src/runtime/queue/message-queue.ts +68 -6
- package/src/runtime/utils/auto-status.test.ts +112 -1
- package/src/runtime/utils/auto-status.ts +31 -5
- package/src/runtime/utils/external-message-conversion.test.ts +202 -0
- package/src/runtime/utils/external-message-conversion.ts +123 -32
- package/src/runtime/utils/message-repository.test.ts +49 -0
- package/src/runtime/utils/message-repository.ts +32 -20
- package/src/runtime/utils/thread-message-like.test.ts +52 -0
- package/src/runtime/utils/thread-message-like.ts +5 -1
- package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +18 -13
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +31 -1
- package/src/runtimes/internal.ts +1 -0
- package/src/runtimes/local/local-thread-runtime-core.test.ts +21 -0
- package/src/runtimes/local/local-thread-runtime-core.ts +11 -1
- package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +128 -2
- package/src/runtimes/remote-thread-list/remote-thread-state.ts +182 -42
- package/src/runtimes/remote-thread-list/title-generation.test.ts +602 -0
- package/src/runtimes/remote-thread-list/title-generation.ts +329 -0
- package/src/runtimes/remote-thread-list/title.test.ts +62 -0
- package/src/runtimes/remote-thread-list/title.ts +13 -0
- package/src/runtimes/remote-thread-list/types.ts +10 -0
- package/src/runtimes/tool-invocations/EDGE_CASES.md +2 -6
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +133 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +10 -6
- package/src/store/clients/external-thread.ts +67 -4
- package/src/store/clients/model-context-client.ts +5 -1
- package/src/store/clients/single-thread-list.ts +1 -0
- package/src/store/clients/suggestions.test.ts +40 -0
- package/src/store/clients/suggestions.ts +13 -10
- package/src/store/clients/thread-tasks.test.ts +274 -0
- package/src/store/clients/thread-tasks.ts +138 -0
- package/src/store/index.ts +8 -0
- package/src/store/primitive-predicates.test.ts +48 -5
- package/src/store/primitive-predicates.ts +7 -2
- package/src/store/runtime-clients/composer-runtime-client.ts +42 -9
- package/src/store/runtime-clients/message-runtime-client.ts +54 -6
- package/src/store/runtime-clients/thread-list-item-runtime-client.ts +4 -2
- package/src/store/runtime-clients/thread-list-runtime-client.ts +1 -0
- package/src/store/runtime-clients/thread-runtime-client.ts +89 -11
- package/src/store/scope-registration.ts +2 -0
- package/src/store/scopes/composer.ts +16 -4
- package/src/store/scopes/message.ts +14 -0
- package/src/store/scopes/task.ts +34 -0
- package/src/store/scopes/thread-list-item.ts +5 -2
- package/src/store/scopes/thread.ts +20 -0
- package/src/store/scopes/threads.ts +1 -0
- package/src/store/thread-tasks.test.tsx +209 -0
- package/src/subscribable/subscribable.test.ts +156 -1
- package/src/subscribable/subscribable.ts +25 -15
- package/src/tests/MessageRepository.test.ts +117 -5
- package/src/tests/OptimisticState-list-race.test.ts +1 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-initialize-adapter-change.test.ts +38 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +47 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +89 -0
- package/src/tests/attachment-adapters.test.ts +14 -0
- package/src/tests/auiV0Encode.test.ts +300 -0
- package/src/tests/base-composer-runtime-core-send.test.ts +51 -0
- package/src/tests/base-composer-runtime-core.test.ts +353 -2
- package/src/tests/external-store-thread-list-runtime-core.test.ts +83 -0
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +178 -18
- package/src/tests/external-thread-attachments.test.tsx +208 -0
- package/src/tests/external-thread-parity.test.tsx +57 -0
- package/src/tests/groupParts.test.ts +71 -0
- package/src/tests/message-queue.test.ts +253 -0
- package/src/tests/remote-thread-list-isLoading.test.ts +1 -0
- package/src/tests/remote-thread-list-reactive-threadId.test.ts +51 -0
- package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
- package/src/tests/thread-switch-events.test.tsx +78 -0
- package/src/tests/tools-scope-migration.test.tsx +28 -0
- package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +43 -0
- package/src/types/attachment.ts +4 -0
- package/src/types/index.ts +1 -0
- package/src/types/message.ts +8 -0
- package/src/utils/abortable-iterable.test.ts +328 -0
- package/src/utils/abortable-iterable.ts +104 -0
- package/src/utils/composite-context-provider.test.ts +25 -0
- package/src/utils/composite-context-provider.ts +23 -2
- package/src/utils/getGroupStatus.test.ts +70 -4
- package/src/utils/getGroupStatus.ts +35 -12
- package/src/utils/record.test.ts +48 -0
- package/src/utils/record.ts +11 -0
- package/src/utils/wire-media.test.ts +10 -0
- package/src/utils/wire-media.ts +6 -2
|
@@ -7,6 +7,62 @@ afterEach(() => {
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
describe("WebSpeechSynthesisAdapter", () => {
|
|
10
|
+
const stubSpeechSynthesis = () => {
|
|
11
|
+
const utterances: EventTarget[] = [];
|
|
12
|
+
class MockSpeechSynthesisUtterance extends EventTarget {
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
|
+
utterances.push(this);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const cancel = vi.fn();
|
|
19
|
+
vi.stubGlobal("SpeechSynthesisUtterance", MockSpeechSynthesisUtterance);
|
|
20
|
+
vi.stubGlobal("window", { speechSynthesis: { speak: vi.fn(), cancel } });
|
|
21
|
+
return { utterances, cancel };
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
it.each(["end", "error"])(
|
|
25
|
+
"does not cancel newer playback through a handle that received %s",
|
|
26
|
+
(event) => {
|
|
27
|
+
const { utterances, cancel } = stubSpeechSynthesis();
|
|
28
|
+
const adapter = new WebSpeechSynthesisAdapter();
|
|
29
|
+
const old = adapter.speak("old");
|
|
30
|
+
utterances[0]!.dispatchEvent(new Event(event));
|
|
31
|
+
const endedStatus = old.status;
|
|
32
|
+
const current = adapter.speak("current");
|
|
33
|
+
|
|
34
|
+
old.cancel();
|
|
35
|
+
old.cancel();
|
|
36
|
+
|
|
37
|
+
expect(cancel).not.toHaveBeenCalled();
|
|
38
|
+
expect(old.status).toBe(endedStatus);
|
|
39
|
+
expect(current.status).toEqual({ type: "running" });
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
it("cancels active playback once and leaves later playback alone", () => {
|
|
44
|
+
const { cancel } = stubSpeechSynthesis();
|
|
45
|
+
const adapter = new WebSpeechSynthesisAdapter();
|
|
46
|
+
const old = adapter.speak("old");
|
|
47
|
+
const onChange = vi.fn();
|
|
48
|
+
old.subscribe(onChange);
|
|
49
|
+
|
|
50
|
+
old.cancel();
|
|
51
|
+
|
|
52
|
+
expect(cancel).toHaveBeenCalledOnce();
|
|
53
|
+
expect(old.status).toMatchObject({ type: "ended", reason: "cancelled" });
|
|
54
|
+
expect(onChange).toHaveBeenCalledOnce();
|
|
55
|
+
|
|
56
|
+
const current = adapter.speak("current");
|
|
57
|
+
old.cancel();
|
|
58
|
+
|
|
59
|
+
expect(cancel).toHaveBeenCalledOnce();
|
|
60
|
+
expect(onChange).toHaveBeenCalledOnce();
|
|
61
|
+
expect(current.status).toEqual({ type: "running" });
|
|
62
|
+
current.cancel();
|
|
63
|
+
expect(cancel).toHaveBeenCalledTimes(2);
|
|
64
|
+
});
|
|
65
|
+
|
|
10
66
|
it("isolates a late subscriber that throws after the utterance ended", async () => {
|
|
11
67
|
const listeners = new Map<string, EventListener>();
|
|
12
68
|
class MockSpeechSynthesisUtterance {
|
|
@@ -109,6 +165,186 @@ describe("WebSpeechDictationAdapter", () => {
|
|
|
109
165
|
return listeners;
|
|
110
166
|
};
|
|
111
167
|
|
|
168
|
+
const emitResults = (
|
|
169
|
+
listeners: Map<string, EventListener>,
|
|
170
|
+
results: [transcript: string, isFinal: boolean][],
|
|
171
|
+
resultIndex = 0,
|
|
172
|
+
) => {
|
|
173
|
+
listeners.get("result")!({
|
|
174
|
+
resultIndex,
|
|
175
|
+
results: results.map(([transcript, isFinal]) => ({
|
|
176
|
+
0: { transcript },
|
|
177
|
+
isFinal,
|
|
178
|
+
})),
|
|
179
|
+
} as unknown as Event);
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
it("publishes the entire interim suffix when only its last result changes", () => {
|
|
183
|
+
const listeners = stubSpeechRecognition();
|
|
184
|
+
const session = new WebSpeechDictationAdapter().listen();
|
|
185
|
+
const onSpeech = vi.fn();
|
|
186
|
+
session.onSpeech(onSpeech);
|
|
187
|
+
|
|
188
|
+
emitResults(listeners, [
|
|
189
|
+
["hello ", false],
|
|
190
|
+
["world", false],
|
|
191
|
+
]);
|
|
192
|
+
emitResults(
|
|
193
|
+
listeners,
|
|
194
|
+
[
|
|
195
|
+
["hello ", false],
|
|
196
|
+
["there", false],
|
|
197
|
+
],
|
|
198
|
+
1,
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
expect(onSpeech.mock.calls).toEqual([
|
|
202
|
+
[{ transcript: "hello world", isFinal: false }],
|
|
203
|
+
[{ transcript: "hello there", isFinal: false }],
|
|
204
|
+
]);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("publishes partial and complete retractions with no changed results", () => {
|
|
208
|
+
const listeners = stubSpeechRecognition();
|
|
209
|
+
const session = new WebSpeechDictationAdapter().listen();
|
|
210
|
+
const onSpeech = vi.fn();
|
|
211
|
+
session.onSpeech(onSpeech);
|
|
212
|
+
|
|
213
|
+
emitResults(listeners, [
|
|
214
|
+
["hello ", false],
|
|
215
|
+
["world", false],
|
|
216
|
+
]);
|
|
217
|
+
emitResults(listeners, [["hello ", false]], 1);
|
|
218
|
+
emitResults(listeners, []);
|
|
219
|
+
emitResults(listeners, []);
|
|
220
|
+
|
|
221
|
+
expect(onSpeech.mock.calls).toEqual([
|
|
222
|
+
[{ transcript: "hello world", isFinal: false }],
|
|
223
|
+
[{ transcript: "hello ", isFinal: false }],
|
|
224
|
+
[{ transcript: "", isFinal: false }],
|
|
225
|
+
]);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it("delivers changed final results once before the remaining interim suffix", () => {
|
|
229
|
+
const listeners = stubSpeechRecognition();
|
|
230
|
+
const session = new WebSpeechDictationAdapter().listen();
|
|
231
|
+
const onSpeech = vi.fn();
|
|
232
|
+
const onEnd = vi.fn();
|
|
233
|
+
session.onSpeech(onSpeech);
|
|
234
|
+
session.onSpeechEnd(onEnd);
|
|
235
|
+
|
|
236
|
+
emitResults(listeners, [
|
|
237
|
+
["hello ", true],
|
|
238
|
+
["wor", false],
|
|
239
|
+
["ld", false],
|
|
240
|
+
]);
|
|
241
|
+
emitResults(
|
|
242
|
+
listeners,
|
|
243
|
+
[
|
|
244
|
+
["hello ", true],
|
|
245
|
+
["world", true],
|
|
246
|
+
],
|
|
247
|
+
1,
|
|
248
|
+
);
|
|
249
|
+
listeners.get("end")!(new Event("end"));
|
|
250
|
+
|
|
251
|
+
expect(onSpeech.mock.calls).toEqual([
|
|
252
|
+
[{ transcript: "hello ", isFinal: true }],
|
|
253
|
+
[{ transcript: "world", isFinal: false }],
|
|
254
|
+
[{ transcript: "world", isFinal: true }],
|
|
255
|
+
]);
|
|
256
|
+
expect(onEnd).toHaveBeenCalledExactlyOnceWith({
|
|
257
|
+
transcript: "hello world",
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it("clears an interim suffix while retaining earlier final results", () => {
|
|
262
|
+
const listeners = stubSpeechRecognition();
|
|
263
|
+
const session = new WebSpeechDictationAdapter().listen();
|
|
264
|
+
const onSpeech = vi.fn();
|
|
265
|
+
session.onSpeech(onSpeech);
|
|
266
|
+
|
|
267
|
+
emitResults(listeners, [
|
|
268
|
+
["hello ", true],
|
|
269
|
+
["world", false],
|
|
270
|
+
]);
|
|
271
|
+
emitResults(listeners, [["hello ", true]], 1);
|
|
272
|
+
|
|
273
|
+
expect(onSpeech.mock.calls).toEqual([
|
|
274
|
+
[{ transcript: "hello ", isFinal: true }],
|
|
275
|
+
[{ transcript: "world", isFinal: false }],
|
|
276
|
+
[{ transcript: "", isFinal: false }],
|
|
277
|
+
]);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it("keeps final-only delivery free of empty interim updates", () => {
|
|
281
|
+
const listeners = stubSpeechRecognition();
|
|
282
|
+
const session = new WebSpeechDictationAdapter().listen();
|
|
283
|
+
const onSpeech = vi.fn();
|
|
284
|
+
session.onSpeech(onSpeech);
|
|
285
|
+
|
|
286
|
+
emitResults(listeners, [["hello", true]]);
|
|
287
|
+
emitResults(listeners, [["hello", true]], 1);
|
|
288
|
+
|
|
289
|
+
expect(onSpeech).toHaveBeenCalledExactlyOnceWith({
|
|
290
|
+
transcript: "hello",
|
|
291
|
+
isFinal: true,
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it("does not drop an unconsumed final when resultIndex skips it", () => {
|
|
296
|
+
const listeners = stubSpeechRecognition();
|
|
297
|
+
const session = new WebSpeechDictationAdapter().listen();
|
|
298
|
+
const onSpeech = vi.fn();
|
|
299
|
+
const onEnd = vi.fn();
|
|
300
|
+
session.onSpeech(onSpeech);
|
|
301
|
+
session.onSpeechEnd(onEnd);
|
|
302
|
+
|
|
303
|
+
emitResults(listeners, [["hello ", false]]);
|
|
304
|
+
emitResults(
|
|
305
|
+
listeners,
|
|
306
|
+
[
|
|
307
|
+
["hello ", true],
|
|
308
|
+
["world", false],
|
|
309
|
+
],
|
|
310
|
+
1,
|
|
311
|
+
);
|
|
312
|
+
listeners.get("end")!(new Event("end"));
|
|
313
|
+
|
|
314
|
+
expect(onSpeech.mock.calls).toEqual([
|
|
315
|
+
[{ transcript: "hello ", isFinal: false }],
|
|
316
|
+
[{ transcript: "hello ", isFinal: true }],
|
|
317
|
+
[{ transcript: "world", isFinal: false }],
|
|
318
|
+
]);
|
|
319
|
+
expect(onEnd).toHaveBeenCalledExactlyOnceWith({ transcript: "hello " });
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it("does not reread historical finalized results during interim updates", () => {
|
|
323
|
+
const listeners = stubSpeechRecognition();
|
|
324
|
+
new WebSpeechDictationAdapter().listen();
|
|
325
|
+
const readFinal = vi.fn(() => ({ transcript: "word " }));
|
|
326
|
+
const finals = Array.from({ length: 1_000 }, () => ({
|
|
327
|
+
get 0() {
|
|
328
|
+
return readFinal();
|
|
329
|
+
},
|
|
330
|
+
isFinal: true,
|
|
331
|
+
}));
|
|
332
|
+
listeners.get("result")!({
|
|
333
|
+
resultIndex: 0,
|
|
334
|
+
results: finals,
|
|
335
|
+
} as unknown as Event);
|
|
336
|
+
expect(readFinal).toHaveBeenCalledTimes(1_000);
|
|
337
|
+
|
|
338
|
+
for (const transcript of ["hel", "hello", "hello world"]) {
|
|
339
|
+
listeners.get("result")!({
|
|
340
|
+
resultIndex: finals.length,
|
|
341
|
+
results: [...finals, { 0: { transcript }, isFinal: false }],
|
|
342
|
+
} as unknown as Event);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
expect(readFinal).toHaveBeenCalledTimes(1_000);
|
|
346
|
+
});
|
|
347
|
+
|
|
112
348
|
it("continues notifying dictation listeners when one throws", () => {
|
|
113
349
|
const listeners = stubSpeechRecognition();
|
|
114
350
|
const listenerError = new Error("listener failed");
|
package/src/adapters/speech.ts
CHANGED
|
@@ -76,6 +76,7 @@ export class WebSpeechSynthesisAdapter implements SpeechSynthesisAdapter {
|
|
|
76
76
|
const res: SpeechSynthesisAdapter.Utterance = {
|
|
77
77
|
status: { type: "running" },
|
|
78
78
|
cancel: () => {
|
|
79
|
+
if (res.status.type === "ended") return;
|
|
79
80
|
window.speechSynthesis.cancel();
|
|
80
81
|
handleEnd("cancelled");
|
|
81
82
|
},
|
|
@@ -205,6 +206,8 @@ export class WebSpeechDictationAdapter implements DictationAdapter {
|
|
|
205
206
|
>();
|
|
206
207
|
|
|
207
208
|
let finalTranscript = "";
|
|
209
|
+
let hasInterimTranscript = false;
|
|
210
|
+
let firstInterimIndex = 0;
|
|
208
211
|
|
|
209
212
|
const session: DictationAdapter.Session = {
|
|
210
213
|
status: { type: "starting" },
|
|
@@ -267,32 +270,36 @@ export class WebSpeechDictationAdapter implements DictationAdapter {
|
|
|
267
270
|
|
|
268
271
|
recognition.addEventListener("result", (event) => {
|
|
269
272
|
const speechEvent = event as unknown as SpeechRecognitionEvent;
|
|
273
|
+
let interimTranscript = "";
|
|
270
274
|
|
|
271
|
-
for (
|
|
272
|
-
let i = speechEvent.resultIndex;
|
|
273
|
-
i < speechEvent.results.length;
|
|
274
|
-
i++
|
|
275
|
-
) {
|
|
275
|
+
for (let i = firstInterimIndex; i < speechEvent.results.length; i++) {
|
|
276
276
|
const result = speechEvent.results[i];
|
|
277
277
|
if (!result) continue;
|
|
278
278
|
|
|
279
279
|
const transcript = result[0]?.transcript ?? "";
|
|
280
280
|
|
|
281
281
|
if (result.isFinal) {
|
|
282
|
+
firstInterimIndex = i + 1;
|
|
282
283
|
finalTranscript += transcript;
|
|
284
|
+
hasInterimTranscript = false;
|
|
283
285
|
notifyEventListeners(
|
|
284
286
|
speechCallbacks,
|
|
285
287
|
() => ({ transcript, isFinal: true }),
|
|
286
288
|
"Dictation",
|
|
287
289
|
);
|
|
288
290
|
} else {
|
|
289
|
-
|
|
290
|
-
speechCallbacks,
|
|
291
|
-
() => ({ transcript, isFinal: false }),
|
|
292
|
-
"Dictation",
|
|
293
|
-
);
|
|
291
|
+
interimTranscript += transcript;
|
|
294
292
|
}
|
|
295
293
|
}
|
|
294
|
+
|
|
295
|
+
if (interimTranscript || hasInterimTranscript) {
|
|
296
|
+
hasInterimTranscript = interimTranscript.length > 0;
|
|
297
|
+
notifyEventListeners(
|
|
298
|
+
speechCallbacks,
|
|
299
|
+
() => ({ transcript: interimTranscript, isFinal: false }),
|
|
300
|
+
"Dictation",
|
|
301
|
+
);
|
|
302
|
+
}
|
|
296
303
|
});
|
|
297
304
|
|
|
298
305
|
recognition.addEventListener("speechend", () => {
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
ExportedMessageRepositoryItem,
|
|
8
8
|
} from "../runtime/utils/message-repository";
|
|
9
9
|
import type { ReadonlyJSONValue } from "assistant-stream/utils";
|
|
10
|
+
import type { ThreadMessage } from "../types";
|
|
10
11
|
|
|
11
12
|
export interface MessageStorageEntry<TPayload> {
|
|
12
13
|
id: string;
|
|
@@ -52,6 +53,8 @@ export type GenericThreadHistoryAdapter<TMessage> = {
|
|
|
52
53
|
options?: {
|
|
53
54
|
durationMs?: number;
|
|
54
55
|
stepTimestamps?: { start_ms: number; end_ms: number }[];
|
|
56
|
+
/** The thread message the items were persisted from; its status and timing complete a report the stored format cannot carry. */
|
|
57
|
+
message?: ThreadMessage;
|
|
55
58
|
},
|
|
56
59
|
): void;
|
|
57
60
|
};
|
package/src/index.ts
CHANGED
|
@@ -40,6 +40,7 @@ export type {
|
|
|
40
40
|
MessageStatus,
|
|
41
41
|
// Thread messages
|
|
42
42
|
MessageTiming,
|
|
43
|
+
MessageModality,
|
|
43
44
|
ThreadStep,
|
|
44
45
|
ThreadSystemMessage,
|
|
45
46
|
ThreadUserMessage,
|
|
@@ -261,6 +262,7 @@ export type {
|
|
|
261
262
|
ThreadListItemEventCallback,
|
|
262
263
|
ThreadListItemEventPayload,
|
|
263
264
|
ThreadListItemEventType,
|
|
265
|
+
ThreadListItemGenerateTitleOptions,
|
|
264
266
|
ThreadListItemRuntime,
|
|
265
267
|
} from "./runtime/api/thread-list-item-runtime";
|
|
266
268
|
|
package/src/internal.ts
CHANGED
|
@@ -67,6 +67,10 @@ export {
|
|
|
67
67
|
resolveFilePartSource,
|
|
68
68
|
} from "./utils/data-url";
|
|
69
69
|
export { invokeUserCallback } from "./utils/invoke-user-callback";
|
|
70
|
+
export {
|
|
71
|
+
abortableIterable,
|
|
72
|
+
openAbortableIterable,
|
|
73
|
+
} from "./utils/abortable-iterable";
|
|
70
74
|
export { detectImageMediaType } from "./utils/image-media-type";
|
|
71
75
|
export {
|
|
72
76
|
resolveFileMediaType,
|
|
@@ -74,9 +74,31 @@ beforeEach(() => {
|
|
|
74
74
|
afterEach(() => {
|
|
75
75
|
vi.useRealTimers();
|
|
76
76
|
vi.unstubAllGlobals();
|
|
77
|
+
vi.restoreAllMocks();
|
|
77
78
|
});
|
|
78
79
|
|
|
79
80
|
describe("AssistantFrameHost", () => {
|
|
81
|
+
it("does not install its message listener when initialization fails", () => {
|
|
82
|
+
const addEventListener = vi.fn();
|
|
83
|
+
const removeEventListener = vi.fn();
|
|
84
|
+
vi.stubGlobal("window", {
|
|
85
|
+
addEventListener,
|
|
86
|
+
removeEventListener,
|
|
87
|
+
location: { origin: DEFAULT_ORIGIN },
|
|
88
|
+
});
|
|
89
|
+
const error = new Error("postMessage failed");
|
|
90
|
+
const iframeWindow = {
|
|
91
|
+
postMessage: vi.fn(() => {
|
|
92
|
+
throw error;
|
|
93
|
+
}),
|
|
94
|
+
} as unknown as Window;
|
|
95
|
+
|
|
96
|
+
expect(() => new AssistantFrameHost(iframeWindow)).toThrow(error);
|
|
97
|
+
|
|
98
|
+
expect(addEventListener).not.toHaveBeenCalled();
|
|
99
|
+
expect(removeEventListener).not.toHaveBeenCalled();
|
|
100
|
+
});
|
|
101
|
+
|
|
80
102
|
it("defaults to the current origin", () => {
|
|
81
103
|
const { host, postMessage } = createHost();
|
|
82
104
|
|
|
@@ -133,6 +155,30 @@ describe("AssistantFrameHost", () => {
|
|
|
133
155
|
host.dispose();
|
|
134
156
|
});
|
|
135
157
|
|
|
158
|
+
it("cleans up tool calls when posting the request fails", async () => {
|
|
159
|
+
const { execute, host, postMessage } = createHost();
|
|
160
|
+
const error = new Error("postMessage failed");
|
|
161
|
+
const abortController = new AbortController();
|
|
162
|
+
const removeEventListener = vi.spyOn(
|
|
163
|
+
abortController.signal,
|
|
164
|
+
"removeEventListener",
|
|
165
|
+
);
|
|
166
|
+
postMessage.mockImplementation((data) => {
|
|
167
|
+
if (data.message.type === "tool-call") throw error;
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
await expect(
|
|
171
|
+
execute({}, { ...executionContext, abortSignal: abortController.signal }),
|
|
172
|
+
).rejects.toBe(error);
|
|
173
|
+
|
|
174
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
175
|
+
expect(removeEventListener).toHaveBeenCalledWith(
|
|
176
|
+
"abort",
|
|
177
|
+
expect.any(Function),
|
|
178
|
+
);
|
|
179
|
+
host.dispose();
|
|
180
|
+
});
|
|
181
|
+
|
|
136
182
|
it("rejects tool results that carry an empty error message", async () => {
|
|
137
183
|
const { dispatchMessage, execute, getToolCallId, host } = createHost();
|
|
138
184
|
const result = Promise.resolve(
|
|
@@ -188,8 +234,83 @@ describe("AssistantFrameHost", () => {
|
|
|
188
234
|
expect(vi.getTimerCount()).toBe(0);
|
|
189
235
|
});
|
|
190
236
|
|
|
237
|
+
it("settles every pending tool call when cancellation posting fails", async () => {
|
|
238
|
+
const { execute, host, postMessage } = createHost();
|
|
239
|
+
const consoleError = vi
|
|
240
|
+
.spyOn(console, "error")
|
|
241
|
+
.mockImplementation(() => undefined);
|
|
242
|
+
const firstAbortController = new AbortController();
|
|
243
|
+
const secondAbortController = new AbortController();
|
|
244
|
+
const firstRemoveEventListener = vi.spyOn(
|
|
245
|
+
firstAbortController.signal,
|
|
246
|
+
"removeEventListener",
|
|
247
|
+
);
|
|
248
|
+
const secondRemoveEventListener = vi.spyOn(
|
|
249
|
+
secondAbortController.signal,
|
|
250
|
+
"removeEventListener",
|
|
251
|
+
);
|
|
252
|
+
const firstRejected = vi.fn();
|
|
253
|
+
const secondRejected = vi.fn();
|
|
254
|
+
|
|
255
|
+
void execute(
|
|
256
|
+
{},
|
|
257
|
+
{ ...executionContext, abortSignal: firstAbortController.signal },
|
|
258
|
+
).catch(firstRejected);
|
|
259
|
+
void execute(
|
|
260
|
+
{},
|
|
261
|
+
{ ...executionContext, abortSignal: secondAbortController.signal },
|
|
262
|
+
).catch(secondRejected);
|
|
263
|
+
|
|
264
|
+
const firstTransportError = new Error("first tool cancellation failed");
|
|
265
|
+
const secondTransportError = new Error("second tool cancellation failed");
|
|
266
|
+
let cancellationCount = 0;
|
|
267
|
+
postMessage.mockImplementation((data) => {
|
|
268
|
+
if (data.message.type !== "tool-cancel") return;
|
|
269
|
+
cancellationCount += 1;
|
|
270
|
+
throw cancellationCount === 1
|
|
271
|
+
? firstTransportError
|
|
272
|
+
: secondTransportError;
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
expect(() => host.dispose()).toThrow(firstTransportError);
|
|
276
|
+
await Promise.resolve();
|
|
277
|
+
|
|
278
|
+
expect(firstRejected).toHaveBeenCalledWith(
|
|
279
|
+
expect.objectContaining({
|
|
280
|
+
message: "AssistantFrameHost has been disposed",
|
|
281
|
+
}),
|
|
282
|
+
);
|
|
283
|
+
expect(secondRejected).toHaveBeenCalledWith(
|
|
284
|
+
expect.objectContaining({
|
|
285
|
+
message: "AssistantFrameHost has been disposed",
|
|
286
|
+
}),
|
|
287
|
+
);
|
|
288
|
+
expect(
|
|
289
|
+
postMessage.mock.calls.filter(
|
|
290
|
+
([data]) => data.message.type === "tool-cancel",
|
|
291
|
+
),
|
|
292
|
+
).toHaveLength(2);
|
|
293
|
+
expect(firstRemoveEventListener).toHaveBeenCalledWith(
|
|
294
|
+
"abort",
|
|
295
|
+
expect.any(Function),
|
|
296
|
+
);
|
|
297
|
+
expect(secondRemoveEventListener).toHaveBeenCalledWith(
|
|
298
|
+
"abort",
|
|
299
|
+
expect.any(Function),
|
|
300
|
+
);
|
|
301
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
302
|
+
expect(consoleError).toHaveBeenCalledWith(
|
|
303
|
+
"[assistant-ui] AssistantFrameHost tool cancellation could not be sent.",
|
|
304
|
+
secondTransportError,
|
|
305
|
+
);
|
|
306
|
+
expect(() => host.dispose()).not.toThrow();
|
|
307
|
+
});
|
|
308
|
+
|
|
191
309
|
it("rejects pending tool calls when execution is aborted", async () => {
|
|
192
310
|
const { execute, getToolCallId, host, postMessage } = createHost();
|
|
311
|
+
const consoleError = vi
|
|
312
|
+
.spyOn(console, "error")
|
|
313
|
+
.mockImplementation(() => undefined);
|
|
193
314
|
const abortController = new AbortController();
|
|
194
315
|
const abortError = new Error("Run cancelled");
|
|
195
316
|
abortError.name = "AbortError";
|
|
@@ -205,8 +326,13 @@ describe("AssistantFrameHost", () => {
|
|
|
205
326
|
const onRejected = vi.fn();
|
|
206
327
|
void result.catch(onRejected);
|
|
207
328
|
const toolCallId = getToolCallId();
|
|
329
|
+
postMessage.mockImplementation((data) => {
|
|
330
|
+
if (data.message.type === "tool-cancel") {
|
|
331
|
+
throw new Error("tool cancellation failed");
|
|
332
|
+
}
|
|
333
|
+
});
|
|
208
334
|
|
|
209
|
-
abortController.abort(abortError);
|
|
335
|
+
expect(() => abortController.abort(abortError)).not.toThrow();
|
|
210
336
|
await Promise.resolve();
|
|
211
337
|
|
|
212
338
|
expect(onRejected).toHaveBeenCalledWith(abortError);
|
|
@@ -217,17 +343,26 @@ describe("AssistantFrameHost", () => {
|
|
|
217
343
|
},
|
|
218
344
|
DEFAULT_ORIGIN,
|
|
219
345
|
);
|
|
346
|
+
expect(consoleError).toHaveBeenCalledOnce();
|
|
220
347
|
expect(vi.getTimerCount()).toBe(0);
|
|
221
348
|
host.dispose();
|
|
222
349
|
});
|
|
223
350
|
|
|
224
351
|
it("cancels tool calls when they time out", async () => {
|
|
225
352
|
const { execute, getToolCallId, host, postMessage } = createHost();
|
|
353
|
+
const consoleError = vi
|
|
354
|
+
.spyOn(console, "error")
|
|
355
|
+
.mockImplementation(() => undefined);
|
|
226
356
|
const result = Promise.resolve(execute({}, executionContext));
|
|
227
357
|
const toolCallId = getToolCallId();
|
|
228
358
|
const rejection = expect(result).rejects.toThrow(
|
|
229
359
|
'Tool call "search" timed out',
|
|
230
360
|
);
|
|
361
|
+
postMessage.mockImplementation((data) => {
|
|
362
|
+
if (data.message.type === "tool-cancel") {
|
|
363
|
+
throw new Error("tool cancellation failed");
|
|
364
|
+
}
|
|
365
|
+
});
|
|
231
366
|
|
|
232
367
|
await vi.advanceTimersByTimeAsync(30000);
|
|
233
368
|
|
|
@@ -239,6 +374,7 @@ describe("AssistantFrameHost", () => {
|
|
|
239
374
|
},
|
|
240
375
|
DEFAULT_ORIGIN,
|
|
241
376
|
);
|
|
377
|
+
expect(consoleError).toHaveBeenCalledOnce();
|
|
242
378
|
expect(vi.getTimerCount()).toBe(0);
|
|
243
379
|
host.dispose();
|
|
244
380
|
});
|
|
@@ -12,6 +12,13 @@ import {
|
|
|
12
12
|
|
|
13
13
|
const getDefaultTargetOrigin = () => window.location.origin;
|
|
14
14
|
|
|
15
|
+
const logCancellationFailure = (error: unknown) => {
|
|
16
|
+
console.error(
|
|
17
|
+
"[assistant-ui] AssistantFrameHost tool cancellation could not be sent.",
|
|
18
|
+
error,
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
15
22
|
/**
|
|
16
23
|
* Deserializes tools from JSON Schema format back to Tool objects
|
|
17
24
|
*/
|
|
@@ -73,9 +80,10 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
73
80
|
this._targetOrigin = targetOrigin;
|
|
74
81
|
|
|
75
82
|
this.handleMessage = this.handleMessage.bind(this);
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
// A posted message cannot be delivered before this constructor returns, so
|
|
84
|
+
// requesting first means a failed request leaves no listener to clean up.
|
|
78
85
|
this.requestContext();
|
|
86
|
+
window.addEventListener("message", this.handleMessage);
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
private handleMessage(event: MessageEvent) {
|
|
@@ -195,21 +203,34 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
195
203
|
}, timeout);
|
|
196
204
|
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
197
205
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
206
|
+
try {
|
|
207
|
+
this._iframeWindow.postMessage(
|
|
208
|
+
{ channel: FRAME_MESSAGE_CHANNEL, message },
|
|
209
|
+
this._targetOrigin,
|
|
210
|
+
);
|
|
211
|
+
} catch (error) {
|
|
212
|
+
const pending = this._pendingRequests.get(message.id);
|
|
213
|
+
this._pendingRequests.delete(message.id);
|
|
214
|
+
pending?.reject(error);
|
|
215
|
+
}
|
|
202
216
|
});
|
|
203
217
|
}
|
|
204
218
|
|
|
205
|
-
private cancelToolCall(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
219
|
+
private cancelToolCall(
|
|
220
|
+
id: string,
|
|
221
|
+
onError: (error: unknown) => void = logCancellationFailure,
|
|
222
|
+
) {
|
|
223
|
+
try {
|
|
224
|
+
this._iframeWindow.postMessage(
|
|
225
|
+
{
|
|
226
|
+
channel: FRAME_MESSAGE_CHANNEL,
|
|
227
|
+
message: { type: "tool-cancel", id } satisfies FrameMessage,
|
|
228
|
+
},
|
|
229
|
+
this._targetOrigin,
|
|
230
|
+
);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
onError(error);
|
|
233
|
+
}
|
|
213
234
|
}
|
|
214
235
|
|
|
215
236
|
private requestContext() {
|
|
@@ -242,10 +263,22 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
242
263
|
window.removeEventListener("message", this.handleMessage);
|
|
243
264
|
this._subscribers.clear();
|
|
244
265
|
const error = new Error("AssistantFrameHost has been disposed");
|
|
266
|
+
let cancellationFailed = false;
|
|
267
|
+
let cancellationError: unknown;
|
|
268
|
+
|
|
245
269
|
for (const [id, pending] of this._pendingRequests) {
|
|
246
|
-
this.
|
|
270
|
+
this._pendingRequests.delete(id);
|
|
271
|
+
this.cancelToolCall(id, (error) => {
|
|
272
|
+
if (!cancellationFailed) {
|
|
273
|
+
cancellationFailed = true;
|
|
274
|
+
cancellationError = error;
|
|
275
|
+
} else {
|
|
276
|
+
logCancellationFailure(error);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
247
279
|
pending.reject(error);
|
|
248
280
|
}
|
|
249
|
-
|
|
281
|
+
|
|
282
|
+
if (cancellationFailed) throw cancellationError;
|
|
250
283
|
}
|
|
251
284
|
}
|