@assistant-ui/core 0.3.15 → 0.3.17
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/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +8 -2
- package/dist/internal.js +9 -3
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +3 -2
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/frame/provider.d.ts +5 -0
- package/dist/model-context/frame/provider.d.ts.map +1 -1
- package/dist/model-context/frame/provider.js +141 -28
- package/dist/model-context/frame/provider.js.map +1 -1
- package/dist/model-context/interactable-composer-metadata.d.ts +1 -1
- package/dist/model-context/interactable-composer-metadata.js +1 -1
- package/dist/model-context/interactable-composer-metadata.js.map +1 -1
- package/dist/model-context/registry.d.ts +2 -2
- package/dist/model-context/registry.d.ts.map +1 -1
- package/dist/model-context/registry.js +9 -28
- package/dist/model-context/registry.js.map +1 -1
- package/dist/model-context/tool-call-text.d.ts +26 -0
- package/dist/model-context/tool-call-text.d.ts.map +1 -0
- package/dist/model-context/tool-call-text.js +18 -0
- package/dist/model-context/tool-call-text.js.map +1 -0
- package/dist/react/RuntimeAdapter.js +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/AdaptedRemoteThread.js +1 -1
- package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
- package/dist/react/client/InMemoryThreadList.js +25 -21
- package/dist/react/client/InMemoryThreadList.js.map +1 -1
- package/dist/react/client/Interactables.d.ts.map +1 -1
- package/dist/react/client/Interactables.js +60 -178
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/RemoteThreadList.d.ts +15 -0
- package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
- package/dist/react/client/RemoteThreadList.js +263 -194
- package/dist/react/client/RemoteThreadList.js.map +1 -1
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +6 -2
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/index.d.ts +4 -2
- package/dist/react/index.js +2 -1
- package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
- package/dist/react/interactables-legacy/Interactables.js +60 -178
- package/dist/react/interactables-legacy/Interactables.js.map +1 -1
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts +24 -0
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -0
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +138 -0
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -0
- package/dist/react/model-context/toolbox.d.ts +2 -14
- package/dist/react/model-context/toolbox.d.ts.map +1 -1
- package/dist/react/model-context/toolbox.js +1 -13
- package/dist/react/model-context/toolbox.js.map +1 -1
- package/dist/react/model-context/useAssistantContext.js +37 -7
- package/dist/react/model-context/useAssistantContext.js.map +1 -1
- package/dist/react/model-context/useAuiToolOverrides.js +31 -5
- package/dist/react/model-context/useAuiToolOverrides.js.map +1 -1
- package/dist/react/model-context/useInlineRender.d.ts.map +1 -1
- package/dist/react/model-context/useInlineRender.js +10 -36
- package/dist/react/model-context/useInlineRender.js.map +1 -1
- package/dist/react/primitive-hooks/useMessageError.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useMessageError.js +2 -8
- package/dist/react/primitive-hooks/useMessageError.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.js +2 -4
- package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
- package/dist/react/primitives/composer/ComposerAttachments.d.ts.map +1 -1
- package/dist/react/primitives/composer/ComposerAttachments.js +4 -3
- package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
- package/dist/react/primitives/composer/ComposerIf.js.map +1 -1
- package/dist/react/primitives/composer/ComposerQueue.d.ts +2 -1
- package/dist/react/primitives/composer/ComposerQueue.d.ts.map +1 -1
- package/dist/react/primitives/composer/ComposerQueue.js +4 -3
- package/dist/react/primitives/composer/ComposerQueue.js.map +1 -1
- package/dist/react/primitives/message/MessageAttachments.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageAttachments.js +7 -6
- package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.js +2 -2
- package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
- package/dist/react/primitives/message/MessageParts.js +3 -3
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/primitives/threadList/ThreadListItems.d.ts.map +1 -1
- package/dist/react/primitives/threadList/ThreadListItems.js +5 -4
- package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +7 -5
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +44 -22
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +7 -6
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +102 -117
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.d.ts +1 -6
- package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.js +3 -3
- package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
- package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -1
- package/dist/react/runtimes/assistant-transport/runManager.js +2 -12
- package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -1
- package/dist/react/runtimes/assistant-transport/useLatestRef.js +2 -2
- package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +3 -10
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +43 -85
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +5 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts +29 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +159 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.d.ts +12 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.d.ts.map +1 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.js +10 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.js.map +1 -0
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts +1 -9
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +16 -153
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -1
- package/dist/react/runtimes/createMessageConverter.d.ts +2 -1
- package/dist/react/runtimes/createMessageConverter.d.ts.map +1 -1
- package/dist/react/runtimes/external-message-converter.d.ts +6 -25
- package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
- package/dist/react/runtimes/external-message-converter.js +33 -233
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.js +14 -6
- package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
- package/dist/react/types/MessagePartComponentTypes.d.ts +7 -3
- package/dist/react/types/MessagePartComponentTypes.d.ts.map +1 -1
- package/dist/react/types/scopes/tools.d.ts +2 -0
- package/dist/react/types/scopes/tools.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.d.ts +1 -1
- package/dist/runtime/api/composer-runtime.js.map +1 -1
- package/dist/runtime/api/message-part-runtime.d.ts +2 -2
- package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-part-runtime.js +1 -1
- package/dist/runtime/api/message-part-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts +9 -1
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +5 -0
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +2 -3
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +14 -29
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +4 -6
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +5 -11
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +1 -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 +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/composer-runtime-core.d.ts +1 -1
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +14 -2
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +16 -2
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/internal.d.ts +2 -1
- package/dist/runtime/internal.js +2 -1
- package/dist/runtime/queue/external-thread-queue-adapter.d.ts +1 -1
- package/dist/runtime/queue/message-queue.d.ts.map +1 -1
- package/dist/runtime/queue/message-queue.js +1 -1
- package/dist/runtime/queue/message-queue.js.map +1 -1
- package/dist/runtime/queue/queue-item.d.ts +12 -0
- package/dist/runtime/queue/queue-item.d.ts.map +1 -0
- package/dist/runtime/queue/queue-item.js +6 -0
- package/dist/runtime/queue/queue-item.js.map +1 -0
- package/dist/runtime/utils/abortable-thread-load.d.ts +15 -0
- package/dist/runtime/utils/abortable-thread-load.d.ts.map +1 -0
- package/dist/runtime/utils/abortable-thread-load.js +35 -0
- package/dist/runtime/utils/abortable-thread-load.js.map +1 -0
- package/dist/runtime/utils/attachment-add-operations.d.ts +18 -0
- package/dist/runtime/utils/attachment-add-operations.d.ts.map +1 -0
- package/dist/runtime/utils/attachment-add-operations.js +43 -0
- package/dist/runtime/utils/attachment-add-operations.js.map +1 -0
- package/dist/runtime/utils/auto-status.d.ts +7 -2
- package/dist/runtime/utils/auto-status.d.ts.map +1 -1
- package/dist/runtime/utils/auto-status.js +13 -3
- package/dist/runtime/utils/auto-status.js.map +1 -1
- package/dist/runtime/utils/external-message-conversion.d.ts +48 -0
- package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -0
- package/dist/runtime/utils/external-message-conversion.js +222 -0
- package/dist/runtime/utils/external-message-conversion.js.map +1 -0
- package/dist/runtime/utils/external-store-message.d.ts +2 -1
- package/dist/runtime/utils/external-store-message.d.ts.map +1 -1
- package/dist/runtime/utils/external-store-message.js +2 -1
- package/dist/runtime/utils/external-store-message.js.map +1 -1
- package/dist/runtime/utils/message-repository-session.d.ts +30 -0
- package/dist/runtime/utils/message-repository-session.d.ts.map +1 -0
- package/dist/runtime/utils/message-repository-session.js +130 -0
- package/dist/runtime/utils/message-repository-session.js.map +1 -0
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +3 -4
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/pending-tool-calls.d.ts +20 -0
- package/dist/runtime/utils/pending-tool-calls.d.ts.map +1 -0
- package/dist/runtime/utils/pending-tool-calls.js +22 -0
- package/dist/runtime/utils/pending-tool-calls.js.map +1 -0
- package/dist/runtime/utils/resolveToolApprovalResponse.d.ts +6 -3
- package/dist/runtime/utils/resolveToolApprovalResponse.d.ts.map +1 -1
- package/dist/runtime/utils/resolveToolApprovalResponse.js +12 -3
- package/dist/runtime/utils/resolveToolApprovalResponse.js.map +1 -1
- package/dist/runtime/utils/thread-message-like.d.ts +3 -10
- package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
- package/dist/runtime/utils/thread-message-like.js.map +1 -1
- package/dist/runtime/utils/tool-call-tree.d.ts +39 -0
- package/dist/runtime/utils/tool-call-tree.d.ts.map +1 -0
- package/dist/runtime/utils/tool-call-tree.js +85 -0
- package/dist/runtime/utils/tool-call-tree.js.map +1 -0
- package/dist/runtimes/external-store/external-store-adapter.d.ts +29 -2
- package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +2 -5
- 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 +3 -10
- 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 +21 -2
- 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 +154 -46
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts +1 -1
- package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/inert/InertThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +4 -2
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +23 -3
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +12 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.js +107 -14
- package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
- package/dist/runtimes/remote-thread-list/title.d.ts +9 -0
- package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -0
- package/dist/runtimes/remote-thread-list/title.js +6 -0
- package/dist/runtimes/remote-thread-list/title.js.map +1 -0
- package/dist/runtimes/remote-thread-list/types.d.ts +6 -5
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +31 -8
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +98 -59
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/external-thread.d.ts +1 -1
- package/dist/store/clients/external-thread.d.ts.map +1 -1
- package/dist/store/clients/external-thread.js +85 -103
- package/dist/store/clients/external-thread.js.map +1 -1
- package/dist/store/clients/single-thread-list.d.ts.map +1 -1
- package/dist/store/clients/single-thread-list.js +2 -2
- package/dist/store/clients/single-thread-list.js.map +1 -1
- package/dist/store/clients/suggestions.d.ts.map +1 -1
- package/dist/store/clients/suggestions.js +33 -12
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/clients/thread-message-client.js +1 -1
- package/dist/store/clients/thread-selection-events.js +1 -1
- package/dist/store/index.d.ts +6 -3
- package/dist/store/index.js +2 -1
- package/dist/store/internal.d.ts +2 -2
- package/dist/store/internal.js +2 -2
- package/dist/store/primitive-predicates.d.ts +4 -1
- package/dist/store/primitive-predicates.d.ts.map +1 -1
- package/dist/store/primitive-predicates.js +9 -1
- package/dist/store/primitive-predicates.js.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js +1 -1
- package/dist/store/runtime-clients/message-runtime-client.js +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js +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 +124 -105
- package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +1 -1
- package/dist/store/runtime-clients/useSubscribable.d.ts +3 -1
- package/dist/store/runtime-clients/useSubscribable.d.ts.map +1 -1
- package/dist/store/runtime-clients/useSubscribable.js +1 -1
- package/dist/store/runtime-clients/useSubscribable.js.map +1 -1
- package/dist/store/scope-registration.d.ts +1 -1
- package/dist/store/scopes/composer.d.ts +2 -1
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/message.d.ts +1 -1
- package/dist/store/scopes/part.d.ts +6 -3
- package/dist/store/scopes/part.d.ts.map +1 -1
- package/dist/store/scopes/queue-item.d.ts +2 -9
- package/dist/store/scopes/queue-item.d.ts.map +1 -1
- package/dist/store/scopes/queue-item.js +0 -6
- package/dist/subscribable/subscribable.d.ts +8 -1
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/subscribable/subscribable.js +24 -16
- package/dist/subscribable/subscribable.js.map +1 -1
- package/dist/types/message.d.ts +47 -4
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js +7 -1
- package/dist/types/message.js.map +1 -1
- package/dist/utils/data-url.d.ts +14 -1
- package/dist/utils/data-url.d.ts.map +1 -1
- package/dist/utils/data-url.js +13 -1
- package/dist/utils/data-url.js.map +1 -1
- package/dist/utils/invoke-user-callback.d.ts +5 -0
- package/dist/utils/invoke-user-callback.d.ts.map +1 -0
- package/dist/utils/invoke-user-callback.js +19 -0
- package/dist/utils/invoke-user-callback.js.map +1 -0
- package/dist/utils/normalizePartStatus.js.map +1 -1
- package/package.json +12 -17
- package/src/index.ts +6 -1
- package/src/internal.ts +20 -0
- package/src/model-context/frame/host.test.ts +91 -7
- package/src/model-context/frame/host.ts +7 -2
- package/src/model-context/frame/provider.test.ts +484 -13
- package/src/model-context/frame/provider.ts +205 -35
- package/src/model-context/interactable-composer-metadata.ts +1 -1
- package/src/model-context/registry.test.ts +44 -0
- package/src/model-context/registry.ts +13 -35
- package/src/model-context/tool-call-text.test.ts +67 -0
- package/src/model-context/tool-call-text.ts +67 -0
- package/src/react/AssistantRuntimeProvider.test.tsx +66 -2
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +1 -3
- package/src/react/client/InMemoryThreadList.test.tsx +49 -0
- package/src/react/client/InMemoryThreadList.ts +7 -1
- package/src/react/client/Interactables.ts +19 -178
- package/src/react/client/RemoteThreadList.background.test.ts +384 -0
- package/src/react/client/RemoteThreadList.concurrent.test.tsx +274 -0
- package/src/react/client/RemoteThreadList.test.ts +369 -1
- package/src/react/client/RemoteThreadList.ts +320 -142
- package/src/react/client/Tools.ts +7 -1
- package/src/react/index.ts +4 -0
- package/src/react/interactables-legacy/Interactables.ts +20 -177
- package/src/react/interactables-shared/useInteractablePersistenceQueue.test.tsx +161 -0
- package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +206 -0
- package/src/react/model-context/modelContextHooks.test.tsx +131 -0
- package/src/react/model-context/toolbox.test.ts +9 -9
- package/src/react/model-context/toolbox.ts +9 -36
- package/src/react/model-context/useAssistantContext.ts +4 -2
- package/src/react/model-context/useAuiToolOverrides.ts +4 -2
- package/src/react/model-context/useInlineRender.test.tsx +48 -0
- package/src/react/model-context/useInlineRender.ts +14 -10
- package/src/react/primitive-hooks/useMessageError.ts +2 -19
- package/src/react/primitive-hooks/useThreadListLoadMore.ts +2 -3
- package/src/react/primitives/composer/ComposerAttachments.test.tsx +76 -0
- package/src/react/primitives/composer/ComposerAttachments.tsx +9 -4
- package/src/react/primitives/composer/ComposerQueue.test.tsx +72 -0
- package/src/react/primitives/composer/ComposerQueue.tsx +7 -4
- package/src/react/primitives/message/MessageAttachments.test.tsx +107 -37
- package/src/react/primitives/message/MessageAttachments.tsx +10 -7
- package/src/react/primitives/message/MessageGroupedParts.tsx +2 -2
- package/src/react/primitives/message/MessageParts.tsx +3 -3
- package/src/react/primitives/threadList/ThreadListItems.test.tsx +99 -0
- package/src/react/primitives/threadList/ThreadListItems.tsx +8 -5
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +94 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +72 -31
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +169 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +140 -124
- package/src/react/runtimes/RemoteThreadResource.ts +1 -4
- package/src/react/runtimes/assistant-transport/runManager.ts +4 -17
- package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +51 -2
- package/src/react/runtimes/assistant-transport/useLatestRef.ts +2 -2
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +45 -0
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +157 -1
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +82 -176
- package/src/react/runtimes/cloud/auiV0.ts +5 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +88 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +236 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.test.ts +37 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.ts +18 -0
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +90 -1
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +33 -238
- package/src/react/runtimes/external-message-converter.test.ts +0 -14
- package/src/react/runtimes/external-message-converter.test.tsx +77 -0
- package/src/react/runtimes/external-message-converter.ts +59 -481
- package/src/react/runtimes/useRemoteThreadListRuntime.concurrent.test.tsx +216 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.ts +24 -6
- package/src/react/types/MessagePartComponentTypes.ts +7 -3
- package/src/react/types/scopes/tools.ts +2 -0
- package/src/runtime/api/composer-runtime.ts +1 -1
- package/src/runtime/api/message-part-runtime.ts +3 -3
- package/src/runtime/api/message-runtime.test.ts +28 -1
- package/src/runtime/api/thread-list-runtime.ts +25 -1
- package/src/runtime/base/base-composer-runtime-core.ts +20 -40
- package/src/runtime/base/base-thread-runtime-core.test.ts +110 -3
- package/src/runtime/base/base-thread-runtime-core.ts +16 -15
- package/src/runtime/base/default-thread-composer-runtime-core.ts +1 -4
- package/src/runtime/interfaces/composer-runtime-core.ts +1 -1
- package/src/runtime/interfaces/thread-list-runtime-core.ts +20 -1
- package/src/runtime/interfaces/thread-runtime-core.ts +18 -2
- package/src/runtime/internal.ts +5 -0
- package/src/runtime/queue/external-thread-queue-adapter.ts +1 -1
- package/src/runtime/queue/message-queue.ts +1 -4
- package/src/runtime/queue/queue-item.ts +10 -0
- package/src/runtime/utils/abortable-thread-load.test.ts +87 -0
- package/src/runtime/utils/abortable-thread-load.ts +53 -0
- package/src/runtime/utils/attachment-add-operations.ts +59 -0
- package/src/runtime/utils/auto-status.test.ts +57 -0
- package/src/runtime/utils/auto-status.ts +46 -1
- package/src/runtime/utils/external-message-conversion.test.ts +210 -0
- package/src/runtime/utils/external-message-conversion.ts +510 -0
- package/src/runtime/utils/external-store-message.ts +2 -0
- package/src/runtime/utils/message-repository-session.test.ts +195 -0
- package/src/runtime/utils/message-repository-session.ts +176 -0
- package/src/runtime/utils/message-repository.ts +7 -4
- package/src/runtime/utils/pending-tool-calls.test.ts +57 -0
- package/src/runtime/utils/pending-tool-calls.ts +35 -0
- package/src/runtime/utils/resolveToolApprovalResponse.test.ts +73 -0
- package/src/runtime/utils/resolveToolApprovalResponse.ts +27 -6
- package/src/runtime/utils/thread-message-like.ts +4 -10
- package/src/runtime/utils/tool-call-tree.test.ts +191 -0
- package/src/runtime/utils/tool-call-tree.ts +97 -0
- package/src/runtimes/external-store/external-store-adapter.ts +38 -2
- package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +6 -14
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +231 -61
- package/src/runtimes/inert/InertThreadRuntimeCore.ts +1 -1
- package/src/runtimes/local/local-thread-runtime-core.test.ts +201 -4
- package/src/runtimes/local/local-thread-runtime-core.ts +53 -4
- package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +149 -0
- package/src/runtimes/remote-thread-list/remote-thread-state.ts +178 -16
- package/src/runtimes/remote-thread-list/title.ts +3 -0
- package/src/runtimes/remote-thread-list/types.ts +6 -5
- package/src/runtimes/tool-invocations/EDGE_CASES.md +125 -3
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +856 -102
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +145 -89
- package/src/store/clients/external-thread.ts +30 -69
- package/src/store/clients/single-thread-list.ts +4 -1
- package/src/store/clients/suggestions.test.ts +185 -0
- package/src/store/clients/suggestions.ts +42 -35
- package/src/store/index.ts +4 -0
- package/src/store/internal.ts +2 -0
- package/src/store/primitive-predicates.ts +35 -0
- package/src/store/runtime-clients/thread-list-runtime-client.ts +16 -2
- package/src/store/runtime-clients/useSubscribable.ts +8 -2
- package/src/store/scopes/message.ts +1 -1
- package/src/store/scopes/part.ts +6 -3
- package/src/store/scopes/queue-item.ts +2 -9
- package/src/subscribable/subscribable.test.ts +50 -0
- package/src/subscribable/subscribable.ts +33 -21
- package/src/tests/MessageRepository.test.ts +77 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +305 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +78 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-reload.test.ts +52 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +158 -0
- package/src/tests/external-store-optimistic-id.test.ts +79 -0
- package/src/tests/external-store-repository-instance.test.ts +166 -0
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +186 -16
- package/src/tests/external-store-thread-runtime-core.test.ts +642 -0
- package/src/tests/external-thread-attachments.test.tsx +258 -1
- package/src/tests/remote-thread-list-adapter-switch.test.ts +66 -1
- package/src/tests/single-thread-list-item.test.tsx +47 -0
- package/src/tests/thread-message-like.test.ts +39 -1
- package/src/tests/thread-switch-events.test.tsx +397 -2
- package/src/types/message.ts +58 -5
- package/src/utils/data-url.test.ts +52 -1
- package/src/utils/data-url.ts +21 -0
- package/src/utils/invoke-user-callback.test.ts +82 -0
- package/src/utils/invoke-user-callback.ts +31 -0
- package/src/utils/normalizePartStatus.ts +1 -1
- package/dist/store/scopes/queue-item.js.map +0 -1
|
@@ -2,27 +2,35 @@ import {
|
|
|
2
2
|
useCallback,
|
|
3
3
|
useEffect,
|
|
4
4
|
useMemo,
|
|
5
|
+
useRef,
|
|
5
6
|
useState,
|
|
6
7
|
useSyncExternalStore,
|
|
7
8
|
} from "react";
|
|
8
|
-
import { resource, withKey } from "@assistant-ui/tap";
|
|
9
|
+
import { resource, withKey, type ResourceElement } from "@assistant-ui/tap";
|
|
9
10
|
import type { ClientOutput } from "@assistant-ui/store";
|
|
10
11
|
import {
|
|
11
12
|
attachTransformScopes,
|
|
13
|
+
Derived,
|
|
14
|
+
useAssistantContextProvider,
|
|
15
|
+
useAssistantContextValue,
|
|
12
16
|
useClientLookup,
|
|
13
17
|
useClientResource,
|
|
18
|
+
useConfiguredAui,
|
|
14
19
|
} from "@assistant-ui/store/client";
|
|
15
20
|
import { isDevelopment, useThreadSelectionEvents } from "../../store/internal";
|
|
16
|
-
import { generateId } from "../../utils/id";
|
|
17
21
|
import { OptimisticState } from "../../runtimes/remote-thread-list/optimistic-state";
|
|
18
22
|
import {
|
|
19
23
|
classifyThreads,
|
|
24
|
+
createEmptyRemoteThreadState,
|
|
20
25
|
createThreadMappingId,
|
|
21
26
|
getThreadData,
|
|
22
27
|
normalizeCursor,
|
|
23
28
|
updateStatusReducer,
|
|
24
29
|
type RemoteThreadData,
|
|
25
30
|
type RemoteThreadState,
|
|
31
|
+
preserveMidLoadTransitions,
|
|
32
|
+
seedNewThread,
|
|
33
|
+
statusSnapshot,
|
|
26
34
|
} from "../../runtimes/remote-thread-list/remote-thread-state";
|
|
27
35
|
import type {
|
|
28
36
|
RemoteThreadInitializeResponse,
|
|
@@ -37,19 +45,11 @@ import {
|
|
|
37
45
|
type InMemoryThreadListProps,
|
|
38
46
|
} from "./InMemoryThreadList";
|
|
39
47
|
import { AdaptedRemoteThread } from "./AdaptedRemoteThread";
|
|
48
|
+
import { isTitleSourceMessage } from "../../runtimes/remote-thread-list/title";
|
|
40
49
|
|
|
41
50
|
const RESOLVED_PROMISE = Promise.resolve();
|
|
42
51
|
|
|
43
|
-
const EMPTY_LIST
|
|
44
|
-
isLoading: true,
|
|
45
|
-
isLoadingMore: false,
|
|
46
|
-
cursor: undefined,
|
|
47
|
-
newThreadId: undefined,
|
|
48
|
-
threadIds: [],
|
|
49
|
-
archivedThreadIds: [],
|
|
50
|
-
threadIdMap: {},
|
|
51
|
-
threadData: {},
|
|
52
|
-
};
|
|
52
|
+
const EMPTY_LIST = createEmptyRemoteThreadState();
|
|
53
53
|
|
|
54
54
|
export type RemoteThreadListProps = {
|
|
55
55
|
/**
|
|
@@ -68,6 +68,18 @@ export type RemoteThreadListProps = {
|
|
|
68
68
|
onSwitchToThread?: ((threadId: string) => void) | undefined;
|
|
69
69
|
onSwitchToNewThread?: (() => void) | undefined;
|
|
70
70
|
onDelete?: ((threadId: string) => void) | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Keeps every thread the session switched to mounted, so a run continues
|
|
73
|
+
* after the user switches away, per-item `isRunning` reflects background
|
|
74
|
+
* runs, and a freshly initialized thread generates its title automatically.
|
|
75
|
+
* A body unmounts on delete, detach, or an adapter replacement (`reload()`
|
|
76
|
+
* after swapping the adapter); visited threads otherwise stay mounted for
|
|
77
|
+
* the client's lifetime. Each body reads its own thread through the ambient
|
|
78
|
+
* `threadListItem` scope, and `unstable_useAdapters` runs once per mounted
|
|
79
|
+
* body. Off (the default), only the visible thread is mounted and a switch
|
|
80
|
+
* unmounts it. The mode is fixed at mount.
|
|
81
|
+
*/
|
|
82
|
+
backgroundThreads?: boolean | undefined;
|
|
71
83
|
};
|
|
72
84
|
|
|
73
85
|
const threadNotFoundError = (threadIdOrRemoteId: string, action: string) =>
|
|
@@ -91,46 +103,14 @@ const toInitializeResult = (
|
|
|
91
103
|
|
|
92
104
|
const applyTitleStream = async (
|
|
93
105
|
stream: Parameters<typeof AssistantMessageStream.fromAssistantStream>[0],
|
|
94
|
-
onTitle: (title: string | undefined) => void
|
|
106
|
+
onTitle: (title: string | undefined) => Promise<void>,
|
|
95
107
|
) => {
|
|
96
108
|
const messageStream = AssistantMessageStream.fromAssistantStream(stream);
|
|
97
109
|
for await (const result of messageStream) {
|
|
98
|
-
onTitle(result.parts.filter((part) => part.type === "text")[0]?.text);
|
|
110
|
+
await onTitle(result.parts.filter((part) => part.type === "text")[0]?.text);
|
|
99
111
|
}
|
|
100
112
|
};
|
|
101
113
|
|
|
102
|
-
const seedNewThread = (
|
|
103
|
-
state: RemoteThreadState,
|
|
104
|
-
): { id: string; state: RemoteThreadState } => {
|
|
105
|
-
let id: string;
|
|
106
|
-
do {
|
|
107
|
-
id = `__LOCALID_${generateId()}`;
|
|
108
|
-
} while (state.threadIdMap[id]);
|
|
109
|
-
const mappingId = createThreadMappingId(id);
|
|
110
|
-
return {
|
|
111
|
-
id,
|
|
112
|
-
state: {
|
|
113
|
-
...state,
|
|
114
|
-
newThreadId: id,
|
|
115
|
-
threadIdMap: {
|
|
116
|
-
...state.threadIdMap,
|
|
117
|
-
[id]: mappingId,
|
|
118
|
-
},
|
|
119
|
-
threadData: {
|
|
120
|
-
...state.threadData,
|
|
121
|
-
[mappingId]: {
|
|
122
|
-
status: "new",
|
|
123
|
-
id,
|
|
124
|
-
remoteId: undefined,
|
|
125
|
-
externalId: undefined,
|
|
126
|
-
title: undefined,
|
|
127
|
-
custom: undefined,
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
};
|
|
132
|
-
};
|
|
133
|
-
|
|
134
114
|
const useThreadListItemClient = (props: {
|
|
135
115
|
data: RemoteThreadData;
|
|
136
116
|
isRunning: boolean;
|
|
@@ -240,9 +220,96 @@ const isSameThread = (
|
|
|
240
220
|
return data !== undefined && itemMatchesId(data, listState, right);
|
|
241
221
|
};
|
|
242
222
|
|
|
223
|
+
const useRemoteThreadBody = ({
|
|
224
|
+
id,
|
|
225
|
+
status,
|
|
226
|
+
remoteId,
|
|
227
|
+
item,
|
|
228
|
+
thread,
|
|
229
|
+
}: {
|
|
230
|
+
id: string;
|
|
231
|
+
status: RemoteThreadData["status"];
|
|
232
|
+
remoteId: string | undefined;
|
|
233
|
+
item: (isRunning: boolean) => ResourceElement<ClientOutput<"threadListItem">>;
|
|
234
|
+
thread: ResourceElement<ClientOutput<"thread">>;
|
|
235
|
+
}): ClientOutput<"thread"> => {
|
|
236
|
+
const parent = useAssistantContextValue();
|
|
237
|
+
const [isRunning, setIsRunning] = useState(false);
|
|
238
|
+
// The item client is mounted inside the body and served to the subtree
|
|
239
|
+
// through a Derived scope, which keeps the graft on the derived-only (no
|
|
240
|
+
// nested client host) path; resolving `parent.threads` here instead would
|
|
241
|
+
// read the threads scope during its own construction.
|
|
242
|
+
const itemHandle = useClientResource(item(isRunning));
|
|
243
|
+
const { client } = useConfiguredAui(parent, {
|
|
244
|
+
threadListItem: Derived({
|
|
245
|
+
source: "threads",
|
|
246
|
+
query: { type: "id", id },
|
|
247
|
+
get: () => itemHandle.methods,
|
|
248
|
+
}),
|
|
249
|
+
});
|
|
250
|
+
// Auto-title arms only for a thread born "new" in this body's lifetime;
|
|
251
|
+
// threads loaded or fetched from the adapter already carry their title. The
|
|
252
|
+
// settled (non-optimistic) initialize is what writes remoteId, so its
|
|
253
|
+
// arrival is the initialization signal.
|
|
254
|
+
const bornNewRef = useRef(status === "new");
|
|
255
|
+
const titleFiredRef = useRef(false);
|
|
256
|
+
return useAssistantContextProvider(client, function useBoundRemoteBody() {
|
|
257
|
+
const body = useClientResource(thread);
|
|
258
|
+
const bodyRunning = body.state.isRunning === true;
|
|
259
|
+
useEffect(() => {
|
|
260
|
+
setIsRunning(bodyRunning);
|
|
261
|
+
}, [bodyRunning]);
|
|
262
|
+
const armed =
|
|
263
|
+
bornNewRef.current && !titleFiredRef.current && remoteId !== undefined;
|
|
264
|
+
const hasTitleSource =
|
|
265
|
+
armed &&
|
|
266
|
+
(
|
|
267
|
+
body.state.messages as readonly {
|
|
268
|
+
status?: { type: string } | undefined;
|
|
269
|
+
}[]
|
|
270
|
+
).some(isTitleSourceMessage);
|
|
271
|
+
useEffect(() => {
|
|
272
|
+
if (!hasTitleSource || titleFiredRef.current) return;
|
|
273
|
+
titleFiredRef.current = true;
|
|
274
|
+
client.threadListItem.generateTitle();
|
|
275
|
+
}, [hasTitleSource]);
|
|
276
|
+
return body.methods;
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const RemoteThreadBody = resource(useRemoteThreadBody);
|
|
281
|
+
|
|
282
|
+
// `thread("main")` keeps one identity across switches, like the single
|
|
283
|
+
// useClientResource slot it replaced: consumers (the ambient `thread` scope,
|
|
284
|
+
// captured clients) hold the facade while it delegates to whichever body is
|
|
285
|
+
// currently main. Publishing the target during commit keeps abandoned
|
|
286
|
+
// concurrent renders from changing the facade observed by committed consumers.
|
|
287
|
+
const useMainThreadFacade = (
|
|
288
|
+
current: ClientOutput<"thread">,
|
|
289
|
+
): ClientOutput<"thread"> => {
|
|
290
|
+
const currentRef = useRef(current);
|
|
291
|
+
useEffect(() => {
|
|
292
|
+
currentRef.current = current;
|
|
293
|
+
}, [current]);
|
|
294
|
+
const [facade] = useState(
|
|
295
|
+
() =>
|
|
296
|
+
new Proxy({} as ClientOutput<"thread">, {
|
|
297
|
+
get: (_, prop) =>
|
|
298
|
+
(currentRef.current as unknown as Record<PropertyKey, unknown>)[prop],
|
|
299
|
+
has: (_, prop) => prop in (currentRef.current as object),
|
|
300
|
+
ownKeys: () => Reflect.ownKeys(currentRef.current as object),
|
|
301
|
+
getOwnPropertyDescriptor: (_, prop) =>
|
|
302
|
+
Reflect.getOwnPropertyDescriptor(currentRef.current as object, prop),
|
|
303
|
+
}),
|
|
304
|
+
);
|
|
305
|
+
return facade;
|
|
306
|
+
};
|
|
307
|
+
|
|
243
308
|
const useRemoteThreadListView = ({
|
|
244
309
|
listState,
|
|
245
310
|
mainThreadId,
|
|
311
|
+
startedIds,
|
|
312
|
+
backgroundThreads,
|
|
246
313
|
threadFactory,
|
|
247
314
|
useAdapters,
|
|
248
315
|
onSwitchTo,
|
|
@@ -257,6 +324,8 @@ const useRemoteThreadListView = ({
|
|
|
257
324
|
}: {
|
|
258
325
|
listState: RemoteThreadState;
|
|
259
326
|
mainThreadId: string;
|
|
327
|
+
startedIds: readonly string[];
|
|
328
|
+
backgroundThreads: boolean;
|
|
260
329
|
threadFactory: RemoteThreadListProps["thread"];
|
|
261
330
|
useAdapters: RemoteThreadListAdapter["unstable_useAdapters"];
|
|
262
331
|
onSwitchTo: (
|
|
@@ -281,17 +350,102 @@ const useRemoteThreadListView = ({
|
|
|
281
350
|
}>;
|
|
282
351
|
onDetach: (threadId: string) => Promise<void>;
|
|
283
352
|
}) => {
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
353
|
+
const bodyIds = useMemo(() => {
|
|
354
|
+
if (!backgroundThreads) return [mainThreadId];
|
|
355
|
+
const seen = new Set<string>();
|
|
356
|
+
const seenRemoteIds = new Set<string>();
|
|
357
|
+
const ids: string[] = [];
|
|
358
|
+
for (const id of startedIds) {
|
|
359
|
+
const data = getThreadData(listState, id);
|
|
360
|
+
if (!data || seen.has(data.id)) continue;
|
|
361
|
+
if (data.remoteId !== undefined && seenRemoteIds.has(data.remoteId)) {
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
seen.add(data.id);
|
|
365
|
+
if (data.remoteId !== undefined) seenRemoteIds.add(data.remoteId);
|
|
366
|
+
ids.push(data.id);
|
|
367
|
+
}
|
|
368
|
+
return ids;
|
|
369
|
+
}, [backgroundThreads, listState, mainThreadId, startedIds]);
|
|
370
|
+
|
|
371
|
+
const itemElementFor = (data: RemoteThreadData, isRunning: boolean) =>
|
|
372
|
+
ThreadListItemClient({
|
|
373
|
+
data,
|
|
374
|
+
isRunning,
|
|
375
|
+
onSwitchTo: (options) =>
|
|
376
|
+
handleThreadListAction("switch", () => onSwitchTo(data.id, options)),
|
|
377
|
+
onRename: (title) =>
|
|
378
|
+
handleThreadListAction("rename", () => onRename(data.id, title)),
|
|
379
|
+
onUpdateCustom: (custom) =>
|
|
380
|
+
handleThreadListAction("update custom metadata", () =>
|
|
381
|
+
onUpdateCustom(data.id, custom),
|
|
382
|
+
),
|
|
383
|
+
onArchive: () =>
|
|
384
|
+
handleThreadListAction("archive", () => onArchive(data.id)),
|
|
385
|
+
onUnarchive: () =>
|
|
386
|
+
handleThreadListAction("unarchive", () => onUnarchive(data.id)),
|
|
387
|
+
onDelete: () => handleThreadListAction("delete", () => onDelete(data.id)),
|
|
388
|
+
onGenerateTitle: () =>
|
|
389
|
+
handleThreadListAction("generate title", () =>
|
|
390
|
+
onGenerateTitle(
|
|
391
|
+
data.id,
|
|
392
|
+
(backgroundThreads
|
|
393
|
+
? bodyStateOf(data.id)?.messages
|
|
394
|
+
: mainThreadClient.state.messages) as
|
|
395
|
+
| readonly ThreadMessage[]
|
|
396
|
+
| undefined,
|
|
397
|
+
),
|
|
398
|
+
),
|
|
399
|
+
onInitialize: () => onInitialize(data.id),
|
|
400
|
+
onDetach: () => handleThreadListAction("detach", () => onDetach(data.id)),
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
const bodies = useClientLookup(
|
|
404
|
+
bodyIds.map((id) => {
|
|
405
|
+
const made = threadFactory(id);
|
|
406
|
+
// Background bodies never change occupant, so an unkeyed factory
|
|
407
|
+
// element is keyed by the mapping id here; per-body history loads
|
|
408
|
+
// without requiring the factory to key itself.
|
|
409
|
+
const thread =
|
|
410
|
+
backgroundThreads && made.key === undefined ? withKey(id, made) : made;
|
|
411
|
+
const wrapped =
|
|
412
|
+
useAdapters === undefined
|
|
413
|
+
? thread
|
|
414
|
+
: AdaptedRemoteThread({
|
|
415
|
+
useAdapters,
|
|
416
|
+
thread,
|
|
417
|
+
});
|
|
418
|
+
const data = getThreadData(listState, id);
|
|
419
|
+
const element =
|
|
420
|
+
backgroundThreads && data !== undefined
|
|
421
|
+
? RemoteThreadBody({
|
|
422
|
+
id,
|
|
423
|
+
status: data.status,
|
|
424
|
+
remoteId: data.remoteId,
|
|
425
|
+
item: (isRunning) => itemElementFor(data, isRunning),
|
|
426
|
+
thread: wrapped,
|
|
427
|
+
})
|
|
428
|
+
: wrapped;
|
|
429
|
+
return withKey(backgroundThreads ? id : (made.key ?? "main"), element);
|
|
430
|
+
}),
|
|
294
431
|
);
|
|
432
|
+
// A reload can remap a local thread id to its remote identity while the
|
|
433
|
+
// body stays keyed by the original mapping id, so lookups fall back to
|
|
434
|
+
// remote-identity matching.
|
|
435
|
+
const bodyIndexOf = (id: string) => {
|
|
436
|
+
const direct = bodyIds.indexOf(id);
|
|
437
|
+
if (direct !== -1) return direct;
|
|
438
|
+
return bodyIds.findIndex((bodyId) => isSameThread(listState, bodyId, id));
|
|
439
|
+
};
|
|
440
|
+
const bodyStateOf = (id: string) => {
|
|
441
|
+
const index = bodyIndexOf(id);
|
|
442
|
+
return index === -1 ? undefined : bodies.state[index];
|
|
443
|
+
};
|
|
444
|
+
const mainIndex = bodyIndexOf(mainThreadId);
|
|
445
|
+
const mainThreadClient = {
|
|
446
|
+
state: bodies.state[mainIndex]!,
|
|
447
|
+
methods: useMainThreadFacade(bodies.get({ index: mainIndex })),
|
|
448
|
+
};
|
|
295
449
|
const itemOrder = useMemo(
|
|
296
450
|
() => collectItemOrder(listState, mainThreadId),
|
|
297
451
|
[listState, mainThreadId],
|
|
@@ -300,40 +454,13 @@ const useRemoteThreadListView = ({
|
|
|
300
454
|
itemOrder.map((data) =>
|
|
301
455
|
withKey(
|
|
302
456
|
data.id,
|
|
303
|
-
|
|
457
|
+
itemElementFor(
|
|
304
458
|
data,
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
onSwitchTo(data.id, options),
|
|
311
|
-
),
|
|
312
|
-
onRename: (title) =>
|
|
313
|
-
handleThreadListAction("rename", () => onRename(data.id, title)),
|
|
314
|
-
onUpdateCustom: (custom) =>
|
|
315
|
-
handleThreadListAction("update custom metadata", () =>
|
|
316
|
-
onUpdateCustom(data.id, custom),
|
|
317
|
-
),
|
|
318
|
-
onArchive: () =>
|
|
319
|
-
handleThreadListAction("archive", () => onArchive(data.id)),
|
|
320
|
-
onUnarchive: () =>
|
|
321
|
-
handleThreadListAction("unarchive", () => onUnarchive(data.id)),
|
|
322
|
-
onDelete: () =>
|
|
323
|
-
handleThreadListAction("delete", () => onDelete(data.id)),
|
|
324
|
-
onGenerateTitle: () =>
|
|
325
|
-
handleThreadListAction("generate title", () =>
|
|
326
|
-
onGenerateTitle(
|
|
327
|
-
data.id,
|
|
328
|
-
mainThreadClient.state.messages as
|
|
329
|
-
| readonly ThreadMessage[]
|
|
330
|
-
| undefined,
|
|
331
|
-
),
|
|
332
|
-
),
|
|
333
|
-
onInitialize: () => onInitialize(data.id),
|
|
334
|
-
onDetach: () =>
|
|
335
|
-
handleThreadListAction("detach", () => onDetach(data.id)),
|
|
336
|
-
}),
|
|
459
|
+
backgroundThreads
|
|
460
|
+
? (bodyStateOf(data.id)?.isRunning ?? false)
|
|
461
|
+
: itemMatchesId(data, listState, mainThreadId) &&
|
|
462
|
+
mainThreadClient.state.isRunning,
|
|
463
|
+
),
|
|
337
464
|
),
|
|
338
465
|
),
|
|
339
466
|
);
|
|
@@ -378,9 +505,6 @@ const useRemoteThreadList = (
|
|
|
378
505
|
};
|
|
379
506
|
});
|
|
380
507
|
|
|
381
|
-
// Config updates can invoke `reload()` in the same turn as the re-render, before the effect below runs.
|
|
382
|
-
session.adapter = adapter;
|
|
383
|
-
|
|
384
508
|
const listState = useSyncExternalStore(
|
|
385
509
|
(onStoreChange) => store.subscribe(onStoreChange),
|
|
386
510
|
() => store.value,
|
|
@@ -388,15 +512,21 @@ const useRemoteThreadList = (
|
|
|
388
512
|
);
|
|
389
513
|
|
|
390
514
|
const [mainThreadId, setMainThreadId] = useState(initialMainId);
|
|
515
|
+
const [startedIds, setStartedIds] = useState<readonly string[]>([
|
|
516
|
+
initialMainId,
|
|
517
|
+
]);
|
|
518
|
+
const [backgroundThreads] = useState(props.backgroundThreads === true);
|
|
391
519
|
const assignMainThreadId = useCallback(
|
|
392
520
|
(id: string) => {
|
|
393
521
|
session.mainThreadId = id;
|
|
394
522
|
setMainThreadId(id);
|
|
523
|
+
setStartedIds((prev) => (prev.includes(id) ? prev : [...prev, id]));
|
|
395
524
|
},
|
|
396
525
|
[session],
|
|
397
526
|
);
|
|
398
527
|
useThreadSelectionEvents(mainThreadId);
|
|
399
528
|
useEffect(() => {
|
|
529
|
+
// Publishing after commit keeps imperative actions on the adapter the committed tree renders with; an abandoned render must not reach them.
|
|
400
530
|
session.adapter = adapter;
|
|
401
531
|
session.mainThreadId = mainThreadId;
|
|
402
532
|
session.onThreadIdChange = onThreadIdChange;
|
|
@@ -424,34 +554,33 @@ const useRemoteThreadList = (
|
|
|
424
554
|
if (session.loadPromise) return session.loadPromise;
|
|
425
555
|
const generation = session.loadGeneration;
|
|
426
556
|
const adapter = session.adapter;
|
|
557
|
+
const statusAtRequest = statusSnapshot(store.baseValue);
|
|
427
558
|
session.loadPromise = store
|
|
428
559
|
.optimisticUpdate({
|
|
429
560
|
execute: () => adapter.list(),
|
|
430
|
-
loading: (state) =>
|
|
561
|
+
loading: (state) => {
|
|
562
|
+
if (generation !== session.loadGeneration) return state;
|
|
563
|
+
return { ...state, isLoading: true };
|
|
564
|
+
},
|
|
431
565
|
then: (state, page) => {
|
|
432
566
|
if (generation !== session.loadGeneration) return state;
|
|
433
567
|
session.adapterAtLoad = adapter;
|
|
434
568
|
const fresh = classifyThreads(page.threads, {
|
|
435
569
|
threadIds: [],
|
|
436
570
|
archivedThreadIds: [],
|
|
437
|
-
threadIdMap: {},
|
|
438
|
-
threadData: {},
|
|
571
|
+
threadIdMap: { ...state.threadIdMap },
|
|
572
|
+
threadData: { ...state.threadData },
|
|
439
573
|
});
|
|
440
|
-
|
|
574
|
+
const merged = {
|
|
441
575
|
...state,
|
|
442
576
|
isLoading: false,
|
|
443
577
|
cursor: normalizeCursor(page.nextCursor),
|
|
444
578
|
threadIds: fresh.threadIds,
|
|
445
579
|
archivedThreadIds: fresh.archivedThreadIds,
|
|
446
|
-
threadIdMap:
|
|
447
|
-
|
|
448
|
-
...fresh.threadIdMap,
|
|
449
|
-
},
|
|
450
|
-
threadData: {
|
|
451
|
-
...state.threadData,
|
|
452
|
-
...fresh.threadData,
|
|
453
|
-
},
|
|
580
|
+
threadIdMap: fresh.threadIdMap,
|
|
581
|
+
threadData: fresh.threadData,
|
|
454
582
|
};
|
|
583
|
+
return preserveMidLoadTransitions(merged, state, statusAtRequest);
|
|
455
584
|
},
|
|
456
585
|
})
|
|
457
586
|
.catch((error: unknown) => {
|
|
@@ -480,6 +609,7 @@ const useRemoteThreadList = (
|
|
|
480
609
|
const seeded = seedNewThread(EMPTY_LIST);
|
|
481
610
|
store.reset({ ...seeded.state, isLoading: true });
|
|
482
611
|
assignMainThreadId(seeded.id);
|
|
612
|
+
setStartedIds([seeded.id]);
|
|
483
613
|
notifyRemoteId(undefined, true);
|
|
484
614
|
} else {
|
|
485
615
|
store.update({
|
|
@@ -522,7 +652,10 @@ const useRemoteThreadList = (
|
|
|
522
652
|
const task = store
|
|
523
653
|
.optimisticUpdate({
|
|
524
654
|
execute: () => currentAdapter.list({ after: cursor }),
|
|
525
|
-
loading: (state) =>
|
|
655
|
+
loading: (state) => {
|
|
656
|
+
if (generation !== session.loadGeneration) return state;
|
|
657
|
+
return { ...state, isLoadingMore: true };
|
|
658
|
+
},
|
|
526
659
|
then: (state, page) => {
|
|
527
660
|
if (generation !== session.loadGeneration) return state;
|
|
528
661
|
const appended = classifyThreads(page.threads, {
|
|
@@ -640,22 +773,30 @@ const useRemoteThreadList = (
|
|
|
640
773
|
throw threadNotFoundError(threadIdOrRemoteId, "switching to it");
|
|
641
774
|
}
|
|
642
775
|
if (isSameThread(store.value, data.id, session.mainThreadId)) return;
|
|
643
|
-
|
|
644
|
-
|
|
776
|
+
|
|
777
|
+
const targetId = data.id;
|
|
778
|
+
let current: RemoteThreadData | undefined = data;
|
|
779
|
+
|
|
780
|
+
if (current.status === "archived" && options?.unarchive !== false) {
|
|
645
781
|
const { remoteId } = await current.initializeTask;
|
|
646
782
|
if (generation !== session.switchGeneration) return;
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
783
|
+
current = getThreadData(store.value, targetId);
|
|
784
|
+
if (current?.id !== targetId) return;
|
|
785
|
+
if (current.status === "archived") {
|
|
786
|
+
await store.optimisticUpdate({
|
|
787
|
+
execute: () => session.adapter.unarchive(remoteId),
|
|
788
|
+
optimistic: (state) =>
|
|
789
|
+
updateStatusReducer(state, targetId, "regular"),
|
|
790
|
+
});
|
|
791
|
+
if (generation !== session.switchGeneration) return;
|
|
792
|
+
current = getThreadData(store.value, targetId);
|
|
793
|
+
if (current?.id !== targetId) return;
|
|
794
|
+
}
|
|
654
795
|
}
|
|
655
796
|
if (generation !== session.switchGeneration) return;
|
|
656
|
-
assignMainThreadId(
|
|
657
|
-
notifyRemoteId(
|
|
658
|
-
session.onSwitchToThread?.(
|
|
797
|
+
assignMainThreadId(current.id);
|
|
798
|
+
notifyRemoteId(current.remoteId, emitThreadIdChange);
|
|
799
|
+
session.onSwitchToThread?.(current.id);
|
|
659
800
|
}),
|
|
660
801
|
[assignMainThreadId, notifyRemoteId, session, startSwitch, store],
|
|
661
802
|
);
|
|
@@ -764,21 +905,36 @@ const useRemoteThreadList = (
|
|
|
764
905
|
const data = getThreadData(state, threadId);
|
|
765
906
|
if (!data) return state;
|
|
766
907
|
const mappingId = createThreadMappingId(threadId);
|
|
908
|
+
// A list() response that landed while this initialize was in flight
|
|
909
|
+
// could not know the remote id yet, so it may have minted its own
|
|
910
|
+
// slot for it; that slot collapses into this one.
|
|
911
|
+
const listedMappingId = state.threadIdMap[remoteId];
|
|
912
|
+
const orphan =
|
|
913
|
+
listedMappingId !== undefined && listedMappingId !== mappingId
|
|
914
|
+
? state.threadData[listedMappingId]
|
|
915
|
+
: undefined;
|
|
916
|
+
|
|
917
|
+
const threadData = { ...state.threadData };
|
|
918
|
+
if (orphan !== undefined) delete threadData[listedMappingId!];
|
|
919
|
+
threadData[mappingId] = {
|
|
920
|
+
...data,
|
|
921
|
+
initializeTask: Promise.resolve({ remoteId, externalId }),
|
|
922
|
+
remoteId,
|
|
923
|
+
externalId,
|
|
924
|
+
} as RemoteThreadData;
|
|
925
|
+
|
|
926
|
+
const rewire = (ids: readonly string[]) =>
|
|
927
|
+
orphan === undefined ? ids : ids.filter((id) => id !== orphan.id);
|
|
928
|
+
|
|
767
929
|
return {
|
|
768
930
|
...state,
|
|
931
|
+
threadIds: rewire(state.threadIds),
|
|
932
|
+
archivedThreadIds: rewire(state.archivedThreadIds),
|
|
769
933
|
threadIdMap: {
|
|
770
934
|
...state.threadIdMap,
|
|
771
935
|
[remoteId]: mappingId,
|
|
772
936
|
},
|
|
773
|
-
threadData
|
|
774
|
-
...state.threadData,
|
|
775
|
-
[mappingId]: {
|
|
776
|
-
...data,
|
|
777
|
-
initializeTask: Promise.resolve({ remoteId, externalId }),
|
|
778
|
-
remoteId,
|
|
779
|
-
externalId,
|
|
780
|
-
},
|
|
781
|
-
},
|
|
937
|
+
threadData,
|
|
782
938
|
};
|
|
783
939
|
},
|
|
784
940
|
});
|
|
@@ -981,34 +1137,53 @@ const useRemoteThreadList = (
|
|
|
981
1137
|
}
|
|
982
1138
|
const { remoteId } = await data.initializeTask;
|
|
983
1139
|
requireAdapterGeneration(adapterGeneration);
|
|
984
|
-
if (
|
|
1140
|
+
if (
|
|
1141
|
+
!backgroundThreads &&
|
|
1142
|
+
!isSameThread(store.value, data.id, session.mainThreadId)
|
|
1143
|
+
) {
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
985
1146
|
if (!messages) return;
|
|
986
1147
|
const stream = await currentAdapter.generateTitle(remoteId, messages);
|
|
987
1148
|
requireAdapterGeneration(adapterGeneration);
|
|
988
|
-
await applyTitleStream(stream, (newTitle) => {
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1149
|
+
await applyTitleStream(stream, async (newTitle) => {
|
|
1150
|
+
await store.optimisticUpdate({
|
|
1151
|
+
execute: async () => {},
|
|
1152
|
+
optimistic: (state) => {
|
|
1153
|
+
if (adapterGeneration !== session.adapterGeneration) return state;
|
|
1154
|
+
const current = getThreadData(state, data.id);
|
|
1155
|
+
if (!current) return state;
|
|
1156
|
+
return {
|
|
1157
|
+
...state,
|
|
1158
|
+
threadData: {
|
|
1159
|
+
...state.threadData,
|
|
1160
|
+
[current.id]: {
|
|
1161
|
+
...current,
|
|
1162
|
+
title: newTitle,
|
|
1163
|
+
},
|
|
1164
|
+
},
|
|
1165
|
+
};
|
|
1001
1166
|
},
|
|
1002
1167
|
});
|
|
1003
1168
|
});
|
|
1004
1169
|
},
|
|
1005
|
-
[requireAdapterGeneration, session, store],
|
|
1170
|
+
[backgroundThreads, requireAdapterGeneration, session, store],
|
|
1171
|
+
);
|
|
1172
|
+
|
|
1173
|
+
const detach = useCallback(
|
|
1174
|
+
async (threadId: string) => {
|
|
1175
|
+
await ensureNotMain(threadId);
|
|
1176
|
+
setStartedIds((prev) => prev.filter((id) => id !== threadId));
|
|
1177
|
+
},
|
|
1178
|
+
[ensureNotMain],
|
|
1006
1179
|
);
|
|
1007
1180
|
|
|
1008
1181
|
const { mainThreadClient, itemOrder, threadListItems } =
|
|
1009
1182
|
useRemoteThreadListView({
|
|
1010
1183
|
listState,
|
|
1011
1184
|
mainThreadId,
|
|
1185
|
+
startedIds,
|
|
1186
|
+
backgroundThreads,
|
|
1012
1187
|
threadFactory,
|
|
1013
1188
|
useAdapters: adapter.unstable_useAdapters,
|
|
1014
1189
|
onSwitchTo: (id, options) => switchToThread(id, options),
|
|
@@ -1019,7 +1194,7 @@ const useRemoteThreadList = (
|
|
|
1019
1194
|
onDelete: (id) => deleteThread(id),
|
|
1020
1195
|
onGenerateTitle: (id, messages) => generateTitle(id, messages),
|
|
1021
1196
|
onInitialize: async (id) => toInitializeResult(await initialize(id)),
|
|
1022
|
-
onDetach: (id) =>
|
|
1197
|
+
onDetach: (id) => detach(id),
|
|
1023
1198
|
});
|
|
1024
1199
|
|
|
1025
1200
|
const mainRemoteId = getThreadData(listState, mainThreadId)?.remoteId;
|
|
@@ -1130,6 +1305,9 @@ const useRemoteThreadList = (
|
|
|
1130
1305
|
* and attachments come from `unstable_useAdapters`. `useRemoteThreadListRuntime`
|
|
1131
1306
|
* uses the same hook when `unstable_Provider` is omitted. Key the factory
|
|
1132
1307
|
* with `withKey` so history reloads when the visible thread changes.
|
|
1308
|
+
* With `backgroundThreads`, every visited thread stays mounted: runs continue
|
|
1309
|
+
* across switches, per-item `isRunning` is live, and freshly initialized
|
|
1310
|
+
* threads title themselves.
|
|
1133
1311
|
*/
|
|
1134
1312
|
export const RemoteThreadList = resource(useRemoteThreadList);
|
|
1135
1313
|
|
|
@@ -16,6 +16,7 @@ import type { Tool } from "assistant-stream";
|
|
|
16
16
|
import {
|
|
17
17
|
isStandaloneToolDisplay,
|
|
18
18
|
makeToolCallTextComponent,
|
|
19
|
+
type ToolCallText,
|
|
19
20
|
type Toolkit,
|
|
20
21
|
} from "../model-context/toolbox";
|
|
21
22
|
import type { ToolCallMessagePartComponent } from "../types/MessagePartComponentTypes";
|
|
@@ -59,12 +60,16 @@ const useTools = ({
|
|
|
59
60
|
(
|
|
60
61
|
toolName: string,
|
|
61
62
|
render: ToolCallMessagePartComponent,
|
|
62
|
-
options?: {
|
|
63
|
+
options?: {
|
|
64
|
+
standalone?: boolean;
|
|
65
|
+
renderText?: ToolCallText<any, any> | undefined;
|
|
66
|
+
},
|
|
63
67
|
) => {
|
|
64
68
|
// One registration object per call; identity is the removal key, so
|
|
65
69
|
// the per-name list stays correctly ref-counted across re-registers.
|
|
66
70
|
const registration = {
|
|
67
71
|
render,
|
|
72
|
+
renderText: options?.renderText,
|
|
68
73
|
standalone: options?.standalone ?? false,
|
|
69
74
|
};
|
|
70
75
|
|
|
@@ -105,6 +110,7 @@ const useTools = ({
|
|
|
105
110
|
unsubscribes.push(
|
|
106
111
|
setToolUI(toolName, render, {
|
|
107
112
|
standalone: isStandaloneToolDisplay(tool),
|
|
113
|
+
renderText: toolRenderText,
|
|
108
114
|
}),
|
|
109
115
|
);
|
|
110
116
|
}
|