@assistant-ui/core 0.3.12 → 0.3.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/speech.d.ts.map +1 -1
- package/dist/adapters/speech.js +9 -15
- package/dist/adapters/speech.js.map +1 -1
- package/dist/adapters/thread-history.d.ts +2 -0
- package/dist/adapters/thread-history.d.ts.map +1 -1
- package/dist/adapters/voice.d.ts.map +1 -1
- package/dist/adapters/voice.js +27 -15
- package/dist/adapters/voice.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.js +6 -6
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +2 -1
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/registry.d.ts.map +1 -1
- package/dist/model-context/registry.js +16 -4
- package/dist/model-context/registry.js.map +1 -1
- package/dist/react/RuntimeAdapter.d.ts +8 -1
- package/dist/react/RuntimeAdapter.d.ts.map +1 -1
- package/dist/react/RuntimeAdapter.js +23 -18
- package/dist/react/RuntimeAdapter.js.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js +28 -12
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/AdaptedRemoteThread.d.ts +11 -0
- package/dist/react/client/AdaptedRemoteThread.d.ts.map +1 -0
- package/dist/react/client/AdaptedRemoteThread.js +27 -0
- package/dist/react/client/AdaptedRemoteThread.js.map +1 -0
- package/dist/react/client/InMemoryThreadList.d.ts +19 -0
- package/dist/react/client/InMemoryThreadList.d.ts.map +1 -0
- package/dist/react/client/InMemoryThreadList.js +418 -0
- package/dist/react/client/InMemoryThreadList.js.map +1 -0
- package/dist/react/client/Interactables.d.ts.map +1 -1
- package/dist/react/client/Interactables.js +159 -102
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/RemoteThreadList.d.ts +34 -0
- package/dist/react/client/RemoteThreadList.d.ts.map +1 -0
- package/dist/react/client/RemoteThreadList.js +826 -0
- package/dist/react/client/RemoteThreadList.js.map +1 -0
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +38 -27
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/client/interactable-model-context.d.ts.map +1 -1
- package/dist/react/client/interactable-model-context.js +5 -1
- package/dist/react/client/interactable-model-context.js.map +1 -1
- package/dist/react/index.d.ts +7 -2
- package/dist/react/index.js +5 -2
- package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
- package/dist/react/interactables-legacy/Interactables.js +145 -110
- package/dist/react/interactables-legacy/Interactables.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.js +13 -18
- package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.js +2 -4
- package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.js +2 -4
- package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.js +2 -6
- package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js +2 -6
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.js +2 -4
- package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.js +2 -4
- package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.js +6 -2
- package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
- package/dist/react/primitives/message/MessageParts.d.ts +13 -0
- package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.js +1 -1
- package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +22 -10
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +109 -71
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +8 -2
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +40 -13
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.d.ts +30 -0
- package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -0
- package/dist/react/runtimes/RemoteThreadResource.js +134 -0
- package/dist/react/runtimes/RemoteThreadResource.js.map +1 -0
- package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +3 -10
- package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
- package/dist/react/runtimes/RuntimeAdapterProvider.js +3 -6
- package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
- package/dist/react/runtimes/assistant-transport/commandQueue.d.ts +17 -0
- package/dist/react/runtimes/assistant-transport/commandQueue.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/commandQueue.js +55 -0
- package/dist/react/runtimes/assistant-transport/commandQueue.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts +11 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js +165 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/runManager.d.ts +15 -0
- package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/runManager.js +86 -0
- package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/types.d.ts +130 -0
- package/dist/react/runtimes/assistant-transport/types.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/types.js +0 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts +14 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js +296 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts +7 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.js +25 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts +7 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.js +27 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -0
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +39 -13
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +2 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +3 -3
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +4 -0
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js +7 -0
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +22 -12
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts +16 -0
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts.map +1 -0
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js +36 -0
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -0
- package/dist/react/runtimes/external-message-converter.js +14 -14
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useExternalStoreRuntime.js +44 -28
- package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
- package/dist/react/runtimes/useLocalRuntime.js +1 -1
- package/dist/react/runtimes/useRuntimeAdapters.d.ts +9 -0
- package/dist/react/runtimes/useRuntimeAdapters.d.ts.map +1 -0
- package/dist/react/runtimes/useRuntimeAdapters.js +20 -0
- package/dist/react/runtimes/useRuntimeAdapters.js.map +1 -0
- package/dist/runtime/api/composer-runtime.d.ts +5 -0
- package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.js.map +1 -1
- package/dist/runtime/api/message-runtime.js +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts +1 -0
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +4 -2
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +12 -2
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +13 -3
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts +25 -0
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +72 -18
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +15 -0
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +34 -3
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.js +1 -6
- package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +0 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js +11 -8
- package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/internal.js +5 -5
- package/dist/runtime/queue/external-thread-queue-adapter.d.ts +15 -0
- package/dist/runtime/queue/external-thread-queue-adapter.d.ts.map +1 -1
- package/dist/runtime/queue/message-queue.d.ts.map +1 -1
- package/dist/runtime/queue/message-queue.js +25 -11
- package/dist/runtime/queue/message-queue.js.map +1 -1
- package/dist/runtime/utils/thread-runtime-lifecycle.d.ts +8 -0
- package/dist/runtime/utils/thread-runtime-lifecycle.d.ts.map +1 -0
- package/dist/runtime/utils/thread-runtime-lifecycle.js +11 -0
- package/dist/runtime/utils/thread-runtime-lifecycle.js.map +1 -0
- package/dist/runtimes/external-store/external-store-adapter.d.ts +7 -0
- package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +4 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +11 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +78 -20
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/internal.d.ts +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +55 -14
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +1 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +3 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.js +3 -0
- package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/types.d.ts +29 -1
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +1 -12
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +67 -38
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/external-thread.d.ts +7 -0
- package/dist/store/clients/external-thread.d.ts.map +1 -1
- package/dist/store/clients/external-thread.js +460 -369
- package/dist/store/clients/external-thread.js.map +1 -1
- package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
- package/dist/store/clients/runtime-adapter.js +5 -2
- package/dist/store/clients/runtime-adapter.js.map +1 -1
- package/dist/store/clients/single-thread-list.d.ts.map +1 -1
- package/dist/store/clients/single-thread-list.js +31 -27
- package/dist/store/clients/single-thread-list.js.map +1 -1
- package/dist/store/clients/suggestions.d.ts +3 -1
- package/dist/store/clients/suggestions.d.ts.map +1 -1
- package/dist/store/clients/suggestions.js +65 -37
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/clients/thread-selection-events.d.ts +10 -0
- package/dist/store/clients/thread-selection-events.d.ts.map +1 -0
- package/dist/store/clients/thread-selection-events.js +40 -0
- package/dist/store/clients/thread-selection-events.js.map +1 -0
- package/dist/store/env.d.ts +5 -0
- package/dist/store/env.d.ts.map +1 -0
- package/dist/store/env.js +12 -0
- package/dist/store/env.js.map +1 -0
- package/dist/store/index.d.ts +6 -4
- package/dist/store/index.js +5 -3
- package/dist/store/internal.d.ts +4 -1
- package/dist/store/internal.js +4 -1
- package/dist/store/primitive-predicates.d.ts +19 -0
- package/dist/store/primitive-predicates.d.ts.map +1 -0
- package/dist/store/primitive-predicates.js +19 -0
- package/dist/store/primitive-predicates.js.map +1 -0
- package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/attachment-runtime-client.js +18 -11
- package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/handle-runtime-action.d.ts +5 -0
- package/dist/store/runtime-clients/handle-runtime-action.d.ts.map +1 -0
- package/dist/store/runtime-clients/handle-runtime-action.js +12 -0
- package/dist/store/runtime-clients/handle-runtime-action.js.map +1 -0
- package/dist/store/runtime-clients/handle-thread-list-action.d.ts +5 -0
- package/dist/store/runtime-clients/handle-thread-list-action.d.ts.map +1 -0
- package/dist/store/runtime-clients/handle-thread-list-action.js +7 -0
- package/dist/store/runtime-clients/handle-thread-list-action.js.map +1 -0
- package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js +104 -57
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js +5 -6
- package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +98 -82
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scope-registration.d.ts +2 -2
- package/dist/store/scopes/composer.d.ts +9 -4
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/suggestions.d.ts +6 -1
- package/dist/store/scopes/suggestions.d.ts.map +1 -1
- package/dist/store/scopes/thread-list-item.d.ts +7 -6
- package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
- package/dist/store/scopes/thread.d.ts +25 -7
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/dist/store/scopes/threads.d.ts +17 -1
- package/dist/store/scopes/threads.d.ts.map +1 -1
- package/dist/subscribable/subscribable.d.ts +2 -1
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/subscribable/subscribable.js +23 -18
- package/dist/subscribable/subscribable.js.map +1 -1
- package/dist/types/error.d.ts +15 -1
- package/dist/types/error.d.ts.map +1 -1
- package/dist/types/error.js +18 -1
- package/dist/types/error.js.map +1 -1
- package/dist/types/message.d.ts +2 -0
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js.map +1 -1
- package/dist/utils/composite-context-provider.d.ts +1 -0
- package/dist/utils/composite-context-provider.d.ts.map +1 -1
- package/dist/utils/composite-context-provider.js +25 -9
- package/dist/utils/composite-context-provider.js.map +1 -1
- package/dist/utils/notify-event-listeners.d.ts +2 -2
- package/dist/utils/notify-event-listeners.d.ts.map +1 -1
- package/dist/utils/notify-event-listeners.js +2 -2
- package/dist/utils/notify-event-listeners.js.map +1 -1
- package/package.json +7 -7
- package/src/adapters/speech.test.ts +118 -1
- package/src/adapters/speech.ts +21 -22
- package/src/adapters/thread-history.ts +2 -0
- package/src/adapters/voice.test.ts +69 -0
- package/src/adapters/voice.ts +27 -27
- package/src/index.ts +2 -0
- package/src/model-context/frame/host.test.ts +23 -0
- package/src/model-context/frame/host.ts +2 -1
- package/src/model-context/registry.test.ts +131 -0
- package/src/model-context/registry.ts +16 -6
- package/src/react/RuntimeAdapter.test.ts +2 -0
- package/src/react/RuntimeAdapter.ts +20 -8
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +34 -17
- package/src/react/client/AdaptedRemoteThread.ts +41 -0
- package/src/react/client/InMemoryThreadList.test.tsx +148 -0
- package/src/react/client/InMemoryThreadList.ts +290 -0
- package/src/react/client/Interactables.test.ts +326 -2
- package/src/react/client/Interactables.ts +227 -110
- package/src/react/client/RemoteThreadList.test.ts +1026 -0
- package/src/react/client/RemoteThreadList.ts +1067 -0
- package/src/react/client/Tools.ts +36 -29
- package/src/react/client/interactable-model-context.ts +6 -1
- package/src/react/index.ts +13 -0
- package/src/react/interactables-legacy/Interactables.test.ts +317 -0
- package/src/react/interactables-legacy/Interactables.ts +204 -128
- package/src/react/primitive-hooks/useActionBarCopy.ts +2 -7
- package/src/react/primitive-hooks/useActionBarEdit.ts +2 -1
- package/src/react/primitive-hooks/useActionBarReload.ts +2 -6
- package/src/react/primitive-hooks/useBranchPickerNext.ts +2 -7
- package/src/react/primitive-hooks/useBranchPickerPrevious.ts +2 -7
- package/src/react/primitive-hooks/useComposerCancel.ts +2 -1
- package/src/react/primitive-hooks/useComposerSend.ts +2 -5
- package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +11 -0
- package/src/react/primitive-hooks/useSuggestionTrigger.ts +4 -5
- package/src/react/primitives/message/MessageParts.tsx +0 -1
- package/src/react/primitives/thread/ThreadMessages.tsx +2 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.retry.test.tsx +116 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +1 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +57 -6
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.title.test.tsx +272 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +159 -124
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +59 -20
- package/src/react/runtimes/RemoteThreadResource.test.ts +141 -0
- package/src/react/runtimes/RemoteThreadResource.ts +231 -0
- package/src/react/runtimes/RuntimeAdapterProvider.tsx +8 -20
- package/src/react/runtimes/assistant-transport/commandQueue.ts +68 -0
- package/src/react/runtimes/assistant-transport/replayBoundaryStream.test.ts +455 -0
- package/src/react/runtimes/assistant-transport/replayBoundaryStream.ts +172 -0
- package/src/react/runtimes/assistant-transport/runManager.ts +124 -0
- package/src/react/runtimes/assistant-transport/transport-delivery.test.tsx +79 -0
- package/src/react/runtimes/assistant-transport/transport-parentid.test.tsx +97 -0
- package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +414 -0
- package/src/react/runtimes/assistant-transport/types.ts +170 -0
- package/src/react/runtimes/assistant-transport/useAssistantTransport.spec.md +141 -0
- package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.test.tsx +625 -0
- package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +481 -0
- package/src/react/runtimes/assistant-transport/useConvertedState.ts +20 -0
- package/src/react/runtimes/assistant-transport/useLatestRef.ts +9 -0
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +131 -6
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +61 -15
- package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +6 -4
- package/src/react/runtimes/cloud/auiV0.ts +17 -1
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +36 -21
- package/src/react/runtimes/cloud/useCloudThreadListRuntime.test.tsx +56 -0
- package/src/react/runtimes/cloud/useCloudThreadListRuntime.ts +31 -0
- package/src/react/runtimes/external-message-converter.test.ts +143 -0
- package/src/react/runtimes/external-message-converter.ts +41 -41
- package/src/react/runtimes/remote-thread-hook-on-tap.test.ts +58 -0
- package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +83 -0
- package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +124 -0
- package/src/react/runtimes/useExternalStoreRuntime.ts +7 -0
- package/src/react/runtimes/useExternalStoreSharedOptions.ts +3 -1
- package/src/react/runtimes/useLocalRuntime.test.tsx +130 -4
- package/src/react/runtimes/useRuntimeAdapters.test.tsx +62 -0
- package/src/react/runtimes/useRuntimeAdapters.ts +28 -0
- package/src/runtime/api/composer-runtime.ts +5 -0
- package/src/runtime/api/thread-list-runtime.ts +3 -1
- package/src/runtime/api/thread-runtime.ts +28 -3
- package/src/runtime/base/base-composer-runtime-core.ts +106 -13
- package/src/runtime/base/base-thread-runtime-core.test.ts +191 -0
- package/src/runtime/base/base-thread-runtime-core.ts +47 -2
- package/src/runtime/base/default-edit-composer-runtime-core.ts +1 -15
- package/src/runtime/base/default-thread-composer-runtime-core.ts +13 -15
- package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
- package/src/runtime/queue/external-thread-queue-adapter.ts +17 -0
- package/src/runtime/queue/message-queue.ts +28 -10
- package/src/runtime/utils/thread-runtime-lifecycle.ts +18 -0
- package/src/runtimes/external-store/external-store-adapter.ts +7 -0
- package/src/runtimes/external-store/external-store-shared-options.ts +3 -1
- package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +187 -48
- package/src/runtimes/local/local-thread-runtime-core.test.ts +373 -4
- package/src/runtimes/local/local-thread-runtime-core.ts +83 -15
- package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +4 -0
- package/src/runtimes/remote-thread-list/empty-thread-core.ts +4 -0
- package/src/runtimes/remote-thread-list/types.ts +30 -0
- package/src/runtimes/tool-invocations/EDGE_CASES.md +17 -6
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +243 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +127 -61
- package/src/store/clients/external-thread.ts +119 -16
- package/src/store/clients/model-context-client.test.ts +16 -8
- package/src/store/clients/runtime-adapter.ts +5 -2
- package/src/store/clients/single-thread-list.ts +2 -1
- package/src/store/clients/suggestions.ts +39 -13
- package/src/store/clients/thread-selection-events.ts +21 -0
- package/src/store/env.ts +11 -0
- package/src/store/index.ts +14 -1
- package/src/store/internal.ts +13 -0
- package/src/store/primitive-predicates.test.ts +184 -0
- package/src/store/primitive-predicates.ts +43 -0
- package/src/store/runtime-clients/attachment-runtime-client.test.ts +41 -0
- package/src/store/runtime-clients/attachment-runtime-client.ts +2 -1
- package/src/store/runtime-clients/handle-runtime-action.ts +11 -0
- package/src/store/runtime-clients/handle-thread-list-action.test.ts +69 -0
- package/src/store/runtime-clients/handle-thread-list-action.ts +6 -0
- package/src/store/runtime-clients/thread-list-item-runtime-client.ts +28 -35
- package/src/store/runtime-clients/thread-list-runtime-client.ts +9 -6
- package/src/store/runtime-clients/thread-runtime-client.ts +5 -0
- package/src/store/scopes/composer.ts +9 -4
- package/src/store/scopes/suggestions.ts +6 -0
- package/src/store/scopes/thread-list-item.ts +7 -6
- package/src/store/scopes/thread.ts +25 -7
- package/src/store/scopes/threads.ts +14 -0
- package/src/subscribable/subscribable.test.ts +77 -1
- package/src/subscribable/subscribable.ts +38 -23
- package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-unarchive.test.ts +25 -0
- package/src/tests/append-interactable-snapshots.test.ts +350 -0
- package/src/tests/auiV0Encode.test.ts +66 -0
- package/src/tests/base-composer-runtime-core-send.test.ts +156 -0
- package/src/tests/base-composer-runtime-core.test.ts +136 -1
- package/src/tests/composer-can-cancel.test.ts +101 -0
- package/src/tests/default-edit-composer-runtime-core.test.ts +0 -68
- package/src/tests/external-store-thread-list-runtime-core.test.ts +101 -0
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +491 -1
- package/src/tests/external-store-thread-runtime-core.test.ts +124 -0
- package/src/tests/external-thread-attachments.test.tsx +214 -0
- package/src/tests/external-thread-parity.test.tsx +54 -0
- package/src/tests/external-thread-refetch.test.tsx +117 -0
- package/src/tests/external-thread-suggestions.test.tsx +59 -0
- package/src/tests/interactables-toolui-migration.test.tsx +66 -0
- package/src/tests/message-queue.test.ts +54 -0
- package/src/tests/session-reset-notification.test.ts +145 -0
- package/src/tests/thread-message-like.test.ts +39 -0
- package/src/tests/thread-switch-events.test.tsx +234 -0
- package/src/tests/tools-scope-migration.test.tsx +58 -0
- package/src/types/error.ts +24 -0
- package/src/types/message.ts +2 -0
- package/src/utils/composite-context-provider.test.ts +139 -0
- package/src/utils/composite-context-provider.ts +26 -8
- package/src/utils/notify-event-listeners.ts +10 -5
- package/src/tests/default-thread-composer-runtime-core.test.ts +0 -82
|
@@ -3,6 +3,8 @@ import { DefaultThreadComposerRuntimeCore } from "../runtime/base/default-thread
|
|
|
3
3
|
import type { AttachmentAdapter } from "../adapters/attachment";
|
|
4
4
|
import type { ThreadRuntimeCore } from "../runtime/interfaces/thread-runtime-core";
|
|
5
5
|
import type { PendingAttachment } from "../types/attachment";
|
|
6
|
+
import { MessageNotSentError } from "../types/error";
|
|
7
|
+
import { BaseComposerRuntimeCore } from "../runtime/base/base-composer-runtime-core";
|
|
6
8
|
|
|
7
9
|
const makeAdapter = (
|
|
8
10
|
overrides: Partial<AttachmentAdapter> = {},
|
|
@@ -156,6 +158,36 @@ describe("BaseComposerRuntimeCore.send restore-on-failure", () => {
|
|
|
156
158
|
expect(append).toHaveBeenCalledTimes(1);
|
|
157
159
|
});
|
|
158
160
|
|
|
161
|
+
it("snapshots role and run config before uploading attachments", async () => {
|
|
162
|
+
let resolveSend!: () => void;
|
|
163
|
+
const adapter = makeAdapter({
|
|
164
|
+
send: (a) =>
|
|
165
|
+
new Promise((resolve) => {
|
|
166
|
+
resolveSend = () =>
|
|
167
|
+
resolve({ ...a, status: { type: "complete" }, content: [] });
|
|
168
|
+
}),
|
|
169
|
+
});
|
|
170
|
+
const { composer, append } = makeComposer(adapter);
|
|
171
|
+
|
|
172
|
+
composer.setText("hello");
|
|
173
|
+
composer.setRole("assistant");
|
|
174
|
+
composer.setRunConfig({ custom: { modelName: "model-a" } });
|
|
175
|
+
await composer.addAttachment(textFile());
|
|
176
|
+
|
|
177
|
+
const sendPromise = composer.send();
|
|
178
|
+
composer.setRole("system");
|
|
179
|
+
composer.setRunConfig({ custom: { modelName: "model-b" } });
|
|
180
|
+
resolveSend();
|
|
181
|
+
await sendPromise;
|
|
182
|
+
|
|
183
|
+
expect(append).toHaveBeenCalledWith(
|
|
184
|
+
expect.objectContaining({
|
|
185
|
+
role: "assistant",
|
|
186
|
+
runConfig: { custom: { modelName: "model-a" } },
|
|
187
|
+
}),
|
|
188
|
+
);
|
|
189
|
+
});
|
|
190
|
+
|
|
159
191
|
it("keeps an attachment added while the upload was in flight", async () => {
|
|
160
192
|
let resolveSend!: () => void;
|
|
161
193
|
const adapter = makeAdapter({
|
|
@@ -571,3 +603,127 @@ describe("BaseComposerRuntimeCore send event listener isolation", () => {
|
|
|
571
603
|
});
|
|
572
604
|
});
|
|
573
605
|
});
|
|
606
|
+
|
|
607
|
+
describe("BaseComposerRuntimeCore.send restore-on-undispatched", () => {
|
|
608
|
+
const rejectableAppend = () => {
|
|
609
|
+
let reject!: (error: unknown) => void;
|
|
610
|
+
const append = vi.fn(
|
|
611
|
+
() =>
|
|
612
|
+
new Promise<void>((_resolve, rejectAppend) => {
|
|
613
|
+
reject = rejectAppend;
|
|
614
|
+
}),
|
|
615
|
+
);
|
|
616
|
+
return { append, reject: (error: unknown) => reject(error) };
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
it("restores text, quote, and attachments when the message was never sent", async () => {
|
|
620
|
+
const { append, reject } = rejectableAppend();
|
|
621
|
+
const { composer } = makeComposer(makeAdapter(), append);
|
|
622
|
+
|
|
623
|
+
composer.setText("hello");
|
|
624
|
+
await composer.addAttachment(textFile());
|
|
625
|
+
composer.setQuote({ text: "quoted", messageId: "m-1" });
|
|
626
|
+
|
|
627
|
+
await composer.send();
|
|
628
|
+
expect(composer.text).toBe("");
|
|
629
|
+
expect(composer.attachments).toHaveLength(0);
|
|
630
|
+
|
|
631
|
+
reject(new MessageNotSentError());
|
|
632
|
+
|
|
633
|
+
await vi.waitFor(() => expect(composer.text).toBe("hello"));
|
|
634
|
+
expect(composer.quote).toEqual({ text: "quoted", messageId: "m-1" });
|
|
635
|
+
expect(composer.attachments).toHaveLength(1);
|
|
636
|
+
expect(composer.attachments[0]!.status).toEqual({ type: "complete" });
|
|
637
|
+
expect(append).toHaveBeenCalledTimes(1);
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
it("leaves the composer empty for any other rejection", async () => {
|
|
641
|
+
const { append, reject } = rejectableAppend();
|
|
642
|
+
const { composer } = makeComposer(makeAdapter(), append);
|
|
643
|
+
|
|
644
|
+
composer.setText("hello");
|
|
645
|
+
await composer.send();
|
|
646
|
+
reject(new Error("boom"));
|
|
647
|
+
|
|
648
|
+
await vi.waitFor(() => expect(append).toHaveBeenCalledTimes(1));
|
|
649
|
+
expect(composer.text).toBe("");
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
it("does not clobber a draft written after the send", async () => {
|
|
653
|
+
const { append, reject } = rejectableAppend();
|
|
654
|
+
const { composer } = makeComposer(makeAdapter(), append);
|
|
655
|
+
|
|
656
|
+
composer.setText("hello");
|
|
657
|
+
await composer.send();
|
|
658
|
+
composer.setText("new draft");
|
|
659
|
+
reject(new MessageNotSentError());
|
|
660
|
+
|
|
661
|
+
await vi.waitFor(() => expect(append).toHaveBeenCalledTimes(1));
|
|
662
|
+
expect(composer.text).toBe("new draft");
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
it("does not restore a draft a reset discarded", async () => {
|
|
666
|
+
const { append, reject } = rejectableAppend();
|
|
667
|
+
const { composer } = makeComposer(makeAdapter(), append);
|
|
668
|
+
|
|
669
|
+
composer.setText("hello");
|
|
670
|
+
await composer.send();
|
|
671
|
+
await composer.reset();
|
|
672
|
+
reject(new MessageNotSentError());
|
|
673
|
+
|
|
674
|
+
await vi.waitFor(() => expect(append).toHaveBeenCalledTimes(1));
|
|
675
|
+
expect(composer.text).toBe("");
|
|
676
|
+
});
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
describe("BaseComposerRuntimeCore.send restore-on-undispatched edge cases", () => {
|
|
680
|
+
class SyncThrowComposerCore extends BaseComposerRuntimeCore {
|
|
681
|
+
public readonly error = new MessageNotSentError();
|
|
682
|
+
public get canCancel() {
|
|
683
|
+
return false;
|
|
684
|
+
}
|
|
685
|
+
public get canSend() {
|
|
686
|
+
return true;
|
|
687
|
+
}
|
|
688
|
+
protected getAttachmentAdapter() {
|
|
689
|
+
return undefined;
|
|
690
|
+
}
|
|
691
|
+
protected getDictationAdapter() {
|
|
692
|
+
return undefined;
|
|
693
|
+
}
|
|
694
|
+
protected handleSend(): void {
|
|
695
|
+
throw this.error;
|
|
696
|
+
}
|
|
697
|
+
protected handleCancel(): void {}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
it("restores the draft when handleSend throws synchronously", async () => {
|
|
701
|
+
const composer = new SyncThrowComposerCore();
|
|
702
|
+
composer.setText("hello");
|
|
703
|
+
|
|
704
|
+
await expect(composer.send()).rejects.toThrow(composer.error);
|
|
705
|
+
|
|
706
|
+
expect(composer.text).toBe("hello");
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
it("restores only the most recent of several queued drafts", async () => {
|
|
710
|
+
const rejects: ((error: unknown) => void)[] = [];
|
|
711
|
+
const append = vi.fn(
|
|
712
|
+
() =>
|
|
713
|
+
new Promise<void>((_resolve, reject) => {
|
|
714
|
+
rejects.push(reject);
|
|
715
|
+
}),
|
|
716
|
+
);
|
|
717
|
+
const { composer } = makeComposer(makeAdapter(), append);
|
|
718
|
+
|
|
719
|
+
composer.setText("one");
|
|
720
|
+
await composer.send();
|
|
721
|
+
composer.setText("two");
|
|
722
|
+
await composer.send();
|
|
723
|
+
|
|
724
|
+
rejects[0]!(new MessageNotSentError());
|
|
725
|
+
rejects[1]!(new MessageNotSentError());
|
|
726
|
+
|
|
727
|
+
await vi.waitFor(() => expect(composer.text).toBe("two"));
|
|
728
|
+
});
|
|
729
|
+
});
|
|
@@ -14,8 +14,14 @@ class TestComposerCore extends BaseComposerRuntimeCore {
|
|
|
14
14
|
protected getAttachmentAdapter() {
|
|
15
15
|
return this._attachmentAdapter;
|
|
16
16
|
}
|
|
17
|
+
private _dictationAdapter: DictationAdapter | undefined;
|
|
18
|
+
|
|
17
19
|
protected getDictationAdapter(): DictationAdapter | undefined {
|
|
18
|
-
return
|
|
20
|
+
return this._dictationAdapter;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setDictationAdapter(adapter: DictationAdapter | undefined) {
|
|
24
|
+
this._dictationAdapter = adapter;
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
setAttachmentAdapter(adapter: AttachmentAdapter | undefined) {
|
|
@@ -180,6 +186,34 @@ describe("BaseComposerRuntimeCore", () => {
|
|
|
180
186
|
expect(composer.attachmentAccept).toBe("image/*");
|
|
181
187
|
});
|
|
182
188
|
|
|
189
|
+
it("handles rejected dictation shutdowns", async () => {
|
|
190
|
+
const session: DictationAdapter.Session = {
|
|
191
|
+
status: { type: "running" },
|
|
192
|
+
stop: vi.fn().mockRejectedValue(new Error("shutdown failed")),
|
|
193
|
+
cancel: vi.fn(),
|
|
194
|
+
onSpeechStart: vi.fn(() => () => {}),
|
|
195
|
+
onSpeechEnd: vi.fn(() => () => {}),
|
|
196
|
+
onSpeech: vi.fn(() => () => {}),
|
|
197
|
+
};
|
|
198
|
+
const unhandledRejection = vi.fn();
|
|
199
|
+
composer.setDictationAdapter({ listen: () => session });
|
|
200
|
+
process.on("unhandledRejection", unhandledRejection);
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
composer.startDictation();
|
|
204
|
+
expect(composer.dictation).toBeDefined();
|
|
205
|
+
|
|
206
|
+
composer.stopDictation();
|
|
207
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
208
|
+
|
|
209
|
+
expect(session.stop).toHaveBeenCalledOnce();
|
|
210
|
+
expect(composer.dictation).toBeUndefined();
|
|
211
|
+
expect(unhandledRejection).not.toHaveBeenCalled();
|
|
212
|
+
} finally {
|
|
213
|
+
process.off("unhandledRejection", unhandledRejection);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
183
217
|
describe("CreateAttachment (external source)", () => {
|
|
184
218
|
const makeCreateAttachment = (
|
|
185
219
|
overrides?: Partial<CreateAttachment>,
|
|
@@ -420,3 +454,104 @@ describe("BaseComposerRuntimeCore", () => {
|
|
|
420
454
|
});
|
|
421
455
|
});
|
|
422
456
|
});
|
|
457
|
+
|
|
458
|
+
describe("BaseComposerRuntimeCore.restoreDraft", () => {
|
|
459
|
+
it("refuses while the composer holds something of its own", () => {
|
|
460
|
+
const composer = new TestComposerCore();
|
|
461
|
+
composer.setText("mine");
|
|
462
|
+
|
|
463
|
+
expect(composer.restoreDraft({ text: "returned" })).toBe(false);
|
|
464
|
+
expect(composer.text).toBe("mine");
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
it("rebases a live dictation session onto the restored text", () => {
|
|
468
|
+
let emitSpeech!: (result: { transcript: string }) => void;
|
|
469
|
+
const composer = new TestComposerCore();
|
|
470
|
+
composer.setDictationAdapter({
|
|
471
|
+
listen: () => ({
|
|
472
|
+
status: { type: "running" },
|
|
473
|
+
stop: async () => {},
|
|
474
|
+
cancel: () => {},
|
|
475
|
+
onSpeechStart: () => () => {},
|
|
476
|
+
onSpeechEnd: () => () => {},
|
|
477
|
+
onSpeech: (callback) => {
|
|
478
|
+
emitSpeech = callback;
|
|
479
|
+
return () => {};
|
|
480
|
+
},
|
|
481
|
+
}),
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
composer.startDictation();
|
|
485
|
+
expect(composer.restoreDraft({ text: "returned" })).toBe(true);
|
|
486
|
+
emitSpeech({ transcript: "and this" });
|
|
487
|
+
|
|
488
|
+
expect(composer.text).toBe("returned and this");
|
|
489
|
+
});
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
describe("BaseComposerRuntimeCore.retractDraft", () => {
|
|
493
|
+
const makeCompleteAttachment = (id: string) => ({
|
|
494
|
+
id,
|
|
495
|
+
type: "file" as const,
|
|
496
|
+
name: "spec.pdf",
|
|
497
|
+
contentType: "application/pdf",
|
|
498
|
+
status: { type: "complete" as const },
|
|
499
|
+
content: [],
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
it("clears the composer while it still holds the exact draft", () => {
|
|
503
|
+
const composer = new TestComposerCore();
|
|
504
|
+
const draft = {
|
|
505
|
+
text: "returned",
|
|
506
|
+
quote: { text: "quoted", messageId: "m-1" },
|
|
507
|
+
attachments: [makeCompleteAttachment("a1")],
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
expect(composer.restoreDraft(draft)).toBe(true);
|
|
511
|
+
composer.retractDraft(draft);
|
|
512
|
+
|
|
513
|
+
expect(composer.text).toBe("");
|
|
514
|
+
expect(composer.quote).toBeUndefined();
|
|
515
|
+
expect(composer.attachments).toEqual([]);
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
it("leaves an edited text alone", () => {
|
|
519
|
+
const composer = new TestComposerCore();
|
|
520
|
+
const draft = { text: "returned" };
|
|
521
|
+
|
|
522
|
+
expect(composer.restoreDraft(draft)).toBe(true);
|
|
523
|
+
composer.setText("edited");
|
|
524
|
+
composer.retractDraft(draft);
|
|
525
|
+
|
|
526
|
+
expect(composer.text).toBe("edited");
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
it("leaves a changed quote alone", () => {
|
|
530
|
+
const composer = new TestComposerCore();
|
|
531
|
+
const draft = { text: "returned", quote: { text: "quoted" } };
|
|
532
|
+
|
|
533
|
+
expect(composer.restoreDraft(draft)).toBe(true);
|
|
534
|
+
composer.setQuote({ text: "other" });
|
|
535
|
+
composer.retractDraft(draft);
|
|
536
|
+
|
|
537
|
+
expect(composer.text).toBe("returned");
|
|
538
|
+
expect(composer.quote).toEqual({ text: "other" });
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
it("leaves changed attachments alone", () => {
|
|
542
|
+
const composer = new TestComposerCore();
|
|
543
|
+
const draft = {
|
|
544
|
+
text: "returned",
|
|
545
|
+
attachments: [makeCompleteAttachment("a1")],
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
expect(composer.restoreDraft(draft)).toBe(true);
|
|
549
|
+
composer.retractDraft({
|
|
550
|
+
...draft,
|
|
551
|
+
attachments: [makeCompleteAttachment("a1")],
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
expect(composer.text).toBe("returned");
|
|
555
|
+
expect(composer.attachments).toHaveLength(1);
|
|
556
|
+
});
|
|
557
|
+
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { DefaultThreadComposerRuntimeCore } from "../runtime/base/default-thread-composer-runtime-core";
|
|
3
|
+
import type { ThreadRuntimeCore } from "../runtime/interfaces/thread-runtime-core";
|
|
4
|
+
import type { ThreadMessage } from "../types/message";
|
|
5
|
+
|
|
6
|
+
type ThreadRuntimeStub = Omit<ThreadRuntimeCore, "composer"> & {
|
|
7
|
+
notify: () => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const makeRuntimeStub = (
|
|
11
|
+
overrides: Partial<ThreadRuntimeCore> = {},
|
|
12
|
+
): ThreadRuntimeStub => {
|
|
13
|
+
const subscribers = new Set<() => void>();
|
|
14
|
+
return {
|
|
15
|
+
append: vi.fn(),
|
|
16
|
+
cancelRun: vi.fn(),
|
|
17
|
+
getModelContext: () => ({}),
|
|
18
|
+
subscribe: (cb: () => void) => {
|
|
19
|
+
subscribers.add(cb);
|
|
20
|
+
return () => subscribers.delete(cb);
|
|
21
|
+
},
|
|
22
|
+
capabilities: { cancel: true },
|
|
23
|
+
messages: [],
|
|
24
|
+
isDisabled: false,
|
|
25
|
+
isSendDisabled: false,
|
|
26
|
+
isLoading: false,
|
|
27
|
+
composer: { runConfig: {} },
|
|
28
|
+
notify: () => {
|
|
29
|
+
for (const cb of subscribers) cb();
|
|
30
|
+
},
|
|
31
|
+
...overrides,
|
|
32
|
+
} as unknown as ThreadRuntimeStub;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const runningAssistant = {
|
|
36
|
+
id: "a1",
|
|
37
|
+
role: "assistant",
|
|
38
|
+
status: { type: "running" },
|
|
39
|
+
} as ThreadMessage;
|
|
40
|
+
|
|
41
|
+
describe("DefaultThreadComposerRuntimeCore.canCancel", () => {
|
|
42
|
+
it("is false when the runtime is idle even if cancel is supported", () => {
|
|
43
|
+
const composer = new DefaultThreadComposerRuntimeCore(makeRuntimeStub());
|
|
44
|
+
expect(composer.canCancel).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("is false when cancel is not a capability", () => {
|
|
48
|
+
const composer = new DefaultThreadComposerRuntimeCore(
|
|
49
|
+
makeRuntimeStub({
|
|
50
|
+
capabilities: { cancel: false },
|
|
51
|
+
isRunning: true,
|
|
52
|
+
}),
|
|
53
|
+
);
|
|
54
|
+
expect(composer.canCancel).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("is true while the runtime reports isRunning", () => {
|
|
58
|
+
const composer = new DefaultThreadComposerRuntimeCore(
|
|
59
|
+
makeRuntimeStub({ isRunning: true }),
|
|
60
|
+
);
|
|
61
|
+
expect(composer.canCancel).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("is true while the trailing assistant message is running", () => {
|
|
65
|
+
const composer = new DefaultThreadComposerRuntimeCore(
|
|
66
|
+
makeRuntimeStub({ messages: [runningAssistant] }),
|
|
67
|
+
);
|
|
68
|
+
expect(composer.canCancel).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("stays false after a runtime notify while idle", () => {
|
|
72
|
+
const stub = makeRuntimeStub();
|
|
73
|
+
const composer = new DefaultThreadComposerRuntimeCore(stub);
|
|
74
|
+
stub.notify();
|
|
75
|
+
expect(composer.canCancel).toBe(false);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("notifies subscribers when a run starts", () => {
|
|
79
|
+
const stub = makeRuntimeStub();
|
|
80
|
+
const composer = new DefaultThreadComposerRuntimeCore(stub);
|
|
81
|
+
const onChange = vi.fn();
|
|
82
|
+
composer.subscribe(onChange);
|
|
83
|
+
|
|
84
|
+
(stub as { isRunning?: boolean }).isRunning = true;
|
|
85
|
+
stub.notify();
|
|
86
|
+
|
|
87
|
+
expect(onChange).toHaveBeenCalled();
|
|
88
|
+
expect(composer.canCancel).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("returns to false when the run ends", () => {
|
|
92
|
+
const stub = makeRuntimeStub({ isRunning: true });
|
|
93
|
+
const composer = new DefaultThreadComposerRuntimeCore(stub);
|
|
94
|
+
expect(composer.canCancel).toBe(true);
|
|
95
|
+
|
|
96
|
+
(stub as { isRunning?: boolean }).isRunning = false;
|
|
97
|
+
stub.notify();
|
|
98
|
+
|
|
99
|
+
expect(composer.canCancel).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
@@ -229,74 +229,6 @@ describe("DefaultEditComposerRuntimeCore", () => {
|
|
|
229
229
|
});
|
|
230
230
|
});
|
|
231
231
|
|
|
232
|
-
describe("interactables snapshot gating", () => {
|
|
233
|
-
const live = (state: unknown) => ({
|
|
234
|
-
interactables: [{ id: "n1", name: "note", state }],
|
|
235
|
-
});
|
|
236
|
-
const snapshotMessage = (id: string, state: unknown): ThreadMessage =>
|
|
237
|
-
makeUserMessage({
|
|
238
|
-
id,
|
|
239
|
-
metadata: {
|
|
240
|
-
custom: { interactables: [{ id: "n1", name: "note", state }] },
|
|
241
|
-
},
|
|
242
|
-
} as Partial<ThreadMessage>);
|
|
243
|
-
|
|
244
|
-
it("re-stamps the baseline when the edited message carried the only snapshot", async () => {
|
|
245
|
-
// The new branch's prefix (before the edited message) has no snapshot,
|
|
246
|
-
// so the live (unchanged) state becomes the branch's baseline.
|
|
247
|
-
const edited = snapshotMessage("msg-1", { v: 1 });
|
|
248
|
-
const { runtime, append } = makeRuntime({
|
|
249
|
-
messages: [edited],
|
|
250
|
-
composerMetadata: live({ v: 1 }),
|
|
251
|
-
});
|
|
252
|
-
const composer = new DefaultEditComposerRuntimeCore(runtime, () => {}, {
|
|
253
|
-
parentId: null,
|
|
254
|
-
message: edited,
|
|
255
|
-
});
|
|
256
|
-
composer.setText("new");
|
|
257
|
-
await composer.send();
|
|
258
|
-
const appended = append.mock.calls[0]![0] as AppendMessage;
|
|
259
|
-
expect(appended.metadata?.custom?.interactables).toEqual([
|
|
260
|
-
{ id: "n1", name: "note", state: { v: 1 } },
|
|
261
|
-
]);
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it("stamps the newest live state when the interactable was edited after the original message", async () => {
|
|
265
|
-
const edited = snapshotMessage("msg-1", { v: 1 });
|
|
266
|
-
const { runtime, append } = makeRuntime({
|
|
267
|
-
messages: [edited],
|
|
268
|
-
composerMetadata: live({ v: 2 }),
|
|
269
|
-
});
|
|
270
|
-
const composer = new DefaultEditComposerRuntimeCore(runtime, () => {}, {
|
|
271
|
-
parentId: null,
|
|
272
|
-
message: edited,
|
|
273
|
-
});
|
|
274
|
-
composer.setText("new");
|
|
275
|
-
await composer.send();
|
|
276
|
-
const appended = append.mock.calls[0]![0] as AppendMessage;
|
|
277
|
-
expect(appended.metadata?.custom?.interactables).toEqual([
|
|
278
|
-
{ id: "n1", name: "note", state: { v: 2 } },
|
|
279
|
-
]);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it("stamps nothing when the branch prefix already carries the live state", async () => {
|
|
283
|
-
const parent = snapshotMessage("parent-1", { v: 1 });
|
|
284
|
-
const edited = makeUserMessage({ id: "msg-1" });
|
|
285
|
-
const { runtime, append } = makeRuntime({
|
|
286
|
-
messages: [parent, edited],
|
|
287
|
-
composerMetadata: live({ v: 1 }),
|
|
288
|
-
});
|
|
289
|
-
const composer = new DefaultEditComposerRuntimeCore(runtime, () => {}, {
|
|
290
|
-
parentId: "parent-1",
|
|
291
|
-
message: edited,
|
|
292
|
-
});
|
|
293
|
-
composer.setText("new");
|
|
294
|
-
await composer.send();
|
|
295
|
-
const appended = append.mock.calls[0]![0] as AppendMessage;
|
|
296
|
-
expect(appended.metadata?.custom?.interactables).toBeUndefined();
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
|
|
300
232
|
describe("non-user messages", () => {
|
|
301
233
|
it("does not lift non-text parts for assistant messages", () => {
|
|
302
234
|
const { runtime } = makeRuntime();
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
2
|
import { ExternalStoreThreadListRuntimeCore } from "../runtimes/external-store/external-store-thread-list-runtime-core";
|
|
3
3
|
import type { ExternalStoreThreadRuntimeCore } from "../runtimes/external-store/external-store-thread-runtime-core";
|
|
4
|
+
import { ExternalStoreThreadRuntimeCore as ExternalStoreThreadRuntimeCoreImpl } from "../runtimes/external-store/external-store-thread-runtime-core";
|
|
4
5
|
import type { ExternalStoreThreadListAdapter } from "../runtimes/external-store/external-store-adapter";
|
|
6
|
+
import type { ExternalStoreAdapter } from "../runtimes/external-store/external-store-adapter";
|
|
7
|
+
import type { ModelContextProvider } from "../model-context/types";
|
|
5
8
|
import { ThreadListRuntimeImpl } from "../runtime/api/thread-list-runtime";
|
|
6
9
|
|
|
7
10
|
const makeFactory = (overrides: Record<string, unknown> = {}) =>
|
|
@@ -18,6 +21,21 @@ const makeAdapter = (
|
|
|
18
21
|
overrides: Partial<ExternalStoreThreadListAdapter> = {},
|
|
19
22
|
): ExternalStoreThreadListAdapter => ({ ...overrides });
|
|
20
23
|
|
|
24
|
+
const mockContextProvider: ModelContextProvider = {
|
|
25
|
+
getModelContext: () => ({}),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const appendMessage = () => ({
|
|
29
|
+
parentId: null,
|
|
30
|
+
sourceId: null,
|
|
31
|
+
runConfig: {},
|
|
32
|
+
role: "user" as const,
|
|
33
|
+
content: [{ type: "text" as const, text: "hello" }],
|
|
34
|
+
attachments: [],
|
|
35
|
+
metadata: { custom: {} },
|
|
36
|
+
createdAt: new Date(0),
|
|
37
|
+
});
|
|
38
|
+
|
|
21
39
|
describe("ExternalStoreThreadListRuntimeCore - construction", () => {
|
|
22
40
|
it("assigns a resolvable fallback mainThreadId when adapter has no threadId", () => {
|
|
23
41
|
const core = new ExternalStoreThreadListRuntimeCore(
|
|
@@ -149,6 +167,26 @@ describe("ExternalStoreThreadListRuntimeCore - __internal_setAdapter", () => {
|
|
|
149
167
|
expect(callback).toHaveBeenCalled();
|
|
150
168
|
});
|
|
151
169
|
|
|
170
|
+
it("notifies later subscribers when an earlier subscriber throws", () => {
|
|
171
|
+
const core = new ExternalStoreThreadListRuntimeCore(
|
|
172
|
+
makeAdapter({ threadId: "thread-alpha" }),
|
|
173
|
+
makeFactory(),
|
|
174
|
+
);
|
|
175
|
+
const error = new Error("subscriber failed");
|
|
176
|
+
const laterSubscriber = vi.fn();
|
|
177
|
+
|
|
178
|
+
core.subscribe(() => {
|
|
179
|
+
throw error;
|
|
180
|
+
});
|
|
181
|
+
core.subscribe(laterSubscriber);
|
|
182
|
+
|
|
183
|
+
expect(() =>
|
|
184
|
+
core.__internal_setAdapter(makeAdapter({ threadId: "thread-beta" })),
|
|
185
|
+
).toThrow(error);
|
|
186
|
+
expect(core.mainThreadId).toBe("thread-beta");
|
|
187
|
+
expect(laterSubscriber).toHaveBeenCalledOnce();
|
|
188
|
+
});
|
|
189
|
+
|
|
152
190
|
it("synthesizes mainThreadId entry after a switch to a threadId not in the threads list", () => {
|
|
153
191
|
const core = new ExternalStoreThreadListRuntimeCore(
|
|
154
192
|
makeAdapter({ threadId: "thread-alpha" }),
|
|
@@ -175,6 +213,69 @@ describe("ExternalStoreThreadListRuntimeCore - __internal_setAdapter", () => {
|
|
|
175
213
|
"thread-gamma",
|
|
176
214
|
]);
|
|
177
215
|
});
|
|
216
|
+
|
|
217
|
+
it("dispatches an append before a thread switch", async () => {
|
|
218
|
+
let resolveInitialization!: () => void;
|
|
219
|
+
const initialization = new Promise<void>((resolve) => {
|
|
220
|
+
resolveInitialization = resolve;
|
|
221
|
+
});
|
|
222
|
+
const onNew = vi.fn(async () => {});
|
|
223
|
+
const firstRuntime = new ExternalStoreThreadRuntimeCoreImpl(
|
|
224
|
+
mockContextProvider,
|
|
225
|
+
{ messages: [], onNew } as ExternalStoreAdapter,
|
|
226
|
+
);
|
|
227
|
+
firstRuntime.__internal_setGetInitializePromise(() => initialization);
|
|
228
|
+
const secondRuntime = new ExternalStoreThreadRuntimeCoreImpl(
|
|
229
|
+
mockContextProvider,
|
|
230
|
+
{ messages: [], onNew: vi.fn() } as ExternalStoreAdapter,
|
|
231
|
+
);
|
|
232
|
+
const factory = vi
|
|
233
|
+
.fn()
|
|
234
|
+
.mockReturnValueOnce(firstRuntime)
|
|
235
|
+
.mockReturnValueOnce(secondRuntime);
|
|
236
|
+
const core = new ExternalStoreThreadListRuntimeCore(
|
|
237
|
+
makeAdapter({ threadId: "thread-alpha" }),
|
|
238
|
+
factory,
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const appendPromise = firstRuntime.append(appendMessage());
|
|
242
|
+
await Promise.resolve();
|
|
243
|
+
|
|
244
|
+
expect(onNew).toHaveBeenCalledTimes(1);
|
|
245
|
+
|
|
246
|
+
core.__internal_setAdapter(makeAdapter({ threadId: "thread-beta" }));
|
|
247
|
+
resolveInitialization();
|
|
248
|
+
|
|
249
|
+
await appendPromise;
|
|
250
|
+
expect(onNew).toHaveBeenCalledTimes(1);
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
describe("ExternalStoreThreadListRuntimeCore - detach", () => {
|
|
255
|
+
it("leaves the main thread's pending append alone when an item detaches", async () => {
|
|
256
|
+
let resolveInitialization!: () => void;
|
|
257
|
+
const initialization = new Promise<void>((resolve) => {
|
|
258
|
+
resolveInitialization = resolve;
|
|
259
|
+
});
|
|
260
|
+
const onNew = vi.fn(async () => {});
|
|
261
|
+
const runtime = new ExternalStoreThreadRuntimeCoreImpl(
|
|
262
|
+
mockContextProvider,
|
|
263
|
+
{ messages: [], onNew } as ExternalStoreAdapter,
|
|
264
|
+
);
|
|
265
|
+
runtime.__internal_setGetInitializePromise(() => initialization);
|
|
266
|
+
const core = new ExternalStoreThreadListRuntimeCore(
|
|
267
|
+
makeAdapter(),
|
|
268
|
+
vi.fn(() => runtime),
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
const appendPromise = runtime.append(appendMessage());
|
|
272
|
+
await Promise.resolve();
|
|
273
|
+
await core.detach();
|
|
274
|
+
resolveInitialization();
|
|
275
|
+
|
|
276
|
+
await appendPromise;
|
|
277
|
+
expect(onNew).toHaveBeenCalledTimes(1);
|
|
278
|
+
});
|
|
178
279
|
});
|
|
179
280
|
|
|
180
281
|
describe("ExternalStoreThreadListRuntimeCore - isMain via ThreadListRuntimeImpl", () => {
|