@assistant-ui/core 0.3.16 → 0.3.18
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/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +4 -2
- package/dist/internal.js +4 -2
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +10 -4
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/frame/provider.d.ts +5 -0
- package/dist/model-context/frame/provider.d.ts.map +1 -1
- package/dist/model-context/frame/provider.js +101 -28
- 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 +16 -9
- 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/tool-call-text.d.ts +26 -0
- package/dist/model-context/tool-call-text.d.ts.map +1 -0
- package/dist/model-context/tool-call-text.js +18 -0
- package/dist/model-context/tool-call-text.js.map +1 -0
- 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/RuntimeAdapter.js +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/AdaptedRemoteThread.js +1 -1
- package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
- package/dist/react/client/InMemoryThreadList.js +63 -57
- 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 +25 -28
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/RemoteThreadList.d.ts +16 -0
- package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
- package/dist/react/client/RemoteThreadList.js +354 -242
- 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 +24 -18
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +2 -1
- package/dist/react/interactables-legacy/Interactables.js +246 -125
- package/dist/react/interactables-legacy/Interactables.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/toolbox.d.ts +2 -14
- package/dist/react/model-context/toolbox.d.ts.map +1 -1
- package/dist/react/model-context/toolbox.js +1 -13
- package/dist/react/model-context/toolbox.js.map +1 -1
- package/dist/react/model-context/useAssistantContext.js +37 -7
- package/dist/react/model-context/useAssistantContext.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/useAuiToolOverrides.js +31 -5
- package/dist/react/model-context/useAuiToolOverrides.js.map +1 -1
- package/dist/react/model-context/useInlineRender.d.ts.map +1 -1
- package/dist/react/model-context/useInlineRender.js +10 -36
- package/dist/react/model-context/useInlineRender.js.map +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/primitive-hooks/useMessageError.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useMessageError.js +2 -8
- package/dist/react/primitive-hooks/useMessageError.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.js +2 -4
- package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
- package/dist/react/primitives/composer/ComposerAttachments.d.ts.map +1 -1
- package/dist/react/primitives/composer/ComposerAttachments.js +4 -3
- package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
- package/dist/react/primitives/composer/ComposerQueue.d.ts.map +1 -1
- package/dist/react/primitives/composer/ComposerQueue.js +4 -3
- package/dist/react/primitives/composer/ComposerQueue.js.map +1 -1
- package/dist/react/primitives/message/MessageAttachments.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageAttachments.js +7 -6
- package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.js +2 -2
- package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
- package/dist/react/primitives/message/MessageParts.js +3 -3
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/primitives/threadList/ThreadListItems.d.ts.map +1 -1
- package/dist/react/primitives/threadList/ThreadListItems.js +5 -4
- package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +6 -4
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +59 -29
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +11 -6
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +160 -143
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.d.ts +2 -6
- package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.js +15 -13
- package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
- package/dist/react/runtimes/assistant-transport/useLatestRef.js +2 -2
- package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +4 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +424 -52
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +5 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts +29 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +160 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -0
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts +1 -9
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +16 -153
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/external-message-converter.js +1 -1
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/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 +77 -29
- package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
- package/dist/react/types/MessagePartComponentTypes.d.ts +7 -3
- package/dist/react/types/MessagePartComponentTypes.d.ts.map +1 -1
- package/dist/react/types/scopes/tools.d.ts +2 -0
- package/dist/react/types/scopes/tools.d.ts.map +1 -1
- package/dist/runtime/api/message-part-runtime.d.ts +2 -2
- package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-part-runtime.js +1 -1
- package/dist/runtime/api/message-part-runtime.js.map +1 -1
- 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 +12 -1
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +23 -14
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +5 -1
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +1 -1
- 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 +16 -12
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -2
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +8 -7
- 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 +18 -3
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +15 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/utils/auto-status.d.ts +1 -1
- package/dist/runtime/utils/auto-status.d.ts.map +1 -1
- package/dist/runtime/utils/auto-status.js +6 -2
- package/dist/runtime/utils/auto-status.js.map +1 -1
- package/dist/runtime/utils/external-message-conversion.d.ts +3 -2
- package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -1
- package/dist/runtime/utils/external-message-conversion.js +5 -4
- 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 +15 -6
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/resolveToolApprovalResponse.d.ts +6 -3
- package/dist/runtime/utils/resolveToolApprovalResponse.d.ts.map +1 -1
- package/dist/runtime/utils/resolveToolApprovalResponse.js +12 -3
- package/dist/runtime/utils/resolveToolApprovalResponse.js.map +1 -1
- package/dist/runtime/utils/thread-message-like.d.ts +2 -10
- package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
- package/dist/runtime/utils/thread-message-like.js +1 -1
- package/dist/runtime/utils/thread-message-like.js.map +1 -1
- package/dist/runtime/utils/tool-call-tree.d.ts +39 -0
- package/dist/runtime/utils/tool-call-tree.d.ts.map +1 -0
- package/dist/runtime/utils/tool-call-tree.js +85 -0
- package/dist/runtime/utils/tool-call-tree.js.map +1 -0
- package/dist/runtimes/external-store/external-store-adapter.d.ts +29 -2
- package/dist/runtimes/external-store/external-store-adapter.d.ts.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 +2 -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 +34 -28
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts +1 -1
- package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/inert/InertThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/internal.d.ts +2 -2
- 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 +3 -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 +148 -43
- 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 +11 -0
- package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -0
- package/dist/runtimes/remote-thread-list/title.js +14 -0
- package/dist/runtimes/remote-thread-list/title.js.map +1 -0
- package/dist/runtimes/remote-thread-list/types.d.ts +16 -5
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +31 -8
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +97 -60
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/external-thread.d.ts +1 -1
- package/dist/store/clients/external-thread.d.ts.map +1 -1
- package/dist/store/clients/external-thread.js +30 -7
- 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 +2 -1
- 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 +19 -6
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/clients/thread-message-client.js +1 -1
- package/dist/store/clients/thread-selection-events.js +1 -1
- package/dist/store/index.d.ts +2 -1
- package/dist/store/index.js +2 -1
- package/dist/store/internal.d.ts +2 -2
- package/dist/store/internal.js +2 -2
- package/dist/store/primitive-predicates.d.ts +4 -1
- package/dist/store/primitive-predicates.d.ts.map +1 -1
- package/dist/store/primitive-predicates.js +9 -1
- 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 +98 -62
- 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 +2 -2
- 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 +128 -107
- 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 +194 -122
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/useSubscribable.d.ts +3 -1
- package/dist/store/runtime-clients/useSubscribable.d.ts.map +1 -1
- package/dist/store/runtime-clients/useSubscribable.js +1 -1
- package/dist/store/runtime-clients/useSubscribable.js.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/part.d.ts +6 -3
- package/dist/store/scopes/part.d.ts.map +1 -1
- 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 +8 -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 +8 -1
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/subscribable/subscribable.js +24 -16
- 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/message.d.ts +40 -1
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js +7 -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 +72 -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/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/package.json +12 -17
- package/src/adapters/attachment.test.ts +50 -1
- package/src/adapters/attachment.ts +7 -4
- package/src/index.ts +7 -1
- package/src/internal.ts +12 -0
- package/src/model-context/frame/host.test.ts +24 -0
- package/src/model-context/frame/host.ts +10 -4
- package/src/model-context/frame/provider.test.ts +288 -1
- package/src/model-context/frame/provider.ts +148 -30
- package/src/model-context/interactable-composer-metadata.test.ts +28 -0
- package/src/model-context/interactable-composer-metadata.ts +9 -3
- package/src/model-context/registry.test.ts +12 -0
- package/src/model-context/registry.ts +3 -2
- package/src/model-context/tool-call-text.test.ts +67 -0
- package/src/model-context/tool-call-text.ts +67 -0
- package/src/model-context/types.test.ts +25 -0
- package/src/model-context/types.ts +9 -4
- package/src/react/AssistantRuntimeProvider.test.tsx +66 -2
- package/src/react/RuntimeAdapter.test.ts +34 -0
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +1 -3
- package/src/react/client/InMemoryThreadList.ts +1 -0
- package/src/react/client/Interactables.test.ts +28 -0
- package/src/react/client/Interactables.ts +15 -13
- package/src/react/client/RemoteThreadList.background.test.ts +526 -0
- package/src/react/client/RemoteThreadList.concurrent.test.tsx +315 -0
- package/src/react/client/RemoteThreadList.test.ts +617 -3
- package/src/react/client/RemoteThreadList.ts +433 -167
- package/src/react/client/Tools.ts +29 -12
- package/src/react/index.ts +4 -0
- package/src/react/interactables-legacy/Interactables.ts +16 -16
- package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +9 -10
- package/src/react/model-context/makeAssistantTool.ts +2 -2
- package/src/react/model-context/modelContextHooks.test.tsx +131 -0
- package/src/react/model-context/toolbox.test.ts +9 -9
- package/src/react/model-context/toolbox.ts +9 -36
- package/src/react/model-context/useAssistantContext.ts +4 -2
- package/src/react/model-context/useAssistantTool.ts +2 -2
- package/src/react/model-context/useAuiToolOverrides.ts +4 -2
- package/src/react/model-context/useInlineRender.test.tsx +48 -0
- package/src/react/model-context/useInlineRender.ts +14 -10
- package/src/react/model-context/useToolArgsStatus.test.tsx +30 -0
- package/src/react/model-context/useToolArgsStatus.ts +2 -1
- package/src/react/primitive-hooks/useMessageError.ts +2 -19
- package/src/react/primitive-hooks/useThreadListLoadMore.ts +2 -3
- package/src/react/primitives/composer/ComposerAttachments.test.tsx +76 -0
- package/src/react/primitives/composer/ComposerAttachments.tsx +9 -4
- package/src/react/primitives/composer/ComposerQueue.test.tsx +72 -0
- package/src/react/primitives/composer/ComposerQueue.tsx +7 -4
- package/src/react/primitives/message/MessageAttachments.test.tsx +107 -37
- package/src/react/primitives/message/MessageAttachments.tsx +10 -7
- package/src/react/primitives/message/MessageGroupedParts.tsx +2 -2
- package/src/react/primitives/message/MessageParts.tsx +3 -3
- package/src/react/primitives/threadList/ThreadListItems.test.tsx +99 -0
- package/src/react/primitives/threadList/ThreadListItems.tsx +8 -5
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.destroy.test.tsx +172 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +127 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +7 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +99 -35
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.load-error.test.ts +132 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +274 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +223 -152
- package/src/react/runtimes/RemoteThreadResource.test.ts +9 -0
- package/src/react/runtimes/RemoteThreadResource.ts +20 -16
- package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +51 -2
- package/src/react/runtimes/assistant-transport/useLatestRef.ts +2 -2
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +45 -0
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +546 -5
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +546 -103
- package/src/react/runtimes/cloud/auiV0.ts +5 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +103 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +237 -0
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +90 -1
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +33 -238
- package/src/react/runtimes/external-message-converter.ts +1 -0
- 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.concurrent.test.tsx +216 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.load-error.test.tsx +108 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.ts +57 -6
- package/src/react/types/MessagePartComponentTypes.ts +7 -3
- package/src/react/types/scopes/tools.ts +2 -0
- package/src/runtime/api/message-part-runtime.ts +3 -3
- 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 +46 -12
- package/src/runtime/api/thread-runtime.test.ts +78 -0
- package/src/runtime/api/thread-runtime.ts +8 -1
- package/src/runtime/base/base-composer-runtime-core.ts +36 -8
- package/src/runtime/base/base-thread-runtime-core.test.ts +149 -4
- package/src/runtime/base/base-thread-runtime-core.ts +16 -8
- package/src/runtime/interfaces/composer-runtime-core.ts +10 -5
- package/src/runtime/interfaces/thread-list-runtime-core.ts +25 -2
- package/src/runtime/interfaces/thread-runtime-core.ts +17 -1
- package/src/runtime/utils/auto-status.test.ts +57 -0
- package/src/runtime/utils/auto-status.ts +13 -1
- package/src/runtime/utils/external-message-conversion.test.ts +165 -0
- package/src/runtime/utils/external-message-conversion.ts +18 -2
- package/src/runtime/utils/message-repository.ts +29 -17
- package/src/runtime/utils/resolveToolApprovalResponse.test.ts +73 -0
- package/src/runtime/utils/resolveToolApprovalResponse.ts +27 -6
- package/src/runtime/utils/thread-message-like.ts +3 -11
- package/src/runtime/utils/tool-call-tree.test.ts +191 -0
- package/src/runtime/utils/tool-call-tree.ts +97 -0
- package/src/runtimes/external-store/external-store-adapter.ts +38 -2
- 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 +56 -33
- package/src/runtimes/inert/InertThreadRuntimeCore.ts +1 -1
- package/src/runtimes/internal.ts +1 -0
- package/src/runtimes/local/local-thread-runtime-core.test.ts +29 -3
- package/src/runtimes/local/local-thread-runtime-core.ts +5 -1
- package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +238 -0
- package/src/runtimes/remote-thread-list/remote-thread-state.ts +223 -44
- 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 +16 -0
- package/src/runtimes/remote-thread-list/types.ts +16 -5
- package/src/runtimes/tool-invocations/EDGE_CASES.md +110 -5
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +750 -136
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +144 -91
- package/src/store/clients/external-thread.ts +62 -11
- 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 +195 -1
- package/src/store/clients/suggestions.ts +45 -34
- package/src/store/index.ts +4 -0
- package/src/store/internal.ts +2 -0
- package/src/store/primitive-predicates.ts +35 -0
- 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 +17 -2
- package/src/store/runtime-clients/thread-runtime-client.ts +58 -10
- package/src/store/runtime-clients/useSubscribable.ts +8 -2
- package/src/store/scopes/composer.ts +16 -4
- package/src/store/scopes/message.ts +14 -0
- package/src/store/scopes/part.ts +6 -3
- package/src/store/scopes/thread-list-item.ts +5 -2
- package/src/store/scopes/thread.ts +4 -0
- package/src/store/scopes/threads.ts +1 -0
- package/src/subscribable/subscribable.test.ts +50 -0
- package/src/subscribable/subscribable.ts +33 -21
- package/src/tests/MessageRepository.test.ts +116 -0
- 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 +158 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +78 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-reload.test.ts +52 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +89 -0
- package/src/tests/attachment-adapters.test.ts +14 -0
- package/src/tests/base-composer-runtime-core.test.ts +39 -0
- package/src/tests/external-store-optimistic-id.test.ts +79 -0
- package/src/tests/external-store-repository-instance.test.ts +166 -0
- package/src/tests/external-store-thread-list-runtime-core.test.ts +83 -0
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +49 -34
- package/src/tests/external-thread-attachments.test.tsx +224 -1
- package/src/tests/external-thread-parity.test.tsx +23 -0
- package/src/tests/remote-thread-list-adapter-switch.test.ts +66 -1
- package/src/tests/remote-thread-list-isLoading.test.ts +1 -0
- package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
- package/src/tests/thread-switch-events.test.tsx +475 -2
- package/src/tests/tools-scope-migration.test.tsx +28 -0
- package/src/types/attachment.ts +4 -0
- package/src/types/message.ts +50 -2
- package/src/utils/abortable-iterable.test.ts +213 -0
- package/src/utils/abortable-iterable.ts +93 -0
- package/src/utils/composite-context-provider.test.ts +25 -0
- package/src/utils/composite-context-provider.ts +23 -2
- package/src/utils/record.test.ts +48 -0
- package/src/utils/record.ts +11 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
isAttachmentComplete,
|
|
2
3
|
isCreateAttachment,
|
|
3
4
|
type Attachment,
|
|
4
5
|
type CompleteAttachment,
|
|
@@ -34,9 +35,6 @@ import {
|
|
|
34
35
|
drainAttachmentAdd,
|
|
35
36
|
} from "../utils/attachment-add-operations";
|
|
36
37
|
|
|
37
|
-
const isAttachmentComplete = (a: Attachment): a is CompleteAttachment =>
|
|
38
|
-
a.status.type === "complete";
|
|
39
|
-
|
|
40
38
|
export abstract class BaseComposerRuntimeCore
|
|
41
39
|
extends BaseSubscribable
|
|
42
40
|
implements ComposerRuntimeCore
|
|
@@ -161,6 +159,7 @@ export abstract class BaseComposerRuntimeCore
|
|
|
161
159
|
private _emptyTextAndAttachments() {
|
|
162
160
|
this._attachments = [];
|
|
163
161
|
this._text = "";
|
|
162
|
+
this._rebaseDictation("");
|
|
164
163
|
this._notifySubscribers();
|
|
165
164
|
}
|
|
166
165
|
|
|
@@ -301,7 +300,10 @@ export abstract class BaseComposerRuntimeCore
|
|
|
301
300
|
void sendTask.catch((error) => {
|
|
302
301
|
this._restoreUnsentDraft(error, generation, draft);
|
|
303
302
|
});
|
|
304
|
-
this._notifyEventSubscribers("send", {
|
|
303
|
+
this._notifyEventSubscribers("send", {
|
|
304
|
+
chars: text.length,
|
|
305
|
+
attachments: finalAttachments.length,
|
|
306
|
+
});
|
|
305
307
|
}
|
|
306
308
|
|
|
307
309
|
/**
|
|
@@ -417,6 +419,7 @@ export abstract class BaseComposerRuntimeCore
|
|
|
417
419
|
message,
|
|
418
420
|
undefined,
|
|
419
421
|
err,
|
|
422
|
+
fileOrAttachment.contentType,
|
|
420
423
|
);
|
|
421
424
|
throw err;
|
|
422
425
|
}
|
|
@@ -431,7 +434,9 @@ export abstract class BaseComposerRuntimeCore
|
|
|
431
434
|
};
|
|
432
435
|
this._attachments = [...this._attachments, a];
|
|
433
436
|
this._notifySubscribers();
|
|
434
|
-
this._notifyEventSubscribers("attachmentAdd", {
|
|
437
|
+
this._notifyEventSubscribers("attachmentAdd", {
|
|
438
|
+
...(a.contentType ? { contentType: a.contentType } : undefined),
|
|
439
|
+
});
|
|
435
440
|
return;
|
|
436
441
|
}
|
|
437
442
|
|
|
@@ -439,7 +444,13 @@ export abstract class BaseComposerRuntimeCore
|
|
|
439
444
|
if (!adapter) {
|
|
440
445
|
const message = "Attachments are not supported";
|
|
441
446
|
const err = new Error(message);
|
|
442
|
-
this._safeEmitAttachmentAddError(
|
|
447
|
+
this._safeEmitAttachmentAddError(
|
|
448
|
+
"no-adapter",
|
|
449
|
+
message,
|
|
450
|
+
undefined,
|
|
451
|
+
err,
|
|
452
|
+
fileOrAttachment.type,
|
|
453
|
+
);
|
|
443
454
|
throw err;
|
|
444
455
|
}
|
|
445
456
|
|
|
@@ -451,7 +462,13 @@ export abstract class BaseComposerRuntimeCore
|
|
|
451
462
|
) {
|
|
452
463
|
const message = `File type ${fileOrAttachment.type || "unknown"} is not accepted. Accepted types: ${adapter.accept}`;
|
|
453
464
|
const err = new Error(message);
|
|
454
|
-
this._safeEmitAttachmentAddError(
|
|
465
|
+
this._safeEmitAttachmentAddError(
|
|
466
|
+
"not-accepted",
|
|
467
|
+
message,
|
|
468
|
+
undefined,
|
|
469
|
+
err,
|
|
470
|
+
fileOrAttachment.type,
|
|
471
|
+
);
|
|
455
472
|
throw err;
|
|
456
473
|
}
|
|
457
474
|
|
|
@@ -501,6 +518,7 @@ export abstract class BaseComposerRuntimeCore
|
|
|
501
518
|
e instanceof Error ? e.message : String(e),
|
|
502
519
|
lastAttachment?.id,
|
|
503
520
|
e instanceof Error ? e : undefined,
|
|
521
|
+
lastAttachment?.contentType || fileOrAttachment.type,
|
|
504
522
|
);
|
|
505
523
|
throw e;
|
|
506
524
|
} finally {
|
|
@@ -517,9 +535,17 @@ export abstract class BaseComposerRuntimeCore
|
|
|
517
535
|
lastAttachment.status.message ??
|
|
518
536
|
"Attachment upload did not complete successfully.",
|
|
519
537
|
lastAttachment.id,
|
|
538
|
+
undefined,
|
|
539
|
+
lastAttachment.contentType || fileOrAttachment.type,
|
|
520
540
|
);
|
|
521
541
|
} else {
|
|
522
|
-
this._notifyEventSubscribers("attachmentAdd", {
|
|
542
|
+
this._notifyEventSubscribers("attachmentAdd", {
|
|
543
|
+
...(lastAttachment?.contentType
|
|
544
|
+
? { contentType: lastAttachment.contentType }
|
|
545
|
+
: fileOrAttachment.type
|
|
546
|
+
? { contentType: fileOrAttachment.type }
|
|
547
|
+
: undefined),
|
|
548
|
+
});
|
|
523
549
|
}
|
|
524
550
|
}
|
|
525
551
|
|
|
@@ -528,6 +554,7 @@ export abstract class BaseComposerRuntimeCore
|
|
|
528
554
|
message: string,
|
|
529
555
|
attachmentId?: string,
|
|
530
556
|
error?: Error,
|
|
557
|
+
contentType?: string,
|
|
531
558
|
) {
|
|
532
559
|
try {
|
|
533
560
|
this._notifyEventSubscribers("attachmentAddError", {
|
|
@@ -535,6 +562,7 @@ export abstract class BaseComposerRuntimeCore
|
|
|
535
562
|
message,
|
|
536
563
|
...(attachmentId !== undefined && { attachmentId }),
|
|
537
564
|
...(error !== undefined && { error }),
|
|
565
|
+
...(contentType ? { contentType } : undefined),
|
|
538
566
|
});
|
|
539
567
|
} catch (subscriberError) {
|
|
540
568
|
console.error(
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
2
|
import type { RealtimeVoiceAdapter } from "../../adapters/voice";
|
|
3
|
+
import type { ModelContextProvider } from "../../model-context/types";
|
|
3
4
|
import type { AppendMessage } from "../../types/message";
|
|
5
|
+
import { CompositeContextProvider } from "../../utils/composite-context-provider";
|
|
4
6
|
import type {
|
|
5
7
|
AddToolResultOptions,
|
|
6
8
|
ResumeRunConfig,
|
|
@@ -14,6 +16,9 @@ import { BaseThreadRuntimeCore } from "./base-thread-runtime-core";
|
|
|
14
16
|
|
|
15
17
|
const createVoiceAdapter = () => {
|
|
16
18
|
let volumeCallback: ((volume: number) => void) | undefined;
|
|
19
|
+
let transcriptCallback:
|
|
20
|
+
| ((transcript: RealtimeVoiceAdapter.TranscriptItem) => void)
|
|
21
|
+
| undefined;
|
|
17
22
|
const session: RealtimeVoiceAdapter.Session = {
|
|
18
23
|
status: { type: "running" },
|
|
19
24
|
isMuted: false,
|
|
@@ -21,7 +26,12 @@ const createVoiceAdapter = () => {
|
|
|
21
26
|
mute: vi.fn(),
|
|
22
27
|
unmute: vi.fn(),
|
|
23
28
|
onStatusChange: () => () => {},
|
|
24
|
-
onTranscript: () =>
|
|
29
|
+
onTranscript: (callback) => {
|
|
30
|
+
transcriptCallback = callback;
|
|
31
|
+
return () => {
|
|
32
|
+
transcriptCallback = undefined;
|
|
33
|
+
};
|
|
34
|
+
},
|
|
25
35
|
onModeChange: () => () => {},
|
|
26
36
|
onVolumeChange: (callback) => {
|
|
27
37
|
volumeCallback = callback;
|
|
@@ -34,10 +44,13 @@ const createVoiceAdapter = () => {
|
|
|
34
44
|
return {
|
|
35
45
|
adapter: { connect: () => session },
|
|
36
46
|
emitVolume: (volume: number) => volumeCallback?.(volume),
|
|
47
|
+
emitTranscript: (transcript: RealtimeVoiceAdapter.TranscriptItem) =>
|
|
48
|
+
transcriptCallback?.(transcript),
|
|
37
49
|
session,
|
|
38
50
|
} satisfies {
|
|
39
51
|
adapter: RealtimeVoiceAdapter;
|
|
40
52
|
emitVolume: (volume: number) => void;
|
|
53
|
+
emitTranscript: (transcript: RealtimeVoiceAdapter.TranscriptItem) => void;
|
|
41
54
|
session: RealtimeVoiceAdapter.Session;
|
|
42
55
|
};
|
|
43
56
|
};
|
|
@@ -45,8 +58,11 @@ const createVoiceAdapter = () => {
|
|
|
45
58
|
class TestRuntime extends BaseThreadRuntimeCore {
|
|
46
59
|
private readonly voiceAdapter: ReturnType<typeof createVoiceAdapter>;
|
|
47
60
|
|
|
48
|
-
constructor(
|
|
49
|
-
|
|
61
|
+
constructor(
|
|
62
|
+
voiceAdapter: ReturnType<typeof createVoiceAdapter>,
|
|
63
|
+
contextProvider: ModelContextProvider = { getModelContext: () => ({}) },
|
|
64
|
+
) {
|
|
65
|
+
super(contextProvider);
|
|
50
66
|
this.voiceAdapter = voiceAdapter;
|
|
51
67
|
}
|
|
52
68
|
|
|
@@ -99,7 +115,7 @@ class TestRuntime extends BaseThreadRuntimeCore {
|
|
|
99
115
|
resumeRun(_config: ResumeRunConfig) {}
|
|
100
116
|
addToolResult(_options: AddToolResultOptions) {}
|
|
101
117
|
resumeToolCall(_options: ResumeToolCallOptions) {}
|
|
102
|
-
respondToToolApproval(_options: RespondToToolApprovalOptions) {}
|
|
118
|
+
async respondToToolApproval(_options: RespondToToolApprovalOptions) {}
|
|
103
119
|
cancelRun() {}
|
|
104
120
|
exportExternalState() {
|
|
105
121
|
return {};
|
|
@@ -126,6 +142,92 @@ describe("BaseThreadRuntimeCore subscriptions", () => {
|
|
|
126
142
|
expect(() => runtime.reset()).toThrow(error);
|
|
127
143
|
expect(laterSubscriber).toHaveBeenCalledOnce();
|
|
128
144
|
});
|
|
145
|
+
|
|
146
|
+
it("isolates initialize listener errors during late replay", async () => {
|
|
147
|
+
const consoleError = vi
|
|
148
|
+
.spyOn(console, "error")
|
|
149
|
+
.mockImplementation(() => {});
|
|
150
|
+
const runtime = new TestRuntime(createVoiceAdapter());
|
|
151
|
+
runtime.reset();
|
|
152
|
+
|
|
153
|
+
const syncError = new Error("sync listener failed");
|
|
154
|
+
const asyncError = new Error("async listener failed");
|
|
155
|
+
runtime.unstable_on("initialize", () => {
|
|
156
|
+
throw syncError;
|
|
157
|
+
});
|
|
158
|
+
runtime.unstable_on("initialize", async () => {
|
|
159
|
+
throw asyncError;
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
await vi.waitFor(() => {
|
|
163
|
+
expect(consoleError).toHaveBeenCalledTimes(2);
|
|
164
|
+
expect(consoleError).toHaveBeenCalledWith(
|
|
165
|
+
'[assistant-ui] Thread runtime "initialize" listener threw an error',
|
|
166
|
+
syncError,
|
|
167
|
+
);
|
|
168
|
+
expect(consoleError).toHaveBeenCalledWith(
|
|
169
|
+
'[assistant-ui] Thread runtime "initialize" listener threw an error',
|
|
170
|
+
asyncError,
|
|
171
|
+
);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it("isolates modelContextUpdate listener errors during context updates", () => {
|
|
176
|
+
const consoleError = vi
|
|
177
|
+
.spyOn(console, "error")
|
|
178
|
+
.mockImplementation(() => {});
|
|
179
|
+
const provider = new CompositeContextProvider();
|
|
180
|
+
const runtime = new TestRuntime(createVoiceAdapter(), provider);
|
|
181
|
+
const listenerError = new Error("model context listener failed");
|
|
182
|
+
const laterListener = vi.fn();
|
|
183
|
+
|
|
184
|
+
runtime.unstable_on("modelContextUpdate", () => {
|
|
185
|
+
throw listenerError;
|
|
186
|
+
});
|
|
187
|
+
runtime.unstable_on("modelContextUpdate", laterListener);
|
|
188
|
+
|
|
189
|
+
const unregister = provider.registerModelContextProvider({
|
|
190
|
+
getModelContext: () => ({}),
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
expect(laterListener).toHaveBeenCalledOnce();
|
|
194
|
+
expect(consoleError).toHaveBeenNthCalledWith(
|
|
195
|
+
1,
|
|
196
|
+
'[assistant-ui] Thread runtime "modelContextUpdate" listener threw an error',
|
|
197
|
+
listenerError,
|
|
198
|
+
);
|
|
199
|
+
expect(() => unregister()).not.toThrow();
|
|
200
|
+
expect(laterListener).toHaveBeenCalledTimes(2);
|
|
201
|
+
expect(consoleError).toHaveBeenNthCalledWith(
|
|
202
|
+
2,
|
|
203
|
+
'[assistant-ui] Thread runtime "modelContextUpdate" listener threw an error',
|
|
204
|
+
listenerError,
|
|
205
|
+
);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it("observes rejected modelContextUpdate listener promises", async () => {
|
|
209
|
+
const consoleError = vi
|
|
210
|
+
.spyOn(console, "error")
|
|
211
|
+
.mockImplementation(() => {});
|
|
212
|
+
const provider = new CompositeContextProvider();
|
|
213
|
+
const runtime = new TestRuntime(createVoiceAdapter(), provider);
|
|
214
|
+
const listenerError = new Error("async model context listener failed");
|
|
215
|
+
|
|
216
|
+
runtime.unstable_on("modelContextUpdate", async () => {
|
|
217
|
+
throw listenerError;
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
expect(() =>
|
|
221
|
+
provider.registerModelContextProvider({ getModelContext: () => ({}) }),
|
|
222
|
+
).not.toThrow();
|
|
223
|
+
|
|
224
|
+
await vi.waitFor(() => {
|
|
225
|
+
expect(consoleError).toHaveBeenCalledWith(
|
|
226
|
+
'[assistant-ui] Thread runtime "modelContextUpdate" listener threw an error',
|
|
227
|
+
listenerError,
|
|
228
|
+
);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
129
231
|
});
|
|
130
232
|
|
|
131
233
|
describe("BaseThreadRuntimeCore voice volume subscriptions", () => {
|
|
@@ -205,3 +307,46 @@ describe("BaseThreadRuntimeCore voice volume subscriptions", () => {
|
|
|
205
307
|
});
|
|
206
308
|
});
|
|
207
309
|
});
|
|
310
|
+
|
|
311
|
+
describe("BaseThreadRuntimeCore voice transcripts", () => {
|
|
312
|
+
it("completes a final-only reply before the next streamed reply", () => {
|
|
313
|
+
const voiceAdapter = createVoiceAdapter();
|
|
314
|
+
const runtime = new TestRuntime(voiceAdapter);
|
|
315
|
+
runtime.connectVoice();
|
|
316
|
+
|
|
317
|
+
try {
|
|
318
|
+
voiceAdapter.emitTranscript({
|
|
319
|
+
role: "assistant",
|
|
320
|
+
text: "Finished reply",
|
|
321
|
+
isFinal: true,
|
|
322
|
+
});
|
|
323
|
+
expect(runtime.messages).toMatchObject([
|
|
324
|
+
{
|
|
325
|
+
content: [{ type: "text", text: "Finished reply" }],
|
|
326
|
+
status: { type: "complete", reason: "stop" },
|
|
327
|
+
},
|
|
328
|
+
]);
|
|
329
|
+
|
|
330
|
+
voiceAdapter.emitTranscript({ role: "assistant", text: "Next" });
|
|
331
|
+
expect(runtime.messages.at(-1)?.status).toEqual({ type: "running" });
|
|
332
|
+
|
|
333
|
+
voiceAdapter.emitTranscript({
|
|
334
|
+
role: "assistant",
|
|
335
|
+
text: "Next reply",
|
|
336
|
+
isFinal: true,
|
|
337
|
+
});
|
|
338
|
+
expect(runtime.messages).toMatchObject([
|
|
339
|
+
{
|
|
340
|
+
content: [{ type: "text", text: "Finished reply" }],
|
|
341
|
+
status: { type: "complete", reason: "stop" },
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
content: [{ type: "text", text: "Next reply" }],
|
|
345
|
+
status: { type: "complete", reason: "stop" },
|
|
346
|
+
},
|
|
347
|
+
]);
|
|
348
|
+
} finally {
|
|
349
|
+
runtime.disconnectVoice();
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
});
|
|
@@ -51,7 +51,7 @@ export abstract class BaseThreadRuntimeCore
|
|
|
51
51
|
{
|
|
52
52
|
private _isInitialized = false;
|
|
53
53
|
|
|
54
|
-
protected
|
|
54
|
+
protected repository = new MessageRepository();
|
|
55
55
|
public abstract get adapters(): BaseThreadAdapters | undefined;
|
|
56
56
|
public abstract get isDisabled(): boolean;
|
|
57
57
|
public abstract get isSendDisabled(): boolean;
|
|
@@ -68,7 +68,7 @@ export abstract class BaseThreadRuntimeCore
|
|
|
68
68
|
public abstract resumeToolCall(options: ResumeToolCallOptions): void;
|
|
69
69
|
public abstract respondToToolApproval(
|
|
70
70
|
options: RespondToToolApprovalOptions,
|
|
71
|
-
): void
|
|
71
|
+
): Promise<void>;
|
|
72
72
|
public abstract cancelRun(): void;
|
|
73
73
|
public abstract exportExternalState(): any;
|
|
74
74
|
public abstract importExternalState(state: any): void;
|
|
@@ -393,6 +393,10 @@ export abstract class BaseThreadRuntimeCore
|
|
|
393
393
|
this._notifySubscribers();
|
|
394
394
|
}
|
|
395
395
|
} else {
|
|
396
|
+
const status: ThreadAssistantMessage["status"] = transcript.isFinal
|
|
397
|
+
? { type: "complete", reason: "stop" }
|
|
398
|
+
: { type: "running" };
|
|
399
|
+
|
|
396
400
|
if (!this._currentAssistantMsg) {
|
|
397
401
|
this._currentAssistantMsg = {
|
|
398
402
|
id: generateId(),
|
|
@@ -405,7 +409,7 @@ export abstract class BaseThreadRuntimeCore
|
|
|
405
409
|
steps: [],
|
|
406
410
|
custom: {},
|
|
407
411
|
},
|
|
408
|
-
status
|
|
412
|
+
status,
|
|
409
413
|
createdAt: new Date(),
|
|
410
414
|
};
|
|
411
415
|
this._voiceMessages.push(this._currentAssistantMsg);
|
|
@@ -415,9 +419,7 @@ export abstract class BaseThreadRuntimeCore
|
|
|
415
419
|
const updated: ThreadAssistantMessage = {
|
|
416
420
|
...this._currentAssistantMsg,
|
|
417
421
|
content: [{ type: "text", text: transcript.text }],
|
|
418
|
-
|
|
419
|
-
? { status: { type: "complete", reason: "stop" } }
|
|
420
|
-
: {}),
|
|
422
|
+
status,
|
|
421
423
|
};
|
|
422
424
|
this._voiceMessages[idx] = updated;
|
|
423
425
|
this._currentAssistantMsg = updated;
|
|
@@ -518,7 +520,11 @@ export abstract class BaseThreadRuntimeCore
|
|
|
518
520
|
const wrapped = callback as (payload?: unknown) => void;
|
|
519
521
|
if (event === "modelContextUpdate") {
|
|
520
522
|
// provider.subscribe is `() => void`; pump the typed empty payload to the user callback.
|
|
521
|
-
return
|
|
523
|
+
return (
|
|
524
|
+
this._contextProvider.subscribe?.(() =>
|
|
525
|
+
notifyEventListeners([wrapped], {}, `Thread runtime "${event}"`),
|
|
526
|
+
) ?? (() => {})
|
|
527
|
+
);
|
|
522
528
|
}
|
|
523
529
|
|
|
524
530
|
let subscribers = this._eventSubscribers.get(event);
|
|
@@ -532,7 +538,9 @@ export abstract class BaseThreadRuntimeCore
|
|
|
532
538
|
// after the thread already initialized, mirroring a BehaviorSubject.
|
|
533
539
|
if (event === "initialize" && this._isInitialized) {
|
|
534
540
|
queueMicrotask(() => {
|
|
535
|
-
if (subscribers.has(wrapped))
|
|
541
|
+
if (subscribers.has(wrapped)) {
|
|
542
|
+
notifyEventListeners([wrapped], {}, `Thread runtime "${event}"`);
|
|
543
|
+
}
|
|
536
544
|
});
|
|
537
545
|
}
|
|
538
546
|
|
|
@@ -21,16 +21,21 @@ export type AttachmentAddErrorEvent = {
|
|
|
21
21
|
|
|
22
22
|
export type ComposerRuntimeEventPayload = {
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
24
|
+
* Fired after a send with the size of what went out. The composer state is
|
|
25
|
+
* already cleared when it fires, so the counts are only available here.
|
|
26
26
|
*/
|
|
27
|
-
send:
|
|
27
|
+
send: {
|
|
28
|
+
readonly chars: number;
|
|
29
|
+
readonly attachments: number;
|
|
30
|
+
};
|
|
28
31
|
/**
|
|
29
32
|
* @deprecated State-derivable. Observe `state.attachments` via `subscribe` +
|
|
30
33
|
* `getState` instead. Kept for backward compatibility.
|
|
31
34
|
*/
|
|
32
|
-
attachmentAdd:
|
|
33
|
-
attachmentAddError: AttachmentAddErrorEvent
|
|
35
|
+
attachmentAdd: { readonly contentType?: string | undefined };
|
|
36
|
+
attachmentAddError: AttachmentAddErrorEvent & {
|
|
37
|
+
readonly contentType?: string | undefined;
|
|
38
|
+
};
|
|
34
39
|
};
|
|
35
40
|
|
|
36
41
|
export type ComposerRuntimeEventType = keyof ComposerRuntimeEventPayload;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { Unsubscribe } from "../../types/unsubscribe";
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
ThreadRuntimeCore,
|
|
4
|
+
ThreadRuntimeEventType,
|
|
5
|
+
} from "./thread-runtime-core";
|
|
3
6
|
|
|
4
7
|
export type ThreadListItemStatus = "archived" | "regular" | "new" | "deleted";
|
|
5
8
|
|
|
@@ -16,8 +19,14 @@ export type ThreadListItemCoreState = {
|
|
|
16
19
|
readonly runtime?: ThreadRuntimeCore | undefined;
|
|
17
20
|
};
|
|
18
21
|
|
|
22
|
+
export type ThreadListRuntimeEvent = {
|
|
23
|
+
readonly threadId: string;
|
|
24
|
+
readonly type: ThreadRuntimeEventType;
|
|
25
|
+
};
|
|
26
|
+
|
|
19
27
|
export type ThreadListRuntimeCore = {
|
|
20
28
|
readonly isLoading: boolean;
|
|
29
|
+
readonly loadError?: unknown;
|
|
21
30
|
readonly isLoadingMore?: boolean;
|
|
22
31
|
readonly hasMore?: boolean;
|
|
23
32
|
mainThreadId: string;
|
|
@@ -41,6 +50,17 @@ export type ThreadListRuntimeCore = {
|
|
|
41
50
|
*/
|
|
42
51
|
unstable_isThreadRunning?(threadId: string): boolean;
|
|
43
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Lifecycle events from every thread this list keeps alive, including
|
|
55
|
+
* threads that are not the main one. Implemented by thread lists that keep
|
|
56
|
+
* runtimes alive for non-main threads. A thread list that mounts only the
|
|
57
|
+
* main thread leaves this undefined: its other threads have no runtime and so
|
|
58
|
+
* emit nothing, and the main thread's runtime is observed directly.
|
|
59
|
+
*/
|
|
60
|
+
unstable_subscribeThreadEvents?(
|
|
61
|
+
callback: (event: ThreadListRuntimeEvent) => void,
|
|
62
|
+
): Unsubscribe;
|
|
63
|
+
|
|
44
64
|
getItemById(threadId: string): ThreadListItemCoreState | undefined;
|
|
45
65
|
|
|
46
66
|
switchToThread(
|
|
@@ -67,7 +87,10 @@ export type ThreadListRuntimeCore = {
|
|
|
67
87
|
initialize(
|
|
68
88
|
threadId: string,
|
|
69
89
|
): Promise<{ remoteId: string; externalId: string | undefined }>;
|
|
70
|
-
generateTitle(
|
|
90
|
+
generateTitle(
|
|
91
|
+
threadId: string,
|
|
92
|
+
options?: { automatic?: boolean },
|
|
93
|
+
): Promise<void>;
|
|
71
94
|
|
|
72
95
|
subscribe(callback: () => void): Unsubscribe;
|
|
73
96
|
};
|
|
@@ -63,6 +63,8 @@ export type RespondToToolApprovalOptions = {
|
|
|
63
63
|
approved: boolean;
|
|
64
64
|
/** The approval option that produced this decision, when the request carried options. */
|
|
65
65
|
optionId?: string;
|
|
66
|
+
/** The free-form answer, when the request asked for one. */
|
|
67
|
+
text?: string;
|
|
66
68
|
reason?: string;
|
|
67
69
|
};
|
|
68
70
|
|
|
@@ -165,7 +167,21 @@ export type ThreadRuntimeCore = Readonly<{
|
|
|
165
167
|
|
|
166
168
|
addToolResult: (options: AddToolResultOptions) => void;
|
|
167
169
|
resumeToolCall: (options: ResumeToolCallOptions) => void;
|
|
168
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Records a decision on a tool approval gate. Resolves once the runtime has
|
|
172
|
+
* accepted the response and rejects when it could not be recorded, so a
|
|
173
|
+
* caller can leave the gate retryable rather than spending it. A capability
|
|
174
|
+
* or state precondition still throws synchronously; a failure to record
|
|
175
|
+
* arrives as a rejection, including one an adapter raises synchronously.
|
|
176
|
+
*
|
|
177
|
+
* Acceptance is as far as the runtime can see the response: one that records
|
|
178
|
+
* the decision locally settles on the record, while one that answers by
|
|
179
|
+
* resuming a run settles on the resume. A failure of the work the decision
|
|
180
|
+
* unblocks is reported through the runtime's own error channel, not here.
|
|
181
|
+
*/
|
|
182
|
+
respondToToolApproval: (
|
|
183
|
+
options: RespondToToolApprovalOptions,
|
|
184
|
+
) => Promise<void>;
|
|
169
185
|
|
|
170
186
|
speak: (messageId: string) => void;
|
|
171
187
|
stopSpeaking: () => void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { getAutoStatus } from "./auto-status";
|
|
3
|
+
|
|
4
|
+
describe("getAutoStatus", () => {
|
|
5
|
+
it("reports a cancelled message as incomplete", () => {
|
|
6
|
+
expect(
|
|
7
|
+
getAutoStatus(true, false, false, false, undefined, true),
|
|
8
|
+
).toMatchObject({ type: "incomplete", reason: "cancelled" });
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("keeps a cancelled message incomplete once a later message arrives", () => {
|
|
12
|
+
expect(
|
|
13
|
+
getAutoStatus(false, false, false, false, undefined, true),
|
|
14
|
+
).toMatchObject({ type: "incomplete", reason: "cancelled" });
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("reports an uncancelled message as complete", () => {
|
|
18
|
+
expect(
|
|
19
|
+
getAutoStatus(true, false, false, false, undefined, false),
|
|
20
|
+
).toMatchObject({ type: "complete", reason: "unknown" });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it.each([
|
|
24
|
+
["running", { type: "running" }, true, false, false, undefined],
|
|
25
|
+
[
|
|
26
|
+
"an interrupted tool call",
|
|
27
|
+
{ type: "requires-action", reason: "interrupt" },
|
|
28
|
+
false,
|
|
29
|
+
true,
|
|
30
|
+
true,
|
|
31
|
+
undefined,
|
|
32
|
+
],
|
|
33
|
+
[
|
|
34
|
+
"a pending tool call",
|
|
35
|
+
{ type: "requires-action", reason: "tool-calls" },
|
|
36
|
+
false,
|
|
37
|
+
false,
|
|
38
|
+
true,
|
|
39
|
+
undefined,
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
"an error",
|
|
43
|
+
{ type: "incomplete", reason: "error", error: "boom" },
|
|
44
|
+
false,
|
|
45
|
+
false,
|
|
46
|
+
false,
|
|
47
|
+
"boom",
|
|
48
|
+
],
|
|
49
|
+
])(
|
|
50
|
+
"keeps %s ahead of cancellation",
|
|
51
|
+
(_label, expected, isRunning, interrupted, pending, error) => {
|
|
52
|
+
expect(
|
|
53
|
+
getAutoStatus(true, isRunning, interrupted, pending, error, true),
|
|
54
|
+
).toMatchObject(expected);
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
});
|
|
@@ -36,6 +36,15 @@ const AUTO_STATUS_COMPLETE = Object.freeze(
|
|
|
36
36
|
{ [symbolAutoStatus]: true },
|
|
37
37
|
),
|
|
38
38
|
);
|
|
39
|
+
const AUTO_STATUS_CANCELLED = Object.freeze(
|
|
40
|
+
Object.assign(
|
|
41
|
+
{
|
|
42
|
+
type: "incomplete" as const,
|
|
43
|
+
reason: "cancelled" as const,
|
|
44
|
+
},
|
|
45
|
+
{ [symbolAutoStatus]: true },
|
|
46
|
+
),
|
|
47
|
+
);
|
|
39
48
|
|
|
40
49
|
const AUTO_STATUS_PENDING = Object.freeze(
|
|
41
50
|
Object.assign(
|
|
@@ -66,6 +75,7 @@ export const getAutoStatus = (
|
|
|
66
75
|
hasInterruptedToolCalls: boolean,
|
|
67
76
|
hasPendingToolCalls: boolean,
|
|
68
77
|
error?: ReadonlyJSONValue,
|
|
78
|
+
isCancelled?: boolean,
|
|
69
79
|
): MessageStatus => {
|
|
70
80
|
if (isLast && error) {
|
|
71
81
|
return Object.assign(
|
|
@@ -84,7 +94,9 @@ export const getAutoStatus = (
|
|
|
84
94
|
? AUTO_STATUS_INTERRUPT
|
|
85
95
|
: hasPendingToolCalls
|
|
86
96
|
? AUTO_STATUS_PENDING
|
|
87
|
-
:
|
|
97
|
+
: isCancelled
|
|
98
|
+
? AUTO_STATUS_CANCELLED
|
|
99
|
+
: AUTO_STATUS_COMPLETE;
|
|
88
100
|
};
|
|
89
101
|
|
|
90
102
|
export const getContentAutoStatus = (
|