@assistant-ui/core 0.3.13 → 0.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/speech.d.ts.map +1 -1
- package/dist/adapters/speech.js +9 -15
- package/dist/adapters/speech.js.map +1 -1
- package/dist/adapters/thread-history.d.ts +2 -0
- package/dist/adapters/thread-history.d.ts.map +1 -1
- package/dist/adapters/voice.d.ts.map +1 -1
- package/dist/adapters/voice.js +38 -15
- package/dist/adapters/voice.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +3 -2
- package/dist/internal.js +8 -7
- package/dist/model-context/frame/host.d.ts +1 -1
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +19 -4
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/frame/provider.d.ts +4 -0
- package/dist/model-context/frame/provider.d.ts.map +1 -1
- package/dist/model-context/frame/provider.js +50 -3
- package/dist/model-context/frame/provider.js.map +1 -1
- package/dist/model-context/frame/types.d.ts +4 -1
- package/dist/model-context/frame/types.d.ts.map +1 -1
- package/dist/model-context/frame/types.js.map +1 -1
- package/dist/model-context/registry.d.ts.map +1 -1
- package/dist/model-context/registry.js +16 -4
- package/dist/model-context/registry.js.map +1 -1
- package/dist/react/RuntimeAdapter.d.ts +8 -1
- package/dist/react/RuntimeAdapter.d.ts.map +1 -1
- package/dist/react/RuntimeAdapter.js +23 -18
- package/dist/react/RuntimeAdapter.js.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js +28 -12
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/AdaptedRemoteThread.d.ts +11 -0
- package/dist/react/client/AdaptedRemoteThread.d.ts.map +1 -0
- package/dist/react/client/AdaptedRemoteThread.js +27 -0
- package/dist/react/client/AdaptedRemoteThread.js.map +1 -0
- package/dist/react/client/InMemoryThreadList.d.ts +19 -0
- package/dist/react/client/InMemoryThreadList.d.ts.map +1 -0
- package/dist/react/client/InMemoryThreadList.js +418 -0
- package/dist/react/client/InMemoryThreadList.js.map +1 -0
- package/dist/react/client/Interactables.d.ts.map +1 -1
- package/dist/react/client/Interactables.js +159 -102
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/RemoteThreadList.d.ts +34 -0
- package/dist/react/client/RemoteThreadList.d.ts.map +1 -0
- package/dist/react/client/RemoteThreadList.js +898 -0
- package/dist/react/client/RemoteThreadList.js.map +1 -0
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +38 -27
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/index.d.ts +7 -2
- package/dist/react/index.js +5 -2
- package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
- package/dist/react/interactables-legacy/Interactables.js +145 -110
- package/dist/react/interactables-legacy/Interactables.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.js +20 -19
- package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.js +2 -4
- package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.js +2 -4
- package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.js +2 -6
- package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js +2 -6
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.js +2 -4
- package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.js +2 -4
- package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.js +6 -2
- package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts +3 -0
- package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useThreadIsEmpty.js +3 -0
- package/dist/react/primitive-hooks/useThreadIsEmpty.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadIsRunning.d.ts +3 -0
- package/dist/react/primitive-hooks/useThreadIsRunning.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useThreadIsRunning.js +3 -0
- package/dist/react/primitive-hooks/useThreadIsRunning.js.map +1 -1
- package/dist/react/primitives/message/MessageParts.d.ts +13 -0
- package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.js +1 -1
- package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +24 -10
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +115 -71
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +14 -2
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +232 -63
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.d.ts +30 -0
- package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -0
- package/dist/react/runtimes/RemoteThreadResource.js +136 -0
- package/dist/react/runtimes/RemoteThreadResource.js.map +1 -0
- package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +3 -10
- package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
- package/dist/react/runtimes/RuntimeAdapterProvider.js +3 -6
- package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
- package/dist/react/runtimes/assistant-transport/commandQueue.d.ts +17 -0
- package/dist/react/runtimes/assistant-transport/commandQueue.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/commandQueue.js +55 -0
- package/dist/react/runtimes/assistant-transport/commandQueue.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts +11 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js +165 -0
- package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/runManager.d.ts +15 -0
- package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/runManager.js +86 -0
- package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/types.d.ts +130 -0
- package/dist/react/runtimes/assistant-transport/types.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/types.js +0 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts +14 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js +296 -0
- package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts +7 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.js +25 -0
- package/dist/react/runtimes/assistant-transport/useConvertedState.js.map +1 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts +7 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts.map +1 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.js +27 -0
- package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -0
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +39 -13
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +2 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +3 -3
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +4 -0
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js +7 -0
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +60 -17
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts +16 -0
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts.map +1 -0
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js +36 -0
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -0
- package/dist/react/runtimes/external-message-converter.js +14 -14
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useExternalStoreRuntime.js +44 -28
- package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
- package/dist/react/runtimes/useLocalRuntime.js +1 -1
- package/dist/react/runtimes/useRuntimeAdapters.d.ts +9 -0
- package/dist/react/runtimes/useRuntimeAdapters.d.ts.map +1 -0
- package/dist/react/runtimes/useRuntimeAdapters.js +20 -0
- package/dist/react/runtimes/useRuntimeAdapters.js.map +1 -0
- package/dist/runtime/api/composer-runtime.d.ts +5 -0
- package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.js.map +1 -1
- package/dist/runtime/api/message-runtime.js +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts +1 -0
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +4 -2
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +12 -2
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +8 -2
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +8 -7
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -0
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +3 -3
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +0 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js +10 -4
- package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/internal.js +5 -5
- package/dist/runtime/queue/message-queue.d.ts.map +1 -1
- package/dist/runtime/queue/message-queue.js +2 -1
- package/dist/runtime/queue/message-queue.js.map +1 -1
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +27 -18
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/thread-runtime-lifecycle.d.ts +8 -0
- package/dist/runtime/utils/thread-runtime-lifecycle.d.ts.map +1 -0
- package/dist/runtime/utils/thread-runtime-lifecycle.js +11 -0
- package/dist/runtime/utils/thread-runtime-lifecycle.js.map +1 -0
- package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +4 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +8 -0
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +37 -13
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts +102 -0
- package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts.map +1 -0
- package/dist/runtimes/inert/InertThreadRuntimeCore.js +156 -0
- package/dist/runtimes/inert/InertThreadRuntimeCore.js.map +1 -0
- package/dist/runtimes/internal.d.ts +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +78 -19
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +12 -59
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +10 -142
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/remote-thread-list/adapter-changed.d.ts +9 -0
- package/dist/runtimes/remote-thread-list/adapter-changed.d.ts.map +1 -0
- package/dist/runtimes/remote-thread-list/adapter-changed.js +13 -0
- package/dist/runtimes/remote-thread-list/adapter-changed.js.map +1 -0
- package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.js +16 -152
- package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/optimistic-state.d.ts +2 -0
- package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/optimistic-state.js +11 -0
- package/dist/runtimes/remote-thread-list/optimistic-state.js.map +1 -1
- package/dist/runtimes/remote-thread-list/types.d.ts +32 -1
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +1 -12
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +67 -38
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/external-thread.js +1 -1
- package/dist/store/clients/external-thread.js.map +1 -1
- package/dist/store/clients/suggestions.js +2 -2
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/clients/thread-selection-events.d.ts +10 -0
- package/dist/store/clients/thread-selection-events.d.ts.map +1 -0
- package/dist/store/clients/thread-selection-events.js +40 -0
- package/dist/store/clients/thread-selection-events.js.map +1 -0
- package/dist/store/env.d.ts +5 -0
- package/dist/store/env.d.ts.map +1 -0
- package/dist/store/env.js +12 -0
- package/dist/store/env.js.map +1 -0
- package/dist/store/index.d.ts +5 -3
- package/dist/store/index.js +4 -2
- package/dist/store/internal.d.ts +4 -1
- package/dist/store/internal.js +4 -1
- package/dist/store/primitive-predicates.d.ts +19 -0
- package/dist/store/primitive-predicates.d.ts.map +1 -0
- package/dist/store/primitive-predicates.js +19 -0
- package/dist/store/primitive-predicates.js.map +1 -0
- package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/attachment-runtime-client.js +18 -11
- package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/handle-runtime-action.d.ts +5 -0
- package/dist/store/runtime-clients/handle-runtime-action.d.ts.map +1 -0
- package/dist/store/runtime-clients/handle-runtime-action.js +14 -0
- package/dist/store/runtime-clients/handle-runtime-action.js.map +1 -0
- package/dist/store/runtime-clients/handle-thread-list-action.d.ts +5 -0
- package/dist/store/runtime-clients/handle-thread-list-action.d.ts.map +1 -0
- package/dist/store/runtime-clients/handle-thread-list-action.js +7 -0
- package/dist/store/runtime-clients/handle-thread-list-action.js.map +1 -0
- package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js +62 -29
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js +5 -6
- package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
- package/dist/store/scopes/composer.d.ts +9 -4
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/thread-list-item.d.ts +7 -6
- package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
- package/dist/store/scopes/thread.d.ts +8 -7
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/dist/store/scopes/threads.d.ts +17 -1
- package/dist/store/scopes/threads.d.ts.map +1 -1
- package/dist/subscribable/subscribable.d.ts +2 -1
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/subscribable/subscribable.js +23 -18
- package/dist/subscribable/subscribable.js.map +1 -1
- package/dist/types/message.d.ts +1 -1
- package/dist/types/message.js.map +1 -1
- package/dist/utils/composite-context-provider.d.ts +1 -0
- package/dist/utils/composite-context-provider.d.ts.map +1 -1
- package/dist/utils/composite-context-provider.js +25 -9
- package/dist/utils/composite-context-provider.js.map +1 -1
- package/dist/utils/notify-event-listeners.d.ts +2 -2
- package/dist/utils/notify-event-listeners.d.ts.map +1 -1
- package/dist/utils/notify-event-listeners.js +2 -2
- package/dist/utils/notify-event-listeners.js.map +1 -1
- package/dist/utils/silent-runtime-action.d.ts +6 -0
- package/dist/utils/silent-runtime-action.d.ts.map +1 -0
- package/dist/utils/silent-runtime-action.js +7 -0
- package/dist/utils/silent-runtime-action.js.map +1 -0
- package/package.json +8 -8
- package/src/adapters/speech.test.ts +118 -1
- package/src/adapters/speech.ts +21 -22
- package/src/adapters/thread-history.ts +2 -0
- package/src/adapters/voice.test.ts +134 -0
- package/src/adapters/voice.ts +35 -27
- package/src/index.ts +1 -0
- package/src/internal.ts +1 -0
- package/src/model-context/frame/host.test.ts +87 -5
- package/src/model-context/frame/host.ts +18 -4
- package/src/model-context/frame/provider.test.ts +347 -20
- package/src/model-context/frame/provider.ts +58 -2
- package/src/model-context/frame/types.ts +5 -0
- package/src/model-context/registry.test.ts +131 -0
- package/src/model-context/registry.ts +16 -6
- package/src/react/RuntimeAdapter.test.ts +2 -0
- package/src/react/RuntimeAdapter.ts +20 -8
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +34 -17
- package/src/react/client/AdaptedRemoteThread.ts +41 -0
- package/src/react/client/InMemoryThreadList.test.tsx +148 -0
- package/src/react/client/InMemoryThreadList.ts +290 -0
- package/src/react/client/Interactables.test.ts +326 -2
- package/src/react/client/Interactables.ts +227 -110
- package/src/react/client/RemoteThreadList.test.ts +1222 -0
- package/src/react/client/RemoteThreadList.ts +1136 -0
- package/src/react/client/Tools.ts +36 -29
- package/src/react/index.ts +13 -0
- package/src/react/interactables-legacy/Interactables.test.ts +317 -0
- package/src/react/interactables-legacy/Interactables.ts +204 -128
- package/src/react/primitive-hooks/useActionBarCopy.test.ts +15 -0
- package/src/react/primitive-hooks/useActionBarCopy.ts +15 -10
- package/src/react/primitive-hooks/useActionBarEdit.ts +2 -1
- package/src/react/primitive-hooks/useActionBarReload.ts +2 -6
- package/src/react/primitive-hooks/useBranchPickerNext.ts +2 -7
- package/src/react/primitive-hooks/useBranchPickerPrevious.ts +2 -7
- package/src/react/primitive-hooks/useComposerCancel.ts +2 -1
- package/src/react/primitive-hooks/useComposerSend.ts +2 -5
- package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +11 -0
- package/src/react/primitive-hooks/useSuggestionTrigger.ts +4 -5
- package/src/react/primitive-hooks/useThreadIsEmpty.ts +3 -0
- package/src/react/primitive-hooks/useThreadIsRunning.ts +3 -0
- package/src/react/primitives/message/MessageParts.tsx +0 -1
- package/src/react/primitives/thread/ThreadMessages.tsx +2 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.retry.test.tsx +116 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +1 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +57 -6
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.title.test.tsx +272 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +171 -124
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.republish.test.ts +87 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +327 -83
- package/src/react/runtimes/RemoteThreadResource.test.ts +141 -0
- package/src/react/runtimes/RemoteThreadResource.ts +233 -0
- package/src/react/runtimes/RuntimeAdapterProvider.tsx +8 -20
- package/src/react/runtimes/assistant-transport/commandQueue.ts +68 -0
- package/src/react/runtimes/assistant-transport/replayBoundaryStream.test.ts +455 -0
- package/src/react/runtimes/assistant-transport/replayBoundaryStream.ts +172 -0
- package/src/react/runtimes/assistant-transport/runManager.ts +124 -0
- package/src/react/runtimes/assistant-transport/transport-delivery.test.tsx +79 -0
- package/src/react/runtimes/assistant-transport/transport-parentid.test.tsx +97 -0
- package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +414 -0
- package/src/react/runtimes/assistant-transport/types.ts +170 -0
- package/src/react/runtimes/assistant-transport/useAssistantTransport.spec.md +141 -0
- package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.test.tsx +683 -0
- package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +483 -0
- package/src/react/runtimes/assistant-transport/useConvertedState.ts +20 -0
- package/src/react/runtimes/assistant-transport/useLatestRef.ts +9 -0
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +131 -6
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +61 -15
- package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +6 -4
- package/src/react/runtimes/cloud/auiV0.ts +17 -1
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +98 -3
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +104 -27
- package/src/react/runtimes/cloud/useCloudThreadListRuntime.test.tsx +56 -0
- package/src/react/runtimes/cloud/useCloudThreadListRuntime.ts +31 -0
- package/src/react/runtimes/external-message-converter.test.ts +143 -0
- package/src/react/runtimes/external-message-converter.ts +41 -41
- package/src/react/runtimes/remote-thread-hook-on-tap.test.ts +58 -0
- package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +83 -0
- package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +13 -3
- package/src/react/runtimes/useExternalStoreRuntime.ts +7 -0
- package/src/react/runtimes/useExternalStoreSharedOptions.ts +3 -1
- package/src/react/runtimes/useLocalRuntime.test.tsx +134 -8
- package/src/react/runtimes/useRuntimeAdapters.test.tsx +62 -0
- package/src/react/runtimes/useRuntimeAdapters.ts +28 -0
- package/src/runtime/api/composer-runtime.ts +5 -0
- package/src/runtime/api/thread-list-runtime.ts +3 -1
- package/src/runtime/api/thread-runtime.ts +20 -2
- package/src/runtime/base/base-composer-runtime-core.ts +6 -5
- package/src/runtime/base/base-thread-runtime-core.test.ts +191 -0
- package/src/runtime/base/base-thread-runtime-core.ts +11 -2
- package/src/runtime/base/default-thread-composer-runtime-core.ts +12 -4
- package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
- package/src/runtime/queue/message-queue.ts +2 -1
- package/src/runtime/utils/message-repository.ts +26 -18
- package/src/runtime/utils/thread-runtime-lifecycle.ts +18 -0
- package/src/runtimes/external-store/external-store-shared-options.ts +3 -1
- package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +103 -34
- package/src/runtimes/inert/InertThreadRuntimeCore.test.ts +253 -0
- package/src/runtimes/inert/InertThreadRuntimeCore.ts +232 -0
- package/src/runtimes/local/local-thread-runtime-core.test.ts +692 -4
- package/src/runtimes/local/local-thread-runtime-core.ts +117 -22
- package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +17 -205
- package/src/runtimes/remote-thread-list/adapter-changed.ts +10 -0
- package/src/runtimes/remote-thread-list/empty-thread-core.ts +28 -217
- package/src/runtimes/remote-thread-list/optimistic-state.test.ts +18 -0
- package/src/runtimes/remote-thread-list/optimistic-state.ts +13 -0
- package/src/runtimes/remote-thread-list/types.ts +34 -0
- package/src/runtimes/tool-invocations/EDGE_CASES.md +17 -6
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +243 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +127 -61
- package/src/store/clients/external-thread.ts +1 -1
- package/src/store/clients/model-context-client.test.ts +16 -8
- package/src/store/clients/suggestions.ts +2 -2
- package/src/store/clients/thread-selection-events.ts +21 -0
- package/src/store/env.ts +11 -0
- package/src/store/index.ts +14 -1
- package/src/store/internal.ts +13 -0
- package/src/store/primitive-predicates.test.ts +184 -0
- package/src/store/primitive-predicates.ts +43 -0
- package/src/store/runtime-clients/attachment-runtime-client.test.ts +41 -0
- package/src/store/runtime-clients/attachment-runtime-client.ts +2 -1
- package/src/store/runtime-clients/handle-runtime-action.test.ts +40 -0
- package/src/store/runtime-clients/handle-runtime-action.ts +14 -0
- package/src/store/runtime-clients/handle-thread-list-action.test.ts +69 -0
- package/src/store/runtime-clients/handle-thread-list-action.ts +6 -0
- package/src/store/runtime-clients/thread-list-item-runtime-client.ts +15 -7
- package/src/store/runtime-clients/thread-list-runtime-client.ts +9 -6
- package/src/store/scopes/composer.ts +9 -4
- package/src/store/scopes/thread-list-item.ts +7 -6
- package/src/store/scopes/thread.ts +8 -7
- package/src/store/scopes/threads.ts +14 -0
- package/src/subscribable/subscribable.test.ts +77 -1
- package/src/subscribable/subscribable.ts +38 -23
- package/src/tests/MessageRepository.test.ts +48 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-errors.test.ts +2 -2
- package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +8 -6
- package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-unarchive.test.ts +25 -0
- package/src/tests/auiV0Encode.test.ts +66 -0
- package/src/tests/base-composer-runtime-core-send.test.ts +30 -0
- package/src/tests/base-composer-runtime-core.test.ts +28 -0
- package/src/tests/composer-can-cancel.test.ts +101 -0
- package/src/tests/empty-thread-core.test.ts +6 -0
- package/src/tests/external-store-thread-list-runtime-core.test.ts +101 -0
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +211 -1
- package/src/tests/external-store-thread-runtime-core.test.ts +124 -0
- package/src/tests/external-thread-isEmpty.test.tsx +100 -0
- package/src/tests/interactables-toolui-migration.test.tsx +66 -0
- package/src/tests/message-queue.test.ts +28 -0
- package/src/tests/remote-thread-list-adapter-switch.test.ts +383 -0
- package/src/tests/session-reset-notification.test.ts +145 -0
- package/src/tests/thread-switch-events.test.tsx +99 -1
- package/src/tests/tools-scope-migration.test.tsx +58 -0
- package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +67 -0
- package/src/types/message.ts +1 -1
- package/src/utils/composite-context-provider.test.ts +139 -0
- package/src/utils/composite-context-provider.ts +26 -8
- package/src/utils/notify-event-listeners.ts +10 -5
- package/src/utils/silent-runtime-action.ts +6 -0
|
@@ -1,234 +1,45 @@
|
|
|
1
|
+
import type { Unsubscribe } from "../../types/unsubscribe";
|
|
1
2
|
import type { ThreadRuntimeCore } from "../../runtime/interfaces/thread-runtime-core";
|
|
3
|
+
import {
|
|
4
|
+
InertThreadRuntimeCore,
|
|
5
|
+
createInertComposer,
|
|
6
|
+
} from "../inert/InertThreadRuntimeCore";
|
|
2
7
|
|
|
3
8
|
const EMPTY_THREAD_ERROR = new Error(
|
|
4
9
|
"This is the empty thread, a placeholder for the main thread. You cannot perform any actions on this thread instance. This error is probably because you tried to call a thread method in your render function. Call the method inside a `useEffect` hook instead.",
|
|
5
10
|
);
|
|
6
|
-
export const EMPTY_THREAD_CORE: ThreadRuntimeCore = {
|
|
7
|
-
getMessageById() {
|
|
8
|
-
return undefined;
|
|
9
|
-
},
|
|
10
|
-
|
|
11
|
-
getBranches() {
|
|
12
|
-
return [];
|
|
13
|
-
},
|
|
14
|
-
|
|
15
|
-
switchToBranch() {
|
|
16
|
-
throw EMPTY_THREAD_ERROR;
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
append() {
|
|
20
|
-
throw EMPTY_THREAD_ERROR;
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
deleteMessage() {
|
|
24
|
-
throw EMPTY_THREAD_ERROR;
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
startRun() {
|
|
28
|
-
throw EMPTY_THREAD_ERROR;
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
resumeRun() {
|
|
32
|
-
throw EMPTY_THREAD_ERROR;
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
cancelRun() {
|
|
36
|
-
throw EMPTY_THREAD_ERROR;
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
addToolResult() {
|
|
40
|
-
throw EMPTY_THREAD_ERROR;
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
resumeToolCall() {
|
|
44
|
-
throw EMPTY_THREAD_ERROR;
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
respondToToolApproval() {
|
|
48
|
-
throw EMPTY_THREAD_ERROR;
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
speak() {
|
|
52
|
-
throw EMPTY_THREAD_ERROR;
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
stopSpeaking() {
|
|
56
|
-
throw EMPTY_THREAD_ERROR;
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
connectVoice() {
|
|
60
|
-
throw EMPTY_THREAD_ERROR;
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
disconnectVoice() {
|
|
64
|
-
throw EMPTY_THREAD_ERROR;
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
getVoiceVolume: () => 0,
|
|
68
|
-
subscribeVoiceVolume: () => () => {},
|
|
69
|
-
|
|
70
|
-
muteVoice() {
|
|
71
|
-
throw EMPTY_THREAD_ERROR;
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
unmuteVoice() {
|
|
75
|
-
throw EMPTY_THREAD_ERROR;
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
submitFeedback() {
|
|
79
|
-
throw EMPTY_THREAD_ERROR;
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
getModelContext() {
|
|
83
|
-
return {};
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
exportExternalState() {
|
|
87
|
-
throw EMPTY_THREAD_ERROR;
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
importExternalState() {
|
|
91
|
-
throw EMPTY_THREAD_ERROR;
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
composer: {
|
|
95
|
-
attachments: [],
|
|
96
|
-
attachmentAccept: "*",
|
|
97
|
-
|
|
98
|
-
async addAttachment() {
|
|
99
|
-
throw EMPTY_THREAD_ERROR;
|
|
100
|
-
},
|
|
101
|
-
|
|
102
|
-
async removeAttachment() {
|
|
103
|
-
throw EMPTY_THREAD_ERROR;
|
|
104
|
-
},
|
|
105
|
-
|
|
106
|
-
isEditing: true,
|
|
107
|
-
|
|
108
|
-
canCancel: false,
|
|
109
|
-
canSend: false,
|
|
110
|
-
isEmpty: true,
|
|
111
11
|
|
|
112
|
-
|
|
12
|
+
class EmptyThreadRuntimeCore extends InertThreadRuntimeCore {
|
|
13
|
+
protected get error() {
|
|
14
|
+
return EMPTY_THREAD_ERROR;
|
|
15
|
+
}
|
|
113
16
|
|
|
114
|
-
|
|
115
|
-
throw EMPTY_THREAD_ERROR;
|
|
116
|
-
},
|
|
17
|
+
messages = [] as never[];
|
|
117
18
|
|
|
118
|
-
|
|
19
|
+
composer = createInertComposer(EMPTY_THREAD_ERROR, true);
|
|
119
20
|
|
|
120
|
-
|
|
121
|
-
throw EMPTY_THREAD_ERROR;
|
|
122
|
-
},
|
|
21
|
+
isLoading = true;
|
|
123
22
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
setRunConfig() {
|
|
127
|
-
throw EMPTY_THREAD_ERROR;
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
async reset() {
|
|
131
|
-
// noop
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
async clearAttachments() {
|
|
135
|
-
// noop
|
|
136
|
-
},
|
|
137
|
-
|
|
138
|
-
send() {
|
|
139
|
-
throw EMPTY_THREAD_ERROR;
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
cancel() {
|
|
143
|
-
// noop
|
|
144
|
-
},
|
|
145
|
-
|
|
146
|
-
queue: [] as never[],
|
|
147
|
-
moveQueueItem() {},
|
|
148
|
-
removeQueueItem() {},
|
|
149
|
-
|
|
150
|
-
dictation: undefined,
|
|
151
|
-
|
|
152
|
-
startDictation() {
|
|
153
|
-
throw EMPTY_THREAD_ERROR;
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
stopDictation() {
|
|
157
|
-
// noop
|
|
158
|
-
},
|
|
159
|
-
|
|
160
|
-
quote: undefined,
|
|
161
|
-
|
|
162
|
-
setQuote() {
|
|
163
|
-
throw EMPTY_THREAD_ERROR;
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
subscribe() {
|
|
167
|
-
return () => {};
|
|
168
|
-
},
|
|
169
|
-
|
|
170
|
-
unstable_on() {
|
|
171
|
-
return () => {};
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
getEditComposer() {
|
|
23
|
+
getMessageById() {
|
|
176
24
|
return undefined;
|
|
177
|
-
}
|
|
25
|
+
}
|
|
178
26
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
speech: undefined,
|
|
184
|
-
voice: undefined,
|
|
185
|
-
|
|
186
|
-
capabilities: {
|
|
187
|
-
switchToBranch: false,
|
|
188
|
-
switchBranchDuringRun: false,
|
|
189
|
-
edit: false,
|
|
190
|
-
delete: false,
|
|
191
|
-
reload: false,
|
|
192
|
-
refetchThread: false,
|
|
193
|
-
cancel: false,
|
|
194
|
-
unstable_copy: false,
|
|
195
|
-
speech: false,
|
|
196
|
-
dictation: false,
|
|
197
|
-
voice: false,
|
|
198
|
-
attachments: false,
|
|
199
|
-
feedback: false,
|
|
200
|
-
queue: false,
|
|
201
|
-
},
|
|
202
|
-
|
|
203
|
-
isDisabled: false,
|
|
204
|
-
isSendDisabled: false,
|
|
205
|
-
isLoading: true,
|
|
206
|
-
|
|
207
|
-
messages: [],
|
|
208
|
-
|
|
209
|
-
state: null,
|
|
210
|
-
|
|
211
|
-
suggestions: [],
|
|
212
|
-
|
|
213
|
-
extras: undefined,
|
|
214
|
-
|
|
215
|
-
subscribe() {
|
|
216
|
-
return () => {};
|
|
217
|
-
},
|
|
218
|
-
|
|
219
|
-
import() {
|
|
220
|
-
throw EMPTY_THREAD_ERROR;
|
|
221
|
-
},
|
|
27
|
+
getBranches() {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
222
30
|
|
|
223
31
|
export() {
|
|
224
32
|
return { messages: [] };
|
|
225
|
-
}
|
|
33
|
+
}
|
|
226
34
|
|
|
227
|
-
|
|
228
|
-
throw EMPTY_THREAD_ERROR;
|
|
229
|
-
},
|
|
230
|
-
|
|
231
|
-
unstable_on() {
|
|
35
|
+
override subscribe(): Unsubscribe {
|
|
232
36
|
return () => {};
|
|
233
|
-
}
|
|
234
|
-
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override waitForUpdate(): Promise<void> {
|
|
40
|
+
return Promise.reject(EMPTY_THREAD_ERROR);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const EMPTY_THREAD_CORE: ThreadRuntimeCore =
|
|
45
|
+
new EmptyThreadRuntimeCore();
|
|
@@ -60,4 +60,22 @@ describe("OptimisticState", () => {
|
|
|
60
60
|
|
|
61
61
|
expect(state.value.title).toBe("Project Beta");
|
|
62
62
|
});
|
|
63
|
+
|
|
64
|
+
it("drops an in-flight transform after reset", async () => {
|
|
65
|
+
const state = new OptimisticState({ title: "Untitled", extra: 0 });
|
|
66
|
+
const request = deferred();
|
|
67
|
+
const update = state.optimisticUpdate({
|
|
68
|
+
execute: () => request.promise,
|
|
69
|
+
optimistic: (value) => ({ ...value, title: "Pending" }),
|
|
70
|
+
then: (value) => ({ ...value, extra: 1 }),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
expect(state.value.title).toBe("Pending");
|
|
74
|
+
state.reset({ title: "Fresh", extra: 0 });
|
|
75
|
+
expect(state.value).toEqual({ title: "Fresh", extra: 0 });
|
|
76
|
+
|
|
77
|
+
request.resolve();
|
|
78
|
+
await update;
|
|
79
|
+
expect(state.value).toEqual({ title: "Fresh", extra: 0 });
|
|
80
|
+
});
|
|
63
81
|
});
|
|
@@ -48,6 +48,7 @@ export class OptimisticState<TState> extends BaseSubscribable {
|
|
|
48
48
|
[];
|
|
49
49
|
|
|
50
50
|
private _nextTransformOrder = 0;
|
|
51
|
+
private _epoch = 0;
|
|
51
52
|
|
|
52
53
|
private _baseValue: TState;
|
|
53
54
|
private _cachedValue: TState;
|
|
@@ -95,9 +96,20 @@ export class OptimisticState<TState> extends BaseSubscribable {
|
|
|
95
96
|
this._updateState();
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
public reset(state: TState): void {
|
|
100
|
+
// In-flight optimisticUpdate calls must not write into the replacement state.
|
|
101
|
+
this._epoch++;
|
|
102
|
+
this._pendingTransforms.length = 0;
|
|
103
|
+
this._completedOptimistics.length = 0;
|
|
104
|
+
this._baseValue = state;
|
|
105
|
+
this._cachedValue = state;
|
|
106
|
+
this._notifySubscribers();
|
|
107
|
+
}
|
|
108
|
+
|
|
98
109
|
public async optimisticUpdate<TResult>(
|
|
99
110
|
transform: Transform<TState, TResult>,
|
|
100
111
|
): Promise<TResult> {
|
|
112
|
+
const epoch = this._epoch;
|
|
101
113
|
const order = this._nextTransformOrder++;
|
|
102
114
|
const task = transform.execute();
|
|
103
115
|
const pendingTransform = {
|
|
@@ -110,6 +122,7 @@ export class OptimisticState<TState> extends BaseSubscribable {
|
|
|
110
122
|
this._updateState();
|
|
111
123
|
|
|
112
124
|
const result = await task;
|
|
125
|
+
if (epoch !== this._epoch) return result;
|
|
113
126
|
this._baseValue = pipeTransforms(this._baseValue, result, [
|
|
114
127
|
transform.optimistic,
|
|
115
128
|
transform.then,
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { ThreadMessage } from "../../types/message";
|
|
2
2
|
import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
|
|
3
3
|
import type { AssistantStream } from "assistant-stream";
|
|
4
|
+
import type { ThreadHistoryAdapter } from "../../adapters/thread-history";
|
|
5
|
+
import type { AttachmentAdapter } from "../../adapters/attachment";
|
|
6
|
+
import type { ModelContextProvider } from "../../model-context/types";
|
|
4
7
|
|
|
5
8
|
/* oxlint-disable typescript/no-explicit-any -- structural stand-in for ComponentType without depending on react types */
|
|
6
9
|
type RemoteThreadListProviderProps = { children?: any };
|
|
@@ -33,6 +36,12 @@ export type RemoteThreadListPageOptions = {
|
|
|
33
36
|
after?: string | undefined;
|
|
34
37
|
};
|
|
35
38
|
|
|
39
|
+
export type RuntimeAdapters = {
|
|
40
|
+
modelContext?: ModelContextProvider | undefined;
|
|
41
|
+
history?: ThreadHistoryAdapter | undefined;
|
|
42
|
+
attachments?: AttachmentAdapter | undefined;
|
|
43
|
+
};
|
|
44
|
+
|
|
36
45
|
export type RemoteThreadListAdapter = {
|
|
37
46
|
list(params?: RemoteThreadListPageOptions): Promise<RemoteThreadListResponse>;
|
|
38
47
|
|
|
@@ -56,16 +65,41 @@ export type RemoteThreadListAdapter = {
|
|
|
56
65
|
* inject per-thread context such as a history or attachments adapter (see
|
|
57
66
|
* `useCloudThreadListAdapter` for the canonical shape).
|
|
58
67
|
*
|
|
68
|
+
* `useRemoteThreadListRuntime` renders this component when present. If it
|
|
69
|
+
* is omitted, that host synthesizes a `RuntimeAdapterProvider` from
|
|
70
|
+
* `unstable_useAdapters`. The `RemoteThreadList` store entry ignores it;
|
|
71
|
+
* expose `unstable_useAdapters` for that host.
|
|
72
|
+
*
|
|
59
73
|
* The Provider must render `children` on its first commit; deferring them
|
|
60
74
|
* behind a loading state, a Suspense boundary, or a `useEffect`-gated render
|
|
61
75
|
* is unsupported and leaves thread context unavailable to downstream
|
|
62
76
|
* consumers. Load data inside an always-mounted child instead.
|
|
63
77
|
*/
|
|
64
78
|
unstable_Provider?: RemoteThreadListProviderComponent | undefined;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Hook the `RemoteThreadList` store entry calls once for the main-thread
|
|
82
|
+
* slot, then provides to the `thread` factory. This is not mounted per
|
|
83
|
+
* listed thread. `useRemoteThreadListRuntime` also calls it when
|
|
84
|
+
* `unstable_Provider` is omitted. Resolve `threadListItem` lazily on each
|
|
85
|
+
* adapter call; do not capture it at hook mount. The hook must keep a
|
|
86
|
+
* stable hook count across adapter swaps; a different count throws.
|
|
87
|
+
* Memoize the returned object.
|
|
88
|
+
*
|
|
89
|
+
* Per-thread history also requires the `thread` factory to be keyed by
|
|
90
|
+
* thread id (`withKey(id, thread(...))`). History loaders such as
|
|
91
|
+
* `useExternalHistory` run once per mount; an unkeyed factory keeps one
|
|
92
|
+
* instance across switches and the next thread's messages never load.
|
|
93
|
+
*/
|
|
94
|
+
unstable_useAdapters?: (() => RuntimeAdapters | null | undefined) | undefined;
|
|
65
95
|
};
|
|
66
96
|
|
|
67
97
|
export type RemoteThreadListOptions = {
|
|
68
98
|
runtimeHook: () => AssistantRuntime;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The adapter reference should remain stable across renders. Replacing it reloads the list and drops cached threads that are not in the replacement page. In-flight mutations from the previous adapter are cancelled.
|
|
102
|
+
*/
|
|
69
103
|
adapter: RemoteThreadListAdapter;
|
|
70
104
|
|
|
71
105
|
/**
|
|
@@ -10,6 +10,9 @@ observe via `setState(snapshot)` and what the current behavior is.
|
|
|
10
10
|
> first observation — args regress, args change after first completion,
|
|
11
11
|
> result is replaced, result is cleared, key order shuffles — the tracker
|
|
12
12
|
> never invokes the host's tool callback a second time.
|
|
13
|
+
>
|
|
14
|
+
> `reset()` starts a new execution boundary. A reused `toolCallId` in the
|
|
15
|
+
> next boundary gets a new execution identity and may fire once there.
|
|
13
16
|
|
|
14
17
|
This guarantees host-side side effects (the typical reason `streamCall` /
|
|
15
18
|
`execute` exists at all) can't double-run. The cost: post-completion
|
|
@@ -65,7 +68,7 @@ The tracker calls `setResponse` on the active controller and closes it.
|
|
|
65
68
|
The backend result is emitted before the args stream closes, so a stale
|
|
66
69
|
args parse failure cannot replace it. `reader.response.get()` resolves.
|
|
67
70
|
If the tool also had a frontend `execute`, the executor is short-circuited
|
|
68
|
-
via
|
|
71
|
+
via the entry's per-execution skip marker. Single fire.
|
|
69
72
|
|
|
70
73
|
### A.6. Previously-resolved tool's `result` is replaced
|
|
71
74
|
Silently ignored — `entry.hasResult` short-circuits both the
|
|
@@ -153,15 +156,16 @@ tracker's view of "what we last observed". The next snapshot retries.
|
|
|
153
156
|
|
|
154
157
|
### F.1. `reset()` called while `execute()` invocations are in flight
|
|
155
158
|
`abort()` is invoked, in-flight executions reject with
|
|
156
|
-
`Tool execution aborted`. Once they settle, the cleanup logic
|
|
157
|
-
`_executing`. The settled-resolver promises fire so
|
|
158
|
-
resolves.
|
|
159
|
+
`Tool execution aborted`. Once they settle, the cleanup logic removes their
|
|
160
|
+
execution identities from `_executing`. The settled-resolver promises fire so
|
|
161
|
+
the abort promise resolves.
|
|
159
162
|
|
|
160
163
|
### F.2. `setState` called during `reset()`'s in-flight abort
|
|
161
164
|
The new snapshot is processed against an empty `_entries`. Tool calls
|
|
162
165
|
in it are seeded as restored (because `reset()` re-armed
|
|
163
|
-
`_pendingRestore`). Eventual cancellation `result` chunks for the
|
|
164
|
-
|
|
166
|
+
`_pendingRestore`). Eventual cancellation `result` chunks for the aborted
|
|
167
|
+
executions are dropped when their execution identity no longer matches the
|
|
168
|
+
current entry.
|
|
165
169
|
|
|
166
170
|
### F.3. `resume(toolCallId, payload)` for an unknown id
|
|
167
171
|
Silently no-ops. (The pre-class hook *threw*; the tracker softens this
|
|
@@ -175,6 +179,13 @@ rebuilt pipeline does not re-fire `streamCall` for them) and the
|
|
|
175
179
|
snapshot is processed against the fresh pipeline. Repeated failures
|
|
176
180
|
keep the tracker dead with a visible error to avoid restart loops.
|
|
177
181
|
|
|
182
|
+
### F.5. Reset followed by same-id reuse
|
|
183
|
+
The assistant-stream pipeline assigns each streamed tool part an opaque
|
|
184
|
+
execution identity. Human-input callbacks, lifecycle callbacks, result chunks,
|
|
185
|
+
and pending execution cleanup are accepted only when that identity is still
|
|
186
|
+
current for the `toolCallId`. A late callback from before `reset()` is therefore
|
|
187
|
+
dropped even when the next session reuses the id.
|
|
188
|
+
|
|
178
189
|
## Known limitations
|
|
179
190
|
|
|
180
191
|
### Host callback throws
|
|
@@ -1172,3 +1172,246 @@ describe("ToolInvocationTracker", () => {
|
|
|
1172
1172
|
}
|
|
1173
1173
|
});
|
|
1174
1174
|
});
|
|
1175
|
+
|
|
1176
|
+
describe("ToolInvocationTracker reset", () => {
|
|
1177
|
+
const trackerWith = (tools: Record<string, Tool>) => {
|
|
1178
|
+
let statuses: Record<string, ToolExecutionStatus> = {};
|
|
1179
|
+
const tracker = new ToolInvocationTracker(() => tools, {
|
|
1180
|
+
onResult: vi.fn(),
|
|
1181
|
+
onStatusesChange: (s: ReadonlyMap<string, ToolExecutionStatus>) => {
|
|
1182
|
+
statuses = Object.fromEntries(s);
|
|
1183
|
+
},
|
|
1184
|
+
});
|
|
1185
|
+
return { tracker, statuses: () => statuses };
|
|
1186
|
+
};
|
|
1187
|
+
|
|
1188
|
+
it("clears statuses for discarded executions that never settle", async () => {
|
|
1189
|
+
const { tracker, statuses } = trackerWith({
|
|
1190
|
+
weatherSearch: {
|
|
1191
|
+
parameters: { type: "object", properties: {} },
|
|
1192
|
+
execute: vi.fn(() => new Promise(() => {})),
|
|
1193
|
+
} satisfies Tool,
|
|
1194
|
+
});
|
|
1195
|
+
tracker.setState(createState([]));
|
|
1196
|
+
tracker.setState(
|
|
1197
|
+
createState([
|
|
1198
|
+
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
1199
|
+
]),
|
|
1200
|
+
);
|
|
1201
|
+
await waitFor(() => {
|
|
1202
|
+
expect(statuses()["tool-1"]?.type).toBe("executing");
|
|
1203
|
+
});
|
|
1204
|
+
|
|
1205
|
+
tracker.reset();
|
|
1206
|
+
|
|
1207
|
+
expect(statuses()).toEqual({});
|
|
1208
|
+
|
|
1209
|
+
// A new-session snapshot restoring tool activity must not drag the
|
|
1210
|
+
// discarded id back in through the whole-map republication. The first
|
|
1211
|
+
// post-reset snapshot is the fresh session's empty state, consuming the
|
|
1212
|
+
// pending-restore mark.
|
|
1213
|
+
tracker.setState(createState([]));
|
|
1214
|
+
tracker.setState(
|
|
1215
|
+
createState([
|
|
1216
|
+
createAssistantMessage(
|
|
1217
|
+
'{"query":"Paris"}',
|
|
1218
|
+
{ query: "Paris" },
|
|
1219
|
+
{ toolCallId: "tool-2" },
|
|
1220
|
+
),
|
|
1221
|
+
]),
|
|
1222
|
+
);
|
|
1223
|
+
await waitFor(() => {
|
|
1224
|
+
expect(statuses()["tool-2"]?.type).toBe("executing");
|
|
1225
|
+
});
|
|
1226
|
+
expect(statuses()["tool-1"]).toBeUndefined();
|
|
1227
|
+
});
|
|
1228
|
+
|
|
1229
|
+
it("does not republish sibling statuses when a discarded execution settles after reset", async () => {
|
|
1230
|
+
const settled = Promise.withResolvers<void>();
|
|
1231
|
+
const { tracker, statuses } = trackerWith({
|
|
1232
|
+
weatherSearch: {
|
|
1233
|
+
parameters: { type: "object", properties: {} },
|
|
1234
|
+
execute: vi.fn(
|
|
1235
|
+
(_args, { abortSignal }: { abortSignal: AbortSignal }) =>
|
|
1236
|
+
new Promise((resolve) => {
|
|
1237
|
+
abortSignal.addEventListener("abort", () => {
|
|
1238
|
+
resolve({ ok: true });
|
|
1239
|
+
settled.resolve();
|
|
1240
|
+
});
|
|
1241
|
+
}),
|
|
1242
|
+
),
|
|
1243
|
+
} satisfies Tool,
|
|
1244
|
+
pressureSearch: {
|
|
1245
|
+
parameters: { type: "object", properties: {} },
|
|
1246
|
+
execute: vi.fn(() => new Promise(() => {})),
|
|
1247
|
+
} satisfies Tool,
|
|
1248
|
+
});
|
|
1249
|
+
tracker.setState(createState([]));
|
|
1250
|
+
tracker.setState(
|
|
1251
|
+
createState([
|
|
1252
|
+
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
1253
|
+
createAssistantMessage(
|
|
1254
|
+
'{"query":"London"}',
|
|
1255
|
+
{ query: "London" },
|
|
1256
|
+
{
|
|
1257
|
+
toolCallId: "tool-2",
|
|
1258
|
+
toolName: "pressureSearch",
|
|
1259
|
+
},
|
|
1260
|
+
),
|
|
1261
|
+
]),
|
|
1262
|
+
);
|
|
1263
|
+
await waitFor(() => {
|
|
1264
|
+
expect(statuses()["tool-1"]?.type).toBe("executing");
|
|
1265
|
+
expect(statuses()["tool-2"]?.type).toBe("executing");
|
|
1266
|
+
});
|
|
1267
|
+
|
|
1268
|
+
tracker.reset();
|
|
1269
|
+
expect(statuses()).toEqual({});
|
|
1270
|
+
|
|
1271
|
+
// The settle-after-abort of tool-1 is what could republish tool-2;
|
|
1272
|
+
// await it deterministically instead of sleeping.
|
|
1273
|
+
await settled.promise;
|
|
1274
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
1275
|
+
expect(statuses()).toEqual({});
|
|
1276
|
+
});
|
|
1277
|
+
|
|
1278
|
+
it("rejects a human-input request from a discarded execution without resurrecting its status", async () => {
|
|
1279
|
+
let humanFn: ((payload: unknown) => Promise<unknown>) | undefined;
|
|
1280
|
+
const { tracker, statuses } = trackerWith({
|
|
1281
|
+
weatherSearch: {
|
|
1282
|
+
parameters: { type: "object", properties: {} },
|
|
1283
|
+
execute: vi.fn(() => new Promise(() => {})),
|
|
1284
|
+
streamCall: vi.fn((_reader, { human }) => {
|
|
1285
|
+
humanFn = human;
|
|
1286
|
+
}),
|
|
1287
|
+
} satisfies Tool,
|
|
1288
|
+
});
|
|
1289
|
+
tracker.setState(createState([]));
|
|
1290
|
+
tracker.setState(
|
|
1291
|
+
createState([
|
|
1292
|
+
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
1293
|
+
]),
|
|
1294
|
+
);
|
|
1295
|
+
await waitFor(() => {
|
|
1296
|
+
expect(statuses()["tool-1"]?.type).toBe("executing");
|
|
1297
|
+
expect(humanFn).toBeDefined();
|
|
1298
|
+
});
|
|
1299
|
+
|
|
1300
|
+
tracker.reset();
|
|
1301
|
+
|
|
1302
|
+
await expect(humanFn!({ request: "approve" })).rejects.toThrow(
|
|
1303
|
+
"Tool execution aborted",
|
|
1304
|
+
);
|
|
1305
|
+
expect(statuses()).toEqual({});
|
|
1306
|
+
});
|
|
1307
|
+
|
|
1308
|
+
it("rejects a late human-input request when reset reuses the tool call id", async () => {
|
|
1309
|
+
const humanFns: ((payload: unknown) => Promise<unknown>)[] = [];
|
|
1310
|
+
const { tracker, statuses } = trackerWith({
|
|
1311
|
+
weatherSearch: {
|
|
1312
|
+
parameters: { type: "object", properties: {} },
|
|
1313
|
+
execute: vi.fn(() => new Promise(() => {})),
|
|
1314
|
+
streamCall: vi.fn((_reader, { human }) => {
|
|
1315
|
+
humanFns.push(human);
|
|
1316
|
+
}),
|
|
1317
|
+
} satisfies Tool,
|
|
1318
|
+
});
|
|
1319
|
+
|
|
1320
|
+
tracker.setState(createState([]));
|
|
1321
|
+
tracker.setState(
|
|
1322
|
+
createState([
|
|
1323
|
+
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
1324
|
+
]),
|
|
1325
|
+
);
|
|
1326
|
+
await waitFor(() => {
|
|
1327
|
+
expect(humanFns).toHaveLength(1);
|
|
1328
|
+
expect(statuses()["tool-1"]?.type).toBe("executing");
|
|
1329
|
+
});
|
|
1330
|
+
|
|
1331
|
+
tracker.reset();
|
|
1332
|
+
tracker.setState(createState([]));
|
|
1333
|
+
tracker.setState(
|
|
1334
|
+
createState([
|
|
1335
|
+
createAssistantMessage(
|
|
1336
|
+
'{"query":"Paris"}',
|
|
1337
|
+
{ query: "Paris" },
|
|
1338
|
+
{ toolCallId: "tool-1" },
|
|
1339
|
+
),
|
|
1340
|
+
]),
|
|
1341
|
+
);
|
|
1342
|
+
await waitFor(() => expect(humanFns).toHaveLength(2));
|
|
1343
|
+
|
|
1344
|
+
await expect(humanFns[0]!({ stale: true })).rejects.toThrow(
|
|
1345
|
+
"Tool execution aborted",
|
|
1346
|
+
);
|
|
1347
|
+
expect(statuses()["tool-1"]?.type).toBe("executing");
|
|
1348
|
+
|
|
1349
|
+
tracker.reset();
|
|
1350
|
+
});
|
|
1351
|
+
|
|
1352
|
+
it("drops a late result when reset reuses the tool call id", async () => {
|
|
1353
|
+
const executions: Array<{
|
|
1354
|
+
resolve: (value: { session: string }) => void;
|
|
1355
|
+
promise: Promise<{ session: string }>;
|
|
1356
|
+
}> = [];
|
|
1357
|
+
const onResult = vi.fn();
|
|
1358
|
+
const tracker = new ToolInvocationTracker(
|
|
1359
|
+
() => ({
|
|
1360
|
+
weatherSearch: {
|
|
1361
|
+
parameters: { type: "object", properties: {} },
|
|
1362
|
+
execute: vi.fn(
|
|
1363
|
+
(_args: unknown, { abortSignal }: { abortSignal: AbortSignal }) => {
|
|
1364
|
+
let resolveExecution!: (value: { session: string }) => void;
|
|
1365
|
+
const promise = new Promise<{ session: string }>((resolve) => {
|
|
1366
|
+
resolveExecution = resolve;
|
|
1367
|
+
});
|
|
1368
|
+
const execution = { promise, resolve: resolveExecution };
|
|
1369
|
+
abortSignal.addEventListener("abort", () => {
|
|
1370
|
+
execution.resolve({ session: "old" });
|
|
1371
|
+
});
|
|
1372
|
+
executions.push(execution);
|
|
1373
|
+
return promise;
|
|
1374
|
+
},
|
|
1375
|
+
),
|
|
1376
|
+
} satisfies Tool,
|
|
1377
|
+
}),
|
|
1378
|
+
{ onResult, onStatusesChange: vi.fn() },
|
|
1379
|
+
);
|
|
1380
|
+
|
|
1381
|
+
tracker.setState(createState([]));
|
|
1382
|
+
tracker.setState(
|
|
1383
|
+
createState([
|
|
1384
|
+
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
1385
|
+
]),
|
|
1386
|
+
);
|
|
1387
|
+
await waitFor(() => expect(executions).toHaveLength(1));
|
|
1388
|
+
|
|
1389
|
+
tracker.reset();
|
|
1390
|
+
tracker.setState(createState([]));
|
|
1391
|
+
tracker.setState(
|
|
1392
|
+
createState([
|
|
1393
|
+
createAssistantMessage(
|
|
1394
|
+
'{"query":"Paris"}',
|
|
1395
|
+
{ query: "Paris" },
|
|
1396
|
+
{ toolCallId: "tool-1" },
|
|
1397
|
+
),
|
|
1398
|
+
]),
|
|
1399
|
+
);
|
|
1400
|
+
await waitFor(() => expect(executions).toHaveLength(2));
|
|
1401
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1402
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
1403
|
+
|
|
1404
|
+
executions[1]!.resolve({ session: "new" });
|
|
1405
|
+
await waitFor(() => {
|
|
1406
|
+
expect(onResult).toHaveBeenCalledOnce();
|
|
1407
|
+
expect(onResult).toHaveBeenCalledWith(
|
|
1408
|
+
expect.objectContaining({
|
|
1409
|
+
toolCallId: "tool-1",
|
|
1410
|
+
result: { session: "new" },
|
|
1411
|
+
}),
|
|
1412
|
+
);
|
|
1413
|
+
});
|
|
1414
|
+
|
|
1415
|
+
tracker.reset();
|
|
1416
|
+
});
|
|
1417
|
+
});
|