@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
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { StrictMode } from "react";
|
|
4
|
+
import { act, render } from "@testing-library/react";
|
|
5
|
+
import { describe, expect, it, vi } from "vitest";
|
|
6
|
+
import { useExternalStoreRuntime } from "./useExternalStoreRuntime";
|
|
7
|
+
import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
|
|
8
|
+
|
|
9
|
+
describe("useExternalStoreRuntime lifecycle", () => {
|
|
10
|
+
it("keeps dispatching appends after StrictMode's simulated remount", async () => {
|
|
11
|
+
const onNew = vi.fn(async () => {});
|
|
12
|
+
const capture: { runtime: AssistantRuntime | null } = { runtime: null };
|
|
13
|
+
const App = () => {
|
|
14
|
+
const runtime = useExternalStoreRuntime({ messages: [], onNew });
|
|
15
|
+
capture.runtime = runtime;
|
|
16
|
+
return null;
|
|
17
|
+
};
|
|
18
|
+
render(
|
|
19
|
+
<StrictMode>
|
|
20
|
+
<App />
|
|
21
|
+
</StrictMode>,
|
|
22
|
+
);
|
|
23
|
+
expect(capture.runtime).not.toBeNull();
|
|
24
|
+
|
|
25
|
+
await act(async () => {
|
|
26
|
+
await capture.runtime!.thread.append({
|
|
27
|
+
role: "user",
|
|
28
|
+
content: [{ type: "text", text: "hello" }],
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
expect(onNew).toHaveBeenCalledTimes(1);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("dispatches an append before unmount", async () => {
|
|
36
|
+
let resolveInitialization!: () => void;
|
|
37
|
+
const initialization = new Promise<void>((resolve) => {
|
|
38
|
+
resolveInitialization = resolve;
|
|
39
|
+
});
|
|
40
|
+
const onNew = vi.fn(async () => {});
|
|
41
|
+
const capture: { runtime: AssistantRuntime | null } = { runtime: null };
|
|
42
|
+
const App = () => {
|
|
43
|
+
const runtime = useExternalStoreRuntime({ messages: [], onNew });
|
|
44
|
+
capture.runtime = runtime;
|
|
45
|
+
return null;
|
|
46
|
+
};
|
|
47
|
+
const view = render(<App />);
|
|
48
|
+
expect(capture.runtime).not.toBeNull();
|
|
49
|
+
const core = (
|
|
50
|
+
capture.runtime!.thread as unknown as {
|
|
51
|
+
__internal_threadBinding: {
|
|
52
|
+
getState(): {
|
|
53
|
+
__internal_setGetInitializePromise(
|
|
54
|
+
getPromise: () => Promise<unknown> | undefined,
|
|
55
|
+
): void;
|
|
56
|
+
append(message: unknown): Promise<void>;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
).__internal_threadBinding.getState();
|
|
61
|
+
core.__internal_setGetInitializePromise(() => initialization);
|
|
62
|
+
|
|
63
|
+
const appendPromise = core.append({
|
|
64
|
+
parentId: null,
|
|
65
|
+
sourceId: null,
|
|
66
|
+
runConfig: {},
|
|
67
|
+
role: "user",
|
|
68
|
+
content: [{ type: "text", text: "hello" }],
|
|
69
|
+
attachments: [],
|
|
70
|
+
metadata: { custom: {} },
|
|
71
|
+
createdAt: new Date(0),
|
|
72
|
+
});
|
|
73
|
+
await Promise.resolve();
|
|
74
|
+
|
|
75
|
+
expect(onNew).toHaveBeenCalledTimes(1);
|
|
76
|
+
|
|
77
|
+
view.unmount();
|
|
78
|
+
resolveInitialization();
|
|
79
|
+
|
|
80
|
+
await appendPromise;
|
|
81
|
+
expect(onNew).toHaveBeenCalledTimes(1);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { StrictMode } from "react";
|
|
4
|
+
import { cleanup, render, waitFor } from "@testing-library/react";
|
|
5
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
6
|
+
import {
|
|
7
|
+
AuiConfig,
|
|
8
|
+
useAui,
|
|
9
|
+
useAuiState,
|
|
10
|
+
type AssistantClient,
|
|
11
|
+
} from "@assistant-ui/store";
|
|
12
|
+
import type { ThreadSuggestion } from "../../runtime/interfaces/thread-runtime-core";
|
|
13
|
+
import { Suggestions } from "../../store/clients/suggestions";
|
|
14
|
+
import { AssistantRuntimeProvider } from "../AssistantRuntimeProvider";
|
|
15
|
+
import { useExternalStoreRuntime } from "./useExternalStoreRuntime";
|
|
16
|
+
|
|
17
|
+
let aui!: AssistantClient;
|
|
18
|
+
let scopeSuggestions!: readonly { prompt: string }[];
|
|
19
|
+
|
|
20
|
+
const Consumer = () => {
|
|
21
|
+
aui = useAui();
|
|
22
|
+
scopeSuggestions = useAuiState((s) => s.suggestions.suggestions);
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const App = ({
|
|
27
|
+
suggestions,
|
|
28
|
+
config,
|
|
29
|
+
strict,
|
|
30
|
+
}: {
|
|
31
|
+
suggestions?: ThreadSuggestion[];
|
|
32
|
+
config?: AuiConfig;
|
|
33
|
+
strict?: boolean;
|
|
34
|
+
}) => {
|
|
35
|
+
const runtime = useExternalStoreRuntime({
|
|
36
|
+
messages: [],
|
|
37
|
+
onNew: async () => {},
|
|
38
|
+
...(suggestions && { suggestions }),
|
|
39
|
+
});
|
|
40
|
+
const tree = (
|
|
41
|
+
<AssistantRuntimeProvider runtime={runtime} config={config}>
|
|
42
|
+
<Consumer />
|
|
43
|
+
</AssistantRuntimeProvider>
|
|
44
|
+
);
|
|
45
|
+
return strict ? <StrictMode>{tree}</StrictMode> : tree;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
afterEach(() => {
|
|
49
|
+
cleanup();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe("useExternalStoreRuntime suggestions scope", () => {
|
|
53
|
+
it("exposes runtime suggestions on the suggestions scope", () => {
|
|
54
|
+
render(
|
|
55
|
+
<App
|
|
56
|
+
suggestions={[
|
|
57
|
+
{ title: "Weather", label: "in SF", prompt: "What's the weather?" },
|
|
58
|
+
{ prompt: "Help" },
|
|
59
|
+
]}
|
|
60
|
+
/>,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
expect(scopeSuggestions).toEqual([
|
|
64
|
+
{ title: "Weather", label: "in SF", prompt: "What's the weather?" },
|
|
65
|
+
{ title: "Help", label: "", prompt: "Help" },
|
|
66
|
+
]);
|
|
67
|
+
expect(aui.suggestions.suggestion({ index: 0 }).getState()).toEqual({
|
|
68
|
+
title: "Weather",
|
|
69
|
+
label: "in SF",
|
|
70
|
+
prompt: "What's the weather?",
|
|
71
|
+
});
|
|
72
|
+
expect(aui.suggestions.suggestion({ index: 1 }).getState()).toEqual({
|
|
73
|
+
title: "Help",
|
|
74
|
+
label: "",
|
|
75
|
+
prompt: "Help",
|
|
76
|
+
});
|
|
77
|
+
expect(aui.thread.getState().suggestions).toEqual([
|
|
78
|
+
{ title: "Weather", label: "in SF", prompt: "What's the weather?" },
|
|
79
|
+
{ prompt: "Help" },
|
|
80
|
+
]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("exposes runtime suggestions under StrictMode", () => {
|
|
84
|
+
render(<App strict suggestions={[{ prompt: "Tell me a joke" }]} />);
|
|
85
|
+
|
|
86
|
+
expect(scopeSuggestions).toEqual([
|
|
87
|
+
{ title: "Tell me a joke", label: "", prompt: "Tell me a joke" },
|
|
88
|
+
]);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("reports an empty scope without runtime suggestions", () => {
|
|
92
|
+
render(<App />);
|
|
93
|
+
|
|
94
|
+
expect(scopeSuggestions).toEqual([]);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("follows runtime suggestion updates", async () => {
|
|
98
|
+
const view = render(<App suggestions={[{ prompt: "First" }]} />);
|
|
99
|
+
expect(scopeSuggestions).toEqual([
|
|
100
|
+
{ title: "First", label: "", prompt: "First" },
|
|
101
|
+
]);
|
|
102
|
+
|
|
103
|
+
view.rerender(<App suggestions={[{ prompt: "Second" }]} />);
|
|
104
|
+
await waitFor(() => {
|
|
105
|
+
expect(scopeSuggestions).toEqual([
|
|
106
|
+
{ title: "Second", label: "", prompt: "Second" },
|
|
107
|
+
]);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("prefers config-provided suggestions over runtime suggestions", () => {
|
|
112
|
+
render(
|
|
113
|
+
<App
|
|
114
|
+
suggestions={[{ prompt: "Runtime" }]}
|
|
115
|
+
config={AuiConfig({ suggestions: Suggestions(["Static"]) })}
|
|
116
|
+
/>,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
expect(scopeSuggestions).toEqual([
|
|
120
|
+
{ title: "Static", label: "", prompt: "Static" },
|
|
121
|
+
]);
|
|
122
|
+
expect(aui.thread.getState().suggestions).toEqual([{ prompt: "Runtime" }]);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -5,6 +5,7 @@ import { ExternalStoreRuntimeCore } from "../../runtimes/internal";
|
|
|
5
5
|
import type { ExternalStoreAdapter } from "../../runtimes/external-store/external-store-adapter";
|
|
6
6
|
import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
|
|
7
7
|
import { AssistantRuntimeImpl } from "../../runtime/internal";
|
|
8
|
+
import { invalidateThreadRuntime } from "../../runtime/utils/thread-runtime-lifecycle";
|
|
8
9
|
import { useRuntimeAdapters } from "./RuntimeAdapterProvider";
|
|
9
10
|
|
|
10
11
|
export const useExternalStoreRuntime = <T>(
|
|
@@ -12,6 +13,12 @@ export const useExternalStoreRuntime = <T>(
|
|
|
12
13
|
): AssistantRuntime => {
|
|
13
14
|
const [runtime] = useState(() => new ExternalStoreRuntimeCore(store));
|
|
14
15
|
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
return () => {
|
|
18
|
+
invalidateThreadRuntime(runtime.threads.getMainThreadRuntimeCore());
|
|
19
|
+
};
|
|
20
|
+
}, [runtime]);
|
|
21
|
+
|
|
15
22
|
useEffect(() => {
|
|
16
23
|
runtime.setAdapter(store);
|
|
17
24
|
});
|
|
@@ -16,7 +16,9 @@ export const useExternalStoreSharedOptions = (
|
|
|
16
16
|
unstable_capabilities,
|
|
17
17
|
suggestions,
|
|
18
18
|
}) satisfies {
|
|
19
|
-
[
|
|
19
|
+
[
|
|
20
|
+
K in keyof Required<ExternalStoreSharedOptions>
|
|
21
|
+
]: ExternalStoreSharedOptions[K];
|
|
20
22
|
},
|
|
21
23
|
[isDisabled, isSendDisabled, unstable_capabilities, suggestions],
|
|
22
24
|
);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
2
|
|
|
3
|
-
import { render, waitFor } from "@testing-library/react";
|
|
4
|
-
import { StrictMode } from "react";
|
|
3
|
+
import { act, render, waitFor } from "@testing-library/react";
|
|
4
|
+
import { type FC, StrictMode } from "react";
|
|
5
5
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
6
6
|
import type { AssistantCloud } from "assistant-cloud";
|
|
7
|
+
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
7
8
|
import type { ChatModelAdapter } from "../../runtime/utils/chat-model-adapter";
|
|
8
9
|
import { AssistantRuntimeProvider } from "../AssistantRuntimeProvider";
|
|
9
10
|
import { useLocalRuntime } from "./useLocalRuntime";
|
|
@@ -17,13 +18,49 @@ const makeCloud = () =>
|
|
|
17
18
|
threads: {
|
|
18
19
|
list: vi.fn().mockResolvedValue({ threads: [] }),
|
|
19
20
|
},
|
|
21
|
+
files: {
|
|
22
|
+
generatePresignedUploadUrl: vi.fn().mockResolvedValue({
|
|
23
|
+
signedUrl: "https://storage.example/upload",
|
|
24
|
+
publicUrl: "https://cdn.example/file.txt",
|
|
25
|
+
}),
|
|
26
|
+
},
|
|
20
27
|
}) as unknown as AssistantCloud;
|
|
21
28
|
|
|
22
29
|
afterEach(() => {
|
|
30
|
+
vi.unstubAllGlobals();
|
|
23
31
|
vi.restoreAllMocks();
|
|
24
32
|
});
|
|
25
33
|
|
|
26
34
|
describe("useLocalRuntime", () => {
|
|
35
|
+
it("surfaces the live thread after mount without user input", async () => {
|
|
36
|
+
const auiRef: { current: ReturnType<typeof useAui> | null } = {
|
|
37
|
+
current: null,
|
|
38
|
+
};
|
|
39
|
+
const loadingRef = { current: true };
|
|
40
|
+
const Capture: FC = () => {
|
|
41
|
+
auiRef.current = useAui();
|
|
42
|
+
loadingRef.current = useAuiState((s) => s.thread.isLoading);
|
|
43
|
+
return null;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const App = () => {
|
|
47
|
+
const runtime = useLocalRuntime(chatModel, {
|
|
48
|
+
unstable_enableMessageQueue: true,
|
|
49
|
+
});
|
|
50
|
+
return (
|
|
51
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
52
|
+
<Capture />
|
|
53
|
+
</AssistantRuntimeProvider>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
render(<App />);
|
|
58
|
+
await waitFor(() => {
|
|
59
|
+
expect(loadingRef.current).toBe(false);
|
|
60
|
+
expect(auiRef.current!.thread.getState().capabilities.queue).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
27
64
|
it("keeps the Cloud thread list loaded across unrelated rerenders", async () => {
|
|
28
65
|
const firstCloud = makeCloud();
|
|
29
66
|
const secondCloud = makeCloud();
|
|
@@ -59,6 +96,47 @@ describe("useLocalRuntime", () => {
|
|
|
59
96
|
expect(firstCloud.threads.list).toHaveBeenCalledOnce();
|
|
60
97
|
});
|
|
61
98
|
|
|
99
|
+
it("uses the current Cloud client for attachment uploads", async () => {
|
|
100
|
+
vi.stubGlobal("fetch", vi.fn().mockResolvedValue({ ok: true }));
|
|
101
|
+
const firstCloud = makeCloud();
|
|
102
|
+
const secondCloud = makeCloud();
|
|
103
|
+
let addAttachment: ((file: File) => Promise<void>) | undefined;
|
|
104
|
+
let getAttachmentStatus: (() => unknown) | undefined;
|
|
105
|
+
|
|
106
|
+
const App = ({ cloud }: { cloud: AssistantCloud }) => {
|
|
107
|
+
const runtime = useLocalRuntime(chatModel, { cloud });
|
|
108
|
+
addAttachment = (file) => runtime.thread.composer.addAttachment(file);
|
|
109
|
+
getAttachmentStatus = () =>
|
|
110
|
+
runtime.thread.composer.getState().attachments[0]?.status;
|
|
111
|
+
return (
|
|
112
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
113
|
+
<div />
|
|
114
|
+
</AssistantRuntimeProvider>
|
|
115
|
+
);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const { rerender } = render(<App cloud={firstCloud} />);
|
|
119
|
+
|
|
120
|
+
await waitFor(() => {
|
|
121
|
+
expect(firstCloud.threads.list).toHaveBeenCalledOnce();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
rerender(<App cloud={secondCloud} />);
|
|
125
|
+
|
|
126
|
+
await act(async () => {
|
|
127
|
+
await addAttachment!(
|
|
128
|
+
new File(["hello"], "notes.txt", { type: "text/plain" }),
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
expect(firstCloud.files.generatePresignedUploadUrl).not.toHaveBeenCalled();
|
|
133
|
+
expect(secondCloud.files.generatePresignedUploadUrl).toHaveBeenCalledOnce();
|
|
134
|
+
expect(getAttachmentStatus!()).toEqual({
|
|
135
|
+
type: "requires-action",
|
|
136
|
+
reason: "composer-send",
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
62
140
|
it("handles rejected history loads", async () => {
|
|
63
141
|
const error = new Error("history unavailable");
|
|
64
142
|
const consoleError = vi
|
|
@@ -92,8 +170,56 @@ describe("useLocalRuntime", () => {
|
|
|
92
170
|
);
|
|
93
171
|
});
|
|
94
172
|
|
|
173
|
+
const loadsAfterMount = history.load.mock.calls.length;
|
|
174
|
+
const errorsAfterMount = consoleError.mock.calls.length;
|
|
175
|
+
expect(loadsAfterMount).toBeGreaterThan(0);
|
|
95
176
|
rerender(renderApp());
|
|
96
|
-
expect(history.load).toHaveBeenCalledTimes(
|
|
97
|
-
expect(consoleError).toHaveBeenCalledTimes(
|
|
177
|
+
expect(history.load).toHaveBeenCalledTimes(loadsAfterMount);
|
|
178
|
+
expect(consoleError).toHaveBeenCalledTimes(errorsAfterMount);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it("exposes composer.canCancel while a run started after initial messages is in flight", async () => {
|
|
182
|
+
const hangingModel: ChatModelAdapter = {
|
|
183
|
+
async *run({ abortSignal }) {
|
|
184
|
+
await new Promise<void>((resolve) => {
|
|
185
|
+
if (abortSignal.aborted) {
|
|
186
|
+
resolve();
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
abortSignal.addEventListener("abort", () => resolve(), {
|
|
190
|
+
once: true,
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
let runtime: ReturnType<typeof useLocalRuntime> | null = null;
|
|
196
|
+
const App = () => {
|
|
197
|
+
runtime = useLocalRuntime(hangingModel, {
|
|
198
|
+
initialMessages: [
|
|
199
|
+
{
|
|
200
|
+
role: "assistant",
|
|
201
|
+
content: [{ type: "text", text: "Hello" }],
|
|
202
|
+
status: { type: "complete", reason: "stop" },
|
|
203
|
+
},
|
|
204
|
+
],
|
|
205
|
+
});
|
|
206
|
+
return (
|
|
207
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
208
|
+
<div />
|
|
209
|
+
</AssistantRuntimeProvider>
|
|
210
|
+
);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
render(<App />);
|
|
214
|
+
act(() => {
|
|
215
|
+
runtime!.thread.append("Run");
|
|
216
|
+
});
|
|
217
|
+
await waitFor(() => {
|
|
218
|
+
expect(runtime!.thread.getState().isRunning).toBe(true);
|
|
219
|
+
expect(runtime!.thread.composer.getState().canCancel).toBe(true);
|
|
220
|
+
});
|
|
221
|
+
act(() => {
|
|
222
|
+
runtime!.thread.cancelRun();
|
|
223
|
+
});
|
|
98
224
|
});
|
|
99
225
|
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { renderHook } from "@testing-library/react";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { useStableRuntimeAdapters } from "./useRuntimeAdapters";
|
|
6
|
+
import type { RuntimeAdapters } from "../../runtimes/remote-thread-list/types";
|
|
7
|
+
import type { ThreadHistoryAdapter } from "../../adapters/thread-history";
|
|
8
|
+
|
|
9
|
+
const makeHistory = (): ThreadHistoryAdapter => ({
|
|
10
|
+
load: async () => ({ messages: [] }),
|
|
11
|
+
append: async () => {},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("useStableRuntimeAdapters", () => {
|
|
15
|
+
it("keeps the previous bag when a fresh literal is shallow-equal", () => {
|
|
16
|
+
const history = makeHistory();
|
|
17
|
+
const { result, rerender } = renderHook(
|
|
18
|
+
({ adapters }: { adapters: RuntimeAdapters | null }) =>
|
|
19
|
+
useStableRuntimeAdapters(adapters),
|
|
20
|
+
{ initialProps: { adapters: { history } } },
|
|
21
|
+
);
|
|
22
|
+
const first = result.current;
|
|
23
|
+
|
|
24
|
+
rerender({ adapters: { history } });
|
|
25
|
+
|
|
26
|
+
expect(result.current).toBe(first);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("adopts the new bag when a field changes", () => {
|
|
30
|
+
const first = makeHistory();
|
|
31
|
+
const second = makeHistory();
|
|
32
|
+
const { result, rerender } = renderHook(
|
|
33
|
+
({ adapters }: { adapters: RuntimeAdapters | null }) =>
|
|
34
|
+
useStableRuntimeAdapters(adapters),
|
|
35
|
+
{ initialProps: { adapters: { history: first } } },
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
rerender({ adapters: { history: second } });
|
|
39
|
+
|
|
40
|
+
expect(result.current?.history).toBe(second);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("moves between null and a bag", () => {
|
|
44
|
+
const history = makeHistory();
|
|
45
|
+
const { result, rerender } = renderHook(
|
|
46
|
+
({ adapters }: { adapters: RuntimeAdapters | null }) =>
|
|
47
|
+
useStableRuntimeAdapters(adapters),
|
|
48
|
+
{ initialProps: { adapters: null as RuntimeAdapters | null } },
|
|
49
|
+
);
|
|
50
|
+
expect(result.current).toBeNull();
|
|
51
|
+
|
|
52
|
+
rerender({ adapters: { history } });
|
|
53
|
+
expect(result.current?.history).toBe(history);
|
|
54
|
+
|
|
55
|
+
rerender({ adapters: null });
|
|
56
|
+
expect(result.current).toBeNull();
|
|
57
|
+
|
|
58
|
+
rerender({ adapters: {} });
|
|
59
|
+
expect(result.current).not.toBeNull();
|
|
60
|
+
expect(result.current).toEqual({});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
import { useContextProvider } from "@assistant-ui/tap";
|
|
3
|
+
import { useShallowStable } from "@assistant-ui/store/internal";
|
|
4
|
+
import type { RuntimeAdapters } from "../../runtimes/remote-thread-list/types";
|
|
5
|
+
|
|
6
|
+
const RuntimeAdaptersContext = createContext<RuntimeAdapters | null>(null);
|
|
7
|
+
|
|
8
|
+
export const useRuntimeAdaptersProvider = <T>(
|
|
9
|
+
adapters: RuntimeAdapters | null,
|
|
10
|
+
fn: () => T,
|
|
11
|
+
): T => useContextProvider(RuntimeAdaptersContext, adapters, fn);
|
|
12
|
+
|
|
13
|
+
export const useRuntimeAdapters = () => {
|
|
14
|
+
return useContext(RuntimeAdaptersContext);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const NO_ADAPTERS: RuntimeAdapters = {};
|
|
18
|
+
|
|
19
|
+
// Both adapter faces absorb a fresh but shallow-equal bag from
|
|
20
|
+
// `unstable_useAdapters`, so a per-render literal does not churn the context.
|
|
21
|
+
export const useStableRuntimeAdapters = (
|
|
22
|
+
adapters: RuntimeAdapters | null | undefined,
|
|
23
|
+
): RuntimeAdapters | null => {
|
|
24
|
+
const stable = useShallowStable(adapters ?? NO_ADAPTERS);
|
|
25
|
+
return adapters == null ? null : stable;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { RuntimeAdaptersContext };
|
|
@@ -42,6 +42,11 @@ export type {
|
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
type BaseComposerState = {
|
|
45
|
+
/**
|
|
46
|
+
* Whether the composer can cancel the current run. `true` when the runtime
|
|
47
|
+
* supports cancel and a run is in flight, not merely when cancel is a
|
|
48
|
+
* capability.
|
|
49
|
+
*/
|
|
45
50
|
readonly canCancel: boolean;
|
|
46
51
|
readonly canSend: boolean;
|
|
47
52
|
readonly isEditing: boolean;
|
|
@@ -114,6 +114,7 @@ export type ThreadListRuntimeCoreBinding = ThreadListRuntimeCore;
|
|
|
114
114
|
|
|
115
115
|
export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
116
116
|
private _getState;
|
|
117
|
+
private _stateBinding: LazyMemoizeSubject<ThreadListState, object>;
|
|
117
118
|
private _core: ThreadListRuntimeCoreBinding;
|
|
118
119
|
private _runtimeFactory: new (
|
|
119
120
|
binding: ThreadRuntimeCoreBinding,
|
|
@@ -136,6 +137,7 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
|
136
137
|
});
|
|
137
138
|
|
|
138
139
|
this._getState = stateBinding.getState.bind(stateBinding);
|
|
140
|
+
this._stateBinding = stateBinding;
|
|
139
141
|
|
|
140
142
|
this._mainThreadListItemRuntime = new ThreadListItemRuntimeImpl(
|
|
141
143
|
new ShallowMemoizeSubject({
|
|
@@ -213,7 +215,7 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
|
213
215
|
}
|
|
214
216
|
|
|
215
217
|
public subscribe(callback: () => void): Unsubscribe {
|
|
216
|
-
return this.
|
|
218
|
+
return this._stateBinding.subscribe(callback);
|
|
217
219
|
}
|
|
218
220
|
|
|
219
221
|
private _mainThreadListItemRuntime;
|
|
@@ -34,6 +34,7 @@ import type {
|
|
|
34
34
|
import type { ThreadListItemState } from "./bindings";
|
|
35
35
|
import type { AppendMessage, ThreadMessage } from "../../types/message";
|
|
36
36
|
import type { Unsubscribe } from "../../types/unsubscribe";
|
|
37
|
+
import { isMessageNotSentError } from "../../types/error";
|
|
37
38
|
import type { RunConfig } from "../../types/message";
|
|
38
39
|
import { EventSubscriptionSubject } from "../../subscribable/subscribable";
|
|
39
40
|
import { symbolInnerMessage } from "../utils/external-store-message";
|
|
@@ -198,7 +199,7 @@ export type ThreadState = {
|
|
|
198
199
|
* reports it directly; the rest fall back to the trailing assistant message.
|
|
199
200
|
*/
|
|
200
201
|
export const getThreadRuntimeCoreIsRunning = (
|
|
201
|
-
runtime: ThreadRuntimeCore,
|
|
202
|
+
runtime: Pick<ThreadRuntimeCore, "isRunning" | "messages">,
|
|
202
203
|
): boolean => {
|
|
203
204
|
if (runtime.isRunning !== undefined) return runtime.isRunning;
|
|
204
205
|
const lastMessage = runtime.messages.at(-1);
|
|
@@ -293,6 +294,13 @@ export type ThreadRuntime = {
|
|
|
293
294
|
|
|
294
295
|
subscribe(callback: () => void): Unsubscribe;
|
|
295
296
|
cancelRun(): void;
|
|
297
|
+
/**
|
|
298
|
+
* Notifies the runtime that the adapter discarded its backing session.
|
|
299
|
+
* Clears session-scoped tool-invocation state without run-cancel side
|
|
300
|
+
* effects such as composer draft restoration. Internal API for
|
|
301
|
+
* external-store adapter authors.
|
|
302
|
+
*/
|
|
303
|
+
unstable_notifySessionReset(): void;
|
|
296
304
|
getModelContext(): ModelContext;
|
|
297
305
|
|
|
298
306
|
export(): ExportedMessageRepository;
|
|
@@ -338,6 +346,10 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
338
346
|
private readonly _threadBinding: ThreadRuntimeCoreBinding & {
|
|
339
347
|
getStateState(): ThreadState;
|
|
340
348
|
};
|
|
349
|
+
private readonly _stateBinding: ShallowMemoizeSubject<
|
|
350
|
+
ThreadState,
|
|
351
|
+
ThreadRuntimePath
|
|
352
|
+
>;
|
|
341
353
|
|
|
342
354
|
constructor(
|
|
343
355
|
threadBinding: ThreadRuntimeCoreBinding,
|
|
@@ -360,6 +372,7 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
360
372
|
},
|
|
361
373
|
});
|
|
362
374
|
|
|
375
|
+
this._stateBinding = stateBinding;
|
|
363
376
|
this._threadBinding = {
|
|
364
377
|
path: threadBinding.path,
|
|
365
378
|
getState: () => threadBinding.getState(),
|
|
@@ -391,6 +404,8 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
391
404
|
this.exportExternalState = this.exportExternalState.bind(this);
|
|
392
405
|
this.startRun = this.startRun.bind(this);
|
|
393
406
|
this.cancelRun = this.cancelRun.bind(this);
|
|
407
|
+
this.unstable_notifySessionReset =
|
|
408
|
+
this.unstable_notifySessionReset.bind(this);
|
|
394
409
|
this.stopSpeaking = this.stopSpeaking.bind(this);
|
|
395
410
|
this.connectVoice = this.connectVoice.bind(this);
|
|
396
411
|
this.disconnectVoice = this.disconnectVoice.bind(this);
|
|
@@ -416,11 +431,17 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
416
431
|
}
|
|
417
432
|
|
|
418
433
|
public append(message: CreateAppendMessage) {
|
|
419
|
-
this._threadBinding
|
|
434
|
+
const task = this._threadBinding
|
|
420
435
|
.getState()
|
|
421
436
|
.append(
|
|
422
437
|
toAppendMessage(this._threadBinding.getState().messages, message),
|
|
423
438
|
);
|
|
439
|
+
// An undispatched send is reported to the composer, so it is a control
|
|
440
|
+
// signal rather than a failure to surface; every other rejection keeps
|
|
441
|
+
// reaching the host untouched.
|
|
442
|
+
void Promise.resolve(task).catch((error) => {
|
|
443
|
+
if (!isMessageNotSentError(error)) throw error;
|
|
444
|
+
});
|
|
424
445
|
}
|
|
425
446
|
|
|
426
447
|
public deleteMessage(messageId: string) {
|
|
@@ -428,7 +449,7 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
428
449
|
}
|
|
429
450
|
|
|
430
451
|
public subscribe(callback: () => void) {
|
|
431
|
-
return this.
|
|
452
|
+
return this._stateBinding.subscribe(callback);
|
|
432
453
|
}
|
|
433
454
|
|
|
434
455
|
public getModelContext() {
|
|
@@ -455,6 +476,10 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
455
476
|
this._threadBinding.getState().cancelRun();
|
|
456
477
|
}
|
|
457
478
|
|
|
479
|
+
public unstable_notifySessionReset() {
|
|
480
|
+
this._threadBinding.getState().unstable_notifySessionReset();
|
|
481
|
+
}
|
|
482
|
+
|
|
458
483
|
public stopSpeaking() {
|
|
459
484
|
return this._threadBinding.getState().stopSpeaking();
|
|
460
485
|
}
|