@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
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
type ReadonlyJSONValue,
|
|
15
15
|
} from "assistant-stream/utils";
|
|
16
16
|
import { isJSONValueEqual } from "../../utils/json/is-json-equal";
|
|
17
|
-
import type { ThreadMessage } from "../../types/message";
|
|
17
|
+
import type { ThreadMessage, ToolCallMessagePart } from "../../types/message";
|
|
18
|
+
import { walkToolCallTree } from "../../runtime/utils/tool-call-tree";
|
|
18
19
|
|
|
19
20
|
const TOOL_EXECUTION_ID = Symbol.for("assistant-stream.tool-execution-id");
|
|
20
21
|
|
|
@@ -54,6 +55,7 @@ type ToolCallEntry = {
|
|
|
54
55
|
/** Active phase — chunks are flowing through `controller`. */
|
|
55
56
|
controller: ToolCallStreamController;
|
|
56
57
|
argsComplete: boolean;
|
|
58
|
+
clientOwned: boolean;
|
|
57
59
|
}
|
|
58
60
|
);
|
|
59
61
|
|
|
@@ -116,6 +118,9 @@ const getToolExecutionId = (value: object): symbol | undefined =>
|
|
|
116
118
|
export class ToolInvocationTracker {
|
|
117
119
|
private readonly _getTools: () => Record<string, Tool> | undefined;
|
|
118
120
|
private readonly _callbacks: ToolInvocationTracker.Callbacks;
|
|
121
|
+
private readonly _isClientToolCall:
|
|
122
|
+
| ((toolCall: ToolCallMessagePart) => boolean | undefined)
|
|
123
|
+
| undefined;
|
|
119
124
|
|
|
120
125
|
private readonly _entries = new Map<string, ToolCallEntry>();
|
|
121
126
|
private readonly _humanInput = new Map<
|
|
@@ -127,6 +132,13 @@ export class ToolInvocationTracker {
|
|
|
127
132
|
}
|
|
128
133
|
>();
|
|
129
134
|
private readonly _executing = new Set<symbol>();
|
|
135
|
+
/**
|
|
136
|
+
* Tool calls whose turn ended before they reached the executor. Held here
|
|
137
|
+
* rather than on the entry because an entry is rebuilt whenever a snapshot
|
|
138
|
+
* re-creates the call, and this is the one reason to skip that no later
|
|
139
|
+
* snapshot carries.
|
|
140
|
+
*/
|
|
141
|
+
private readonly _discardedToolCallIds = new Set<string>();
|
|
130
142
|
private readonly _settledResolvers: SettledResolver[] = [];
|
|
131
143
|
|
|
132
144
|
private _statuses = new Map<string, ToolExecutionStatus>();
|
|
@@ -143,10 +155,12 @@ export class ToolInvocationTracker {
|
|
|
143
155
|
/**
|
|
144
156
|
* Set when the assistant-stream pipeline has died (errored out via
|
|
145
157
|
* `.pipeTo(...).catch(...)`). The next `setState` re-initializes the
|
|
146
|
-
* pipeline and demotes
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
158
|
+
* pipeline and demotes each active entry that reached the executor to
|
|
159
|
+
* restored, so it survives the restart without re-firing `streamCall`.
|
|
160
|
+
* A restart is an execution boundary like `reset()`: an entry that had
|
|
161
|
+
* not reached it starts over and fires once there (F.4). Capped at a
|
|
162
|
+
* single auto-restart per session — repeated failures keep the tracker
|
|
163
|
+
* dead with a more visible error.
|
|
150
164
|
*/
|
|
151
165
|
private _pipelineDead = false;
|
|
152
166
|
private _pipelineRestartUsed = false;
|
|
@@ -154,9 +168,11 @@ export class ToolInvocationTracker {
|
|
|
154
168
|
constructor(
|
|
155
169
|
getTools: () => Record<string, Tool> | undefined,
|
|
156
170
|
callbacks: ToolInvocationTracker.Callbacks,
|
|
171
|
+
isClientToolCall?: (toolCall: ToolCallMessagePart) => boolean | undefined,
|
|
157
172
|
) {
|
|
158
173
|
this._getTools = getTools;
|
|
159
174
|
this._callbacks = callbacks;
|
|
175
|
+
this._isClientToolCall = isClientToolCall;
|
|
160
176
|
|
|
161
177
|
this._initPipeline();
|
|
162
178
|
}
|
|
@@ -222,10 +238,10 @@ export class ToolInvocationTracker {
|
|
|
222
238
|
*/
|
|
223
239
|
public setState(snapshot: ToolInvocationTracker.Snapshot): void {
|
|
224
240
|
try {
|
|
225
|
-
// Recover from a dead pipeline before processing anything.
|
|
226
|
-
//
|
|
227
|
-
// re-fire `streamCall` for
|
|
228
|
-
//
|
|
241
|
+
// Recover from a dead pipeline before processing anything. Entries
|
|
242
|
+
// that reached the executor are demoted to "restored" so the rebuilt
|
|
243
|
+
// pipeline does not re-fire `streamCall` for them; the rest start over
|
|
244
|
+
// across the boundary the restart opens (F.4).
|
|
229
245
|
if (this._pipelineDead) {
|
|
230
246
|
if (this._pipelineRestartUsed) {
|
|
231
247
|
// Already retried once and failed again. Stay dead.
|
|
@@ -291,6 +307,7 @@ export class ToolInvocationTracker {
|
|
|
291
307
|
try {
|
|
292
308
|
this._pendingRestore = true;
|
|
293
309
|
this._entries.clear();
|
|
310
|
+
this._discardedToolCallIds.clear();
|
|
294
311
|
this._lastSnapshot = null;
|
|
295
312
|
void this.abort();
|
|
296
313
|
// Statuses are cleared synchronously: discarded executions may never
|
|
@@ -310,8 +327,13 @@ export class ToolInvocationTracker {
|
|
|
310
327
|
/**
|
|
311
328
|
* Abort any in-flight `execute()` invocations. Resolves once all of them
|
|
312
329
|
* have settled (or immediately if none are running).
|
|
330
|
+
*
|
|
331
|
+
* `discardPending` additionally kills the calls that never reached the
|
|
332
|
+
* executor, for a caller ending the turn rather than interrupting it. The
|
|
333
|
+
* signal cannot reach those: they are waiting on the run to settle (A.10),
|
|
334
|
+
* and the settled snapshot arrives after this installs a fresh controller.
|
|
313
335
|
*/
|
|
314
|
-
public abort(): Promise<void> {
|
|
336
|
+
public abort(options?: { discardPending?: boolean }): Promise<void> {
|
|
315
337
|
try {
|
|
316
338
|
this._humanInput.forEach(({ reject }) => {
|
|
317
339
|
try {
|
|
@@ -323,6 +345,15 @@ export class ToolInvocationTracker {
|
|
|
323
345
|
});
|
|
324
346
|
this._humanInput.clear();
|
|
325
347
|
|
|
348
|
+
if (options?.discardPending) {
|
|
349
|
+
for (const [toolCallId, entry] of this._entries) {
|
|
350
|
+
if (!entry.controller) continue;
|
|
351
|
+
if (entry.argsComplete || entry.hasResult) continue;
|
|
352
|
+
this._discardedToolCallIds.add(toolCallId);
|
|
353
|
+
entry.skipExecute = true;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
326
357
|
this._ac.abort();
|
|
327
358
|
this._ac = new AbortController();
|
|
328
359
|
|
|
@@ -473,6 +504,8 @@ export class ToolInvocationTracker {
|
|
|
473
504
|
if (entry.skipExecute) return;
|
|
474
505
|
|
|
475
506
|
this._executing.add(executionId!);
|
|
507
|
+
// execute can park human() before onExecutionStart; preserve this execution's interrupt.
|
|
508
|
+
if (this._humanInput.get(toolCallId)?.executionId === executionId) return;
|
|
476
509
|
this._setStatus(toolCallId, { type: "executing" });
|
|
477
510
|
}
|
|
478
511
|
|
|
@@ -519,6 +552,7 @@ export class ToolInvocationTracker {
|
|
|
519
552
|
// The host already set the result (via the live snapshot's
|
|
520
553
|
// `setResponse` path). Suppress the executor's redundant emit.
|
|
521
554
|
if (entry?.hasResult) return;
|
|
555
|
+
if (entry.skipExecute) return;
|
|
522
556
|
|
|
523
557
|
this._invokeOnResult({
|
|
524
558
|
type: "add-tool-result",
|
|
@@ -576,31 +610,40 @@ export class ToolInvocationTracker {
|
|
|
576
610
|
|
|
577
611
|
// ──────────────── internal: snapshot processing ────────────────
|
|
578
612
|
|
|
579
|
-
private
|
|
580
|
-
|
|
581
|
-
|
|
613
|
+
private _warnProviderOwnedSkip(toolName: string, toolCallId: string): void {
|
|
614
|
+
if (process.env.NODE_ENV === "production") return;
|
|
615
|
+
if (this._getTools()?.[toolName]?.execute === undefined) return;
|
|
616
|
+
console.warn(
|
|
617
|
+
"[ToolInvocationTracker] the runtime reports this tool call as provider-owned, so the registered execute is skipped; the provider has to hand the call to the client for it to run (see EDGE_CASES.md A.9)",
|
|
618
|
+
{ toolCallId, toolName },
|
|
619
|
+
);
|
|
582
620
|
}
|
|
583
621
|
|
|
622
|
+
/**
|
|
623
|
+
* Closing the args stream hands the call to the client executor, so it may
|
|
624
|
+
* only happen once the provider can no longer speak about that call. The run
|
|
625
|
+
* ending is the only universal signal for that; an adapter that reports the
|
|
626
|
+
* call as client-owned has said it earlier, per call.
|
|
627
|
+
*/
|
|
584
628
|
private _shouldCloseArgsStream({
|
|
585
|
-
toolName,
|
|
586
629
|
argsText,
|
|
587
630
|
hasResult,
|
|
631
|
+
clientOwned,
|
|
588
632
|
}: {
|
|
589
|
-
toolName: string;
|
|
590
633
|
argsText: string;
|
|
591
634
|
hasResult: boolean;
|
|
635
|
+
clientOwned: boolean;
|
|
592
636
|
}): boolean {
|
|
593
637
|
if (hasResult) return true;
|
|
594
|
-
if (!
|
|
595
|
-
|
|
596
|
-
}
|
|
597
|
-
return isArgsTextComplete(argsText);
|
|
638
|
+
if (!isArgsTextComplete(argsText)) return false;
|
|
639
|
+
return clientOwned || !this._isRunning;
|
|
598
640
|
}
|
|
599
641
|
|
|
600
642
|
private _startActiveEntry(
|
|
601
643
|
toolCallId: string,
|
|
602
644
|
toolName: string,
|
|
603
645
|
skipExecute: boolean,
|
|
646
|
+
clientOwned: boolean,
|
|
604
647
|
): ToolCallEntry {
|
|
605
648
|
const toolCallController = this._controller.addToolCallPart({
|
|
606
649
|
toolName,
|
|
@@ -613,6 +656,7 @@ export class ToolInvocationTracker {
|
|
|
613
656
|
hasResult: false,
|
|
614
657
|
skipExecute,
|
|
615
658
|
argsComplete: false,
|
|
659
|
+
clientOwned,
|
|
616
660
|
};
|
|
617
661
|
this._entries.set(toolCallId, entry);
|
|
618
662
|
return entry;
|
|
@@ -628,6 +672,16 @@ export class ToolInvocationTracker {
|
|
|
628
672
|
private _demoteEntriesToRestored(): void {
|
|
629
673
|
for (const [toolCallId, entry] of this._entries) {
|
|
630
674
|
if (!entry.controller) continue;
|
|
675
|
+
if (!entry.argsComplete && !entry.hasResult) {
|
|
676
|
+
// The call never reached the executor. A restored entry is promoted
|
|
677
|
+
// only when its signature changes, and a call waiting on the run to
|
|
678
|
+
// settle already holds its final args, so demoting it would strand it
|
|
679
|
+
// unexecuted. Dropping it lets the next snapshot start it over; a call
|
|
680
|
+
// whose turn was discarded is held by `_discardedToolCallIds`, not by
|
|
681
|
+
// the entry, so starting over does not revive it.
|
|
682
|
+
this._entries.delete(toolCallId);
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
631
685
|
this._entries.set(toolCallId, {
|
|
632
686
|
toolName: entry.toolName,
|
|
633
687
|
argsText: entry.argsText,
|
|
@@ -682,9 +736,9 @@ export class ToolInvocationTracker {
|
|
|
682
736
|
isEquivalentCompleteArgsText(entry.argsText, content.argsText)
|
|
683
737
|
) {
|
|
684
738
|
const shouldClose = this._shouldCloseArgsStream({
|
|
685
|
-
toolName: content.toolName,
|
|
686
739
|
argsText: content.argsText,
|
|
687
740
|
hasResult,
|
|
741
|
+
clientOwned: entry.clientOwned,
|
|
688
742
|
});
|
|
689
743
|
if (shouldClose) entry.controller.argsText.close();
|
|
690
744
|
entry.argsText = content.argsText;
|
|
@@ -716,9 +770,9 @@ export class ToolInvocationTracker {
|
|
|
716
770
|
const delta = content.argsText.slice(entry.argsText.length);
|
|
717
771
|
entry.controller.argsText.append(delta);
|
|
718
772
|
const shouldClose = this._shouldCloseArgsStream({
|
|
719
|
-
toolName: content.toolName,
|
|
720
773
|
argsText: content.argsText,
|
|
721
774
|
hasResult,
|
|
775
|
+
clientOwned: entry.clientOwned,
|
|
722
776
|
});
|
|
723
777
|
if (shouldClose) entry.controller.argsText.close();
|
|
724
778
|
entry.argsText = content.argsText;
|
|
@@ -731,9 +785,9 @@ export class ToolInvocationTracker {
|
|
|
731
785
|
// gates on the streamed content; a divergent snapshot (A.2) can be
|
|
732
786
|
// complete while the controller still holds an incomplete stale prefix.
|
|
733
787
|
const shouldClose = this._shouldCloseArgsStream({
|
|
734
|
-
toolName: content.toolName,
|
|
735
788
|
argsText: entry.argsText,
|
|
736
789
|
hasResult,
|
|
790
|
+
clientOwned: entry.clientOwned,
|
|
737
791
|
});
|
|
738
792
|
if (shouldClose) {
|
|
739
793
|
entry.controller.argsText.close();
|
|
@@ -745,79 +799,81 @@ export class ToolInvocationTracker {
|
|
|
745
799
|
private _processMessages(messages: readonly ThreadMessage[]): void {
|
|
746
800
|
const isRestore = this._pendingRestore;
|
|
747
801
|
|
|
748
|
-
for (const
|
|
749
|
-
|
|
802
|
+
for (const { part: content } of walkToolCallTree(messages)) {
|
|
803
|
+
const existing = this._entries.get(content.toolCallId);
|
|
804
|
+
|
|
805
|
+
if (isRestore) {
|
|
806
|
+
// Don't overwrite an already-active entry (e.g. live tool-call
|
|
807
|
+
// observed before this restore snapshot landed). Restore can
|
|
808
|
+
// only seed entries the runtime has never seen.
|
|
809
|
+
if (!existing?.controller) {
|
|
810
|
+
this._entries.set(content.toolCallId, {
|
|
811
|
+
toolName: content.toolName,
|
|
812
|
+
argsText: content.argsText,
|
|
813
|
+
hasResult: content.result !== undefined,
|
|
814
|
+
});
|
|
815
|
+
}
|
|
750
816
|
continue;
|
|
751
817
|
}
|
|
752
|
-
for (const content of message.content as readonly ThreadMessage["content"][number][]) {
|
|
753
|
-
if (!content || content.type !== "tool-call") continue;
|
|
754
|
-
|
|
755
|
-
const existing = this._entries.get(content.toolCallId);
|
|
756
|
-
|
|
757
|
-
if (isRestore) {
|
|
758
|
-
// Don't overwrite an already-active entry (e.g. live tool-call
|
|
759
|
-
// observed before this restore snapshot landed). Restore can
|
|
760
|
-
// only seed entries the runtime has never seen.
|
|
761
|
-
if (!existing?.controller) {
|
|
762
|
-
this._entries.set(content.toolCallId, {
|
|
763
|
-
toolName: content.toolName,
|
|
764
|
-
argsText: content.argsText,
|
|
765
|
-
hasResult: content.result !== undefined,
|
|
766
|
-
});
|
|
767
|
-
}
|
|
768
|
-
if (content.messages) this._processMessages(content.messages);
|
|
769
|
-
continue;
|
|
770
|
-
}
|
|
771
818
|
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
819
|
+
// Live snapshot.
|
|
820
|
+
let entry = existing;
|
|
821
|
+
|
|
822
|
+
// A discarded id is remembered only until the call is answered, which
|
|
823
|
+
// bounds the set to the open calls of a discarded turn.
|
|
824
|
+
if (content.result !== undefined)
|
|
825
|
+
this._discardedToolCallIds.delete(content.toolCallId);
|
|
826
|
+
|
|
827
|
+
if (entry && !entry.controller) {
|
|
828
|
+
// Restored entry observed in a live snapshot. Promote if its
|
|
829
|
+
// signature has changed; otherwise treat as still-historical.
|
|
830
|
+
const signatureChanged =
|
|
831
|
+
content.argsText !== entry.argsText ||
|
|
832
|
+
(content.result !== undefined) !== entry.hasResult;
|
|
833
|
+
if (!signatureChanged) continue;
|
|
834
|
+
this._entries.delete(content.toolCallId);
|
|
835
|
+
entry = undefined;
|
|
836
|
+
}
|
|
788
837
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
);
|
|
795
|
-
|
|
838
|
+
if (!entry) {
|
|
839
|
+
const ownership = this._isClientToolCall?.(content);
|
|
840
|
+
const providerOwned =
|
|
841
|
+
content.result === undefined && ownership === false;
|
|
842
|
+
if (providerOwned)
|
|
843
|
+
this._warnProviderOwnedSkip(content.toolName, content.toolCallId);
|
|
844
|
+
entry = this._startActiveEntry(
|
|
845
|
+
content.toolCallId,
|
|
846
|
+
content.toolName,
|
|
847
|
+
content.result !== undefined ||
|
|
848
|
+
providerOwned ||
|
|
849
|
+
this._discardedToolCallIds.has(content.toolCallId),
|
|
850
|
+
ownership === true,
|
|
851
|
+
);
|
|
852
|
+
}
|
|
796
853
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
if (content.result !== undefined && !entry.hasResult) {
|
|
800
|
-
// `entry` is in active phase from this point — either just
|
|
801
|
-
// created by `_startActiveEntry`, or pre-existing with a live
|
|
802
|
-
// controller. Narrow once instead of asserting at every use.
|
|
803
|
-
const { controller: activeController } = entry;
|
|
804
|
-
if (!activeController) continue;
|
|
805
|
-
entry.hasResult = true;
|
|
806
|
-
entry.argsComplete = true;
|
|
807
|
-
activeController.setResponse(
|
|
808
|
-
new ToolResponse({
|
|
809
|
-
result: content.result as ReadonlyJSONValue,
|
|
810
|
-
artifact: content.artifact as ReadonlyJSONValue | undefined,
|
|
811
|
-
isError: content.isError,
|
|
812
|
-
...(content.modelContent !== undefined
|
|
813
|
-
? { modelContent: content.modelContent }
|
|
814
|
-
: {}),
|
|
815
|
-
}),
|
|
816
|
-
);
|
|
817
|
-
activeController.close();
|
|
818
|
-
}
|
|
854
|
+
if (content.approval !== undefined) entry.skipExecute = true;
|
|
819
855
|
|
|
820
|
-
|
|
856
|
+
this._processArgsText(entry, content);
|
|
857
|
+
|
|
858
|
+
if (content.result !== undefined && !entry.hasResult) {
|
|
859
|
+
// `entry` is in active phase from this point — either just
|
|
860
|
+
// created by `_startActiveEntry`, or pre-existing with a live
|
|
861
|
+
// controller. Narrow once instead of asserting at every use.
|
|
862
|
+
const { controller: activeController } = entry;
|
|
863
|
+
if (!activeController) continue;
|
|
864
|
+
entry.hasResult = true;
|
|
865
|
+
entry.argsComplete = true;
|
|
866
|
+
activeController.setResponse(
|
|
867
|
+
new ToolResponse({
|
|
868
|
+
result: content.result as ReadonlyJSONValue,
|
|
869
|
+
artifact: content.artifact as ReadonlyJSONValue | undefined,
|
|
870
|
+
isError: content.isError,
|
|
871
|
+
...(content.modelContent !== undefined
|
|
872
|
+
? { modelContent: content.modelContent }
|
|
873
|
+
: {}),
|
|
874
|
+
}),
|
|
875
|
+
);
|
|
876
|
+
activeController.close();
|
|
821
877
|
}
|
|
822
878
|
}
|
|
823
879
|
}
|
|
@@ -44,7 +44,12 @@ import type { ComposerSendOptions } from "../scopes/composer";
|
|
|
44
44
|
import { fileMatchesAccept } from "../../adapters/attachment";
|
|
45
45
|
import { getThreadMessageText } from "../../utils/text";
|
|
46
46
|
import { resolveToolApprovalResponse } from "../../runtime/utils/resolveToolApprovalResponse";
|
|
47
|
+
import {
|
|
48
|
+
AttachmentAddOperations,
|
|
49
|
+
drainAttachmentAdd,
|
|
50
|
+
} from "../../runtime/utils/attachment-add-operations";
|
|
47
51
|
import { toMessagePartStatus } from "../../utils/normalizePartStatus";
|
|
52
|
+
import { generateId } from "../../utils/id";
|
|
48
53
|
import { ModelContext } from "./model-context-client";
|
|
49
54
|
import { ThreadSuggestions } from "./suggestions";
|
|
50
55
|
import { Tools } from "../../react/client/Tools";
|
|
@@ -114,7 +119,9 @@ export type ExternalThreadProps = {
|
|
|
114
119
|
/** Branch adapter for runtimes that track sibling variants of messages. */
|
|
115
120
|
branches?: ExternalThreadBranchAdapter;
|
|
116
121
|
/** Callback for tool approval decisions. Absent: responding to an approval throws a capability error. */
|
|
117
|
-
onRespondToToolApproval?: (
|
|
122
|
+
onRespondToToolApproval?: (
|
|
123
|
+
options: RespondToToolApprovalOptions,
|
|
124
|
+
) => void | Promise<void>;
|
|
118
125
|
};
|
|
119
126
|
|
|
120
127
|
type MessageClientProps = {
|
|
@@ -126,7 +133,7 @@ type MessageClientProps = {
|
|
|
126
133
|
queue?: ExternalThreadQueueAdapter | undefined;
|
|
127
134
|
branches?: ExternalThreadBranchAdapter | undefined;
|
|
128
135
|
onRespondToToolApproval?:
|
|
129
|
-
| ((options: RespondToToolApprovalOptions) => void)
|
|
136
|
+
| ((options: RespondToToolApprovalOptions) => void | Promise<void>)
|
|
130
137
|
| undefined;
|
|
131
138
|
onAddToolResult?: ((options: AddToolResultOptions) => void) | undefined;
|
|
132
139
|
onResumeToolCall?: ((options: ResumeToolCallOptions) => void) | undefined;
|
|
@@ -309,7 +316,7 @@ type PartResourceProps = {
|
|
|
309
316
|
status: ToolCallMessagePartStatus;
|
|
310
317
|
messageId: string;
|
|
311
318
|
onRespondToToolApproval?:
|
|
312
|
-
| ((options: RespondToToolApprovalOptions) => void)
|
|
319
|
+
| ((options: RespondToToolApprovalOptions) => void | Promise<void>)
|
|
313
320
|
| undefined;
|
|
314
321
|
onAddToolResult?: ((options: AddToolResultOptions) => void) | undefined;
|
|
315
322
|
onResumeToolCall?: ((options: ResumeToolCallOptions) => void) | undefined;
|
|
@@ -378,9 +385,12 @@ const usePartResource = ({
|
|
|
378
385
|
)
|
|
379
386
|
throw new Error("Tool call has no pending approval");
|
|
380
387
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
388
|
+
const options = resolveToolApprovalResponse(part.approval, response);
|
|
389
|
+
try {
|
|
390
|
+
return Promise.resolve(onRespondToToolApproval(options));
|
|
391
|
+
} catch (error) {
|
|
392
|
+
return Promise.reject(error);
|
|
393
|
+
}
|
|
384
394
|
},
|
|
385
395
|
};
|
|
386
396
|
};
|
|
@@ -420,53 +430,6 @@ type ComposerClientResourceProps = {
|
|
|
420
430
|
attachmentAdapter?: AttachmentAdapter | undefined;
|
|
421
431
|
};
|
|
422
432
|
|
|
423
|
-
type AttachmentAddOperation = {
|
|
424
|
-
cancelled: boolean;
|
|
425
|
-
attachmentIds: Set<string>;
|
|
426
|
-
};
|
|
427
|
-
|
|
428
|
-
class AttachmentAddOperations {
|
|
429
|
-
private readonly operations = new Set<AttachmentAddOperation>();
|
|
430
|
-
|
|
431
|
-
start() {
|
|
432
|
-
const operation: AttachmentAddOperation = {
|
|
433
|
-
cancelled: false,
|
|
434
|
-
attachmentIds: new Set(),
|
|
435
|
-
};
|
|
436
|
-
this.operations.add(operation);
|
|
437
|
-
return operation;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
accept(operation: AttachmentAddOperation, attachmentId: string) {
|
|
441
|
-
if (operation.cancelled) return false;
|
|
442
|
-
operation.attachmentIds.add(attachmentId);
|
|
443
|
-
return true;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
finish(operation: AttachmentAddOperation) {
|
|
447
|
-
this.operations.delete(operation);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
isCancelled(operation: AttachmentAddOperation) {
|
|
451
|
-
return operation.cancelled;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
cancel(attachmentId: string) {
|
|
455
|
-
for (const operation of [...this.operations]) {
|
|
456
|
-
if (!operation.attachmentIds.has(attachmentId)) continue;
|
|
457
|
-
operation.cancelled = true;
|
|
458
|
-
this.operations.delete(operation);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
cancelAll() {
|
|
463
|
-
for (const operation of this.operations) {
|
|
464
|
-
operation.cancelled = true;
|
|
465
|
-
}
|
|
466
|
-
this.operations.clear();
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
433
|
const useQueueItemClient = ({
|
|
471
434
|
item,
|
|
472
435
|
onMove,
|
|
@@ -486,19 +449,6 @@ const useQueueItemClient = ({
|
|
|
486
449
|
|
|
487
450
|
const QueueItemClient = resource(useQueueItemClient);
|
|
488
451
|
|
|
489
|
-
const drainAdapterAdd = async (
|
|
490
|
-
result: ReturnType<AttachmentAdapter["add"]>,
|
|
491
|
-
upsert: (attachment: Attachment) => boolean,
|
|
492
|
-
) => {
|
|
493
|
-
if (Symbol.asyncIterator in result) {
|
|
494
|
-
for await (const attachment of result) {
|
|
495
|
-
if (!upsert(attachment)) break;
|
|
496
|
-
}
|
|
497
|
-
} else {
|
|
498
|
-
upsert(await result);
|
|
499
|
-
}
|
|
500
|
-
};
|
|
501
|
-
|
|
502
452
|
// State whose setter tracks the latest value in a ref, so imperative
|
|
503
453
|
// call sequences (setText immediately followed by send) observe the write
|
|
504
454
|
// before React re-renders — legacy composer parity.
|
|
@@ -672,7 +622,7 @@ const useComposerClientResource = ({
|
|
|
672
622
|
if (!isCreateAttachment(fileOrAttachment) && attachmentAdapter) {
|
|
673
623
|
const operation = attachmentAddOperations.start();
|
|
674
624
|
try {
|
|
675
|
-
await
|
|
625
|
+
await drainAttachmentAdd(
|
|
676
626
|
attachmentAdapter.add({ file: fileOrAttachment }),
|
|
677
627
|
(attachment) => {
|
|
678
628
|
if (!attachmentAddOperations.accept(operation, attachment.id))
|
|
@@ -688,7 +638,7 @@ const useComposerClientResource = ({
|
|
|
688
638
|
}
|
|
689
639
|
} else if (!isCreateAttachment(fileOrAttachment)) {
|
|
690
640
|
const newAttachment: Attachment = {
|
|
691
|
-
id:
|
|
641
|
+
id: generateId(),
|
|
692
642
|
type: "file",
|
|
693
643
|
name: fileOrAttachment.name,
|
|
694
644
|
contentType: fileOrAttachment.type,
|
|
@@ -699,7 +649,7 @@ const useComposerClientResource = ({
|
|
|
699
649
|
setAttachments((prev) => [...prev, newAttachment]);
|
|
700
650
|
} else {
|
|
701
651
|
const newAttachment: Attachment = {
|
|
702
|
-
id: fileOrAttachment.id ??
|
|
652
|
+
id: fileOrAttachment.id ?? generateId(),
|
|
703
653
|
type: fileOrAttachment.type ?? "document",
|
|
704
654
|
name: fileOrAttachment.name,
|
|
705
655
|
contentType: fileOrAttachment.contentType,
|
|
@@ -795,6 +745,17 @@ const useComposerClientResource = ({
|
|
|
795
745
|
}
|
|
796
746
|
},
|
|
797
747
|
cancel: () => {
|
|
748
|
+
// An edit session ends here, so its in-flight adapter adds must not
|
|
749
|
+
// land in a later session; the thread composer's cancel stops the run
|
|
750
|
+
// and leaves the draft (and its pending adds) alone.
|
|
751
|
+
if (type === "edit") {
|
|
752
|
+
attachmentAddOperations.cancelAll();
|
|
753
|
+
const removed = attachmentsRef.current;
|
|
754
|
+
setAttachments([]);
|
|
755
|
+
removePendingAttachments(removed).catch((error) => {
|
|
756
|
+
console.error("Failed to remove cancelled edit attachments", error);
|
|
757
|
+
});
|
|
758
|
+
}
|
|
798
759
|
onCancel?.();
|
|
799
760
|
if (type === "edit") setIsEditing(false);
|
|
800
761
|
},
|
|
@@ -93,7 +93,10 @@ const useSingleThreadList = ({
|
|
|
93
93
|
!(
|
|
94
94
|
typeof selector === "object" &&
|
|
95
95
|
"index" in selector &&
|
|
96
|
-
selector.index === 0
|
|
96
|
+
selector.index === 0 &&
|
|
97
|
+
// Index selectors address their archived/regular subset, and the
|
|
98
|
+
// archived subset here is always empty.
|
|
99
|
+
!selector.archived
|
|
97
100
|
)
|
|
98
101
|
) {
|
|
99
102
|
throw new Error(
|