@assistant-ui/core 0.3.16 → 0.3.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/attachment.d.ts.map +1 -1
- package/dist/adapters/attachment.js +5 -4
- package/dist/adapters/attachment.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +4 -2
- package/dist/internal.js +4 -2
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +10 -4
- 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 +101 -28
- package/dist/model-context/frame/provider.js.map +1 -1
- package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -1
- package/dist/model-context/interactable-composer-metadata.js +16 -9
- package/dist/model-context/interactable-composer-metadata.js.map +1 -1
- package/dist/model-context/registry.d.ts.map +1 -1
- package/dist/model-context/registry.js +3 -5
- 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/model-context/types.d.ts.map +1 -1
- package/dist/model-context/types.js +5 -4
- package/dist/model-context/types.js.map +1 -1
- 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 +63 -57
- 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 +25 -28
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/RemoteThreadList.d.ts +16 -0
- package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
- package/dist/react/client/RemoteThreadList.js +354 -242
- 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 +24 -18
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +2 -1
- package/dist/react/interactables-legacy/Interactables.js +246 -125
- package/dist/react/interactables-legacy/Interactables.js.map +1 -1
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -1
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +11 -9
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -1
- package/dist/react/model-context/makeAssistantTool.d.ts +2 -2
- package/dist/react/model-context/makeAssistantTool.js +1 -1
- package/dist/react/model-context/makeAssistantTool.js.map +1 -1
- 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/useAssistantTool.d.ts +2 -2
- package/dist/react/model-context/useAssistantTool.js +1 -1
- package/dist/react/model-context/useAssistantTool.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/model-context/useToolArgsStatus.d.ts.map +1 -1
- package/dist/react/model-context/useToolArgsStatus.js +2 -1
- package/dist/react/model-context/useToolArgsStatus.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/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 +6 -4
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +59 -29
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +11 -6
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +160 -143
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.d.ts +2 -6
- package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.js +15 -13
- package/dist/react/runtimes/RemoteThreadResource.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 +4 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +424 -52
- 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 +160 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.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/external-message-converter.js +1 -1
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreRuntime.js +75 -46
- package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.js +77 -29
- 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/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-item-runtime.d.ts +7 -3
- package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.js +2 -2
- package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts +12 -1
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +23 -14
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +5 -1
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +1 -1
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +16 -12
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -2
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +8 -7
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/composer-runtime-core.d.ts +12 -5
- package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +18 -3
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +15 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/utils/auto-status.d.ts +1 -1
- package/dist/runtime/utils/auto-status.d.ts.map +1 -1
- package/dist/runtime/utils/auto-status.js +6 -2
- package/dist/runtime/utils/auto-status.js.map +1 -1
- package/dist/runtime/utils/external-message-conversion.d.ts +3 -2
- package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -1
- package/dist/runtime/utils/external-message-conversion.js +5 -4
- package/dist/runtime/utils/external-message-conversion.js.map +1 -1
- package/dist/runtime/utils/message-repository.d.ts +1 -0
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +15 -6
- package/dist/runtime/utils/message-repository.js.map +1 -1
- 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 +2 -10
- package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
- package/dist/runtime/utils/thread-message-like.js +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.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +21 -27
- 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 +2 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +34 -28
- 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/internal.d.ts +2 -2
- package/dist/runtimes/internal.js +2 -2
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +3 -1
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +18 -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 +148 -43
- package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
- package/dist/runtimes/remote-thread-list/title-generation.d.ts +49 -0
- package/dist/runtimes/remote-thread-list/title-generation.d.ts.map +1 -0
- package/dist/runtimes/remote-thread-list/title-generation.js +197 -0
- package/dist/runtimes/remote-thread-list/title-generation.js.map +1 -0
- package/dist/runtimes/remote-thread-list/title.d.ts +11 -0
- package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -0
- package/dist/runtimes/remote-thread-list/title.js +14 -0
- package/dist/runtimes/remote-thread-list/title.js.map +1 -0
- package/dist/runtimes/remote-thread-list/types.d.ts +16 -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 +97 -60
- 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 +30 -7
- package/dist/store/clients/external-thread.js.map +1 -1
- package/dist/store/clients/model-context-client.d.ts.map +1 -1
- package/dist/store/clients/model-context-client.js +2 -1
- package/dist/store/clients/model-context-client.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 -1
- 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 +19 -6
- 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 +2 -1
- 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.d.ts +1 -0
- package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js +98 -62
- package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.d.ts +1 -0
- package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.js +221 -144
- package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js +2 -2
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js +128 -107
- package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +194 -122
- package/dist/store/runtime-clients/thread-runtime-client.js.map +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/scopes/composer.d.ts +10 -2
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/message.d.ts +30 -1
- package/dist/store/scopes/message.d.ts.map +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/thread-list-item.d.ts +2 -2
- package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
- package/dist/store/scopes/thread.d.ts +8 -0
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/dist/store/scopes/threads.d.ts +1 -0
- package/dist/store/scopes/threads.d.ts.map +1 -1
- 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/attachment.d.ts +2 -1
- package/dist/types/attachment.d.ts.map +1 -1
- package/dist/types/attachment.js +2 -1
- package/dist/types/attachment.js.map +1 -1
- package/dist/types/message.d.ts +40 -1
- 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/abortable-iterable.d.ts +19 -0
- package/dist/utils/abortable-iterable.d.ts.map +1 -0
- package/dist/utils/abortable-iterable.js +72 -0
- package/dist/utils/abortable-iterable.js.map +1 -0
- package/dist/utils/composite-context-provider.d.ts.map +1 -1
- package/dist/utils/composite-context-provider.js +20 -2
- package/dist/utils/composite-context-provider.js.map +1 -1
- package/dist/utils/record.d.ts +11 -0
- package/dist/utils/record.d.ts.map +1 -0
- package/dist/utils/record.js +12 -0
- package/dist/utils/record.js.map +1 -0
- package/package.json +12 -17
- package/src/adapters/attachment.test.ts +50 -1
- package/src/adapters/attachment.ts +7 -4
- package/src/index.ts +7 -1
- package/src/internal.ts +12 -0
- package/src/model-context/frame/host.test.ts +24 -0
- package/src/model-context/frame/host.ts +10 -4
- package/src/model-context/frame/provider.test.ts +288 -1
- package/src/model-context/frame/provider.ts +148 -30
- package/src/model-context/interactable-composer-metadata.test.ts +28 -0
- package/src/model-context/interactable-composer-metadata.ts +9 -3
- package/src/model-context/registry.test.ts +12 -0
- package/src/model-context/registry.ts +3 -2
- package/src/model-context/tool-call-text.test.ts +67 -0
- package/src/model-context/tool-call-text.ts +67 -0
- package/src/model-context/types.test.ts +25 -0
- package/src/model-context/types.ts +9 -4
- package/src/react/AssistantRuntimeProvider.test.tsx +66 -2
- package/src/react/RuntimeAdapter.test.ts +34 -0
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +1 -3
- package/src/react/client/InMemoryThreadList.ts +1 -0
- package/src/react/client/Interactables.test.ts +28 -0
- package/src/react/client/Interactables.ts +15 -13
- package/src/react/client/RemoteThreadList.background.test.ts +526 -0
- package/src/react/client/RemoteThreadList.concurrent.test.tsx +315 -0
- package/src/react/client/RemoteThreadList.test.ts +617 -3
- package/src/react/client/RemoteThreadList.ts +433 -167
- package/src/react/client/Tools.ts +29 -12
- package/src/react/index.ts +4 -0
- package/src/react/interactables-legacy/Interactables.ts +16 -16
- package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +9 -10
- package/src/react/model-context/makeAssistantTool.ts +2 -2
- 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/useAssistantTool.ts +2 -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/model-context/useToolArgsStatus.test.tsx +30 -0
- package/src/react/model-context/useToolArgsStatus.ts +2 -1
- 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.destroy.test.tsx +172 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +127 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +7 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +99 -35
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.load-error.test.ts +132 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +274 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +223 -152
- package/src/react/runtimes/RemoteThreadResource.test.ts +9 -0
- package/src/react/runtimes/RemoteThreadResource.ts +20 -16
- 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 +546 -5
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +546 -103
- package/src/react/runtimes/cloud/auiV0.ts +5 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +103 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +237 -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.ts +1 -0
- package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +41 -0
- package/src/react/runtimes/useExternalStoreRuntime.ts +10 -4
- package/src/react/runtimes/useLocalRuntime.test.tsx +20 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.concurrent.test.tsx +216 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.load-error.test.tsx +108 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.ts +57 -6
- package/src/react/types/MessagePartComponentTypes.ts +7 -3
- package/src/react/types/scopes/tools.ts +2 -0
- package/src/runtime/api/message-part-runtime.ts +3 -3
- package/src/runtime/api/message-runtime.test.ts +75 -0
- package/src/runtime/api/thread-list-item-runtime.ts +10 -3
- package/src/runtime/api/thread-list-runtime.ts +46 -12
- package/src/runtime/api/thread-runtime.test.ts +78 -0
- package/src/runtime/api/thread-runtime.ts +8 -1
- package/src/runtime/base/base-composer-runtime-core.ts +36 -8
- package/src/runtime/base/base-thread-runtime-core.test.ts +149 -4
- package/src/runtime/base/base-thread-runtime-core.ts +16 -8
- package/src/runtime/interfaces/composer-runtime-core.ts +10 -5
- package/src/runtime/interfaces/thread-list-runtime-core.ts +25 -2
- package/src/runtime/interfaces/thread-runtime-core.ts +17 -1
- package/src/runtime/utils/auto-status.test.ts +57 -0
- package/src/runtime/utils/auto-status.ts +13 -1
- package/src/runtime/utils/external-message-conversion.test.ts +165 -0
- package/src/runtime/utils/external-message-conversion.ts +18 -2
- package/src/runtime/utils/message-repository.ts +29 -17
- 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 +3 -11
- 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 +18 -13
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +56 -33
- package/src/runtimes/inert/InertThreadRuntimeCore.ts +1 -1
- package/src/runtimes/internal.ts +1 -0
- package/src/runtimes/local/local-thread-runtime-core.test.ts +29 -3
- package/src/runtimes/local/local-thread-runtime-core.ts +5 -1
- package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +238 -0
- package/src/runtimes/remote-thread-list/remote-thread-state.ts +223 -44
- package/src/runtimes/remote-thread-list/title-generation.test.ts +602 -0
- package/src/runtimes/remote-thread-list/title-generation.ts +329 -0
- package/src/runtimes/remote-thread-list/title.test.ts +62 -0
- package/src/runtimes/remote-thread-list/title.ts +16 -0
- package/src/runtimes/remote-thread-list/types.ts +16 -5
- package/src/runtimes/tool-invocations/EDGE_CASES.md +110 -5
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +750 -136
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +144 -91
- package/src/store/clients/external-thread.ts +62 -11
- package/src/store/clients/model-context-client.ts +5 -1
- package/src/store/clients/single-thread-list.ts +1 -0
- package/src/store/clients/suggestions.test.ts +195 -1
- package/src/store/clients/suggestions.ts +45 -34
- 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/composer-runtime-client.ts +42 -9
- package/src/store/runtime-clients/message-runtime-client.ts +54 -6
- package/src/store/runtime-clients/thread-list-item-runtime-client.ts +4 -2
- package/src/store/runtime-clients/thread-list-runtime-client.ts +17 -2
- package/src/store/runtime-clients/thread-runtime-client.ts +58 -10
- package/src/store/runtime-clients/useSubscribable.ts +8 -2
- package/src/store/scopes/composer.ts +16 -4
- package/src/store/scopes/message.ts +14 -0
- package/src/store/scopes/part.ts +6 -3
- package/src/store/scopes/thread-list-item.ts +5 -2
- package/src/store/scopes/thread.ts +4 -0
- package/src/store/scopes/threads.ts +1 -0
- package/src/subscribable/subscribable.test.ts +50 -0
- package/src/subscribable/subscribable.ts +33 -21
- package/src/tests/MessageRepository.test.ts +116 -0
- package/src/tests/OptimisticState-list-race.test.ts +1 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-initialize-adapter-change.test.ts +38 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +158 -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 +89 -0
- package/src/tests/attachment-adapters.test.ts +14 -0
- package/src/tests/base-composer-runtime-core.test.ts +39 -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-list-runtime-core.test.ts +83 -0
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +49 -34
- package/src/tests/external-thread-attachments.test.tsx +224 -1
- package/src/tests/external-thread-parity.test.tsx +23 -0
- package/src/tests/remote-thread-list-adapter-switch.test.ts +66 -1
- package/src/tests/remote-thread-list-isLoading.test.ts +1 -0
- package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
- package/src/tests/thread-switch-events.test.tsx +475 -2
- package/src/tests/tools-scope-migration.test.tsx +28 -0
- package/src/types/attachment.ts +4 -0
- package/src/types/message.ts +50 -2
- package/src/utils/abortable-iterable.test.ts +213 -0
- package/src/utils/abortable-iterable.ts +93 -0
- package/src/utils/composite-context-provider.test.ts +25 -0
- package/src/utils/composite-context-provider.ts +23 -2
- package/src/utils/record.test.ts +48 -0
- package/src/utils/record.ts +11 -0
|
@@ -76,6 +76,16 @@ const createAssistantMessage = (
|
|
|
76
76
|
],
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
+
/**
|
|
80
|
+
* The stream failure that sets this flag cannot be provoked through the public
|
|
81
|
+
* API: `unstable_toolResultStream` turns a throwing tool into an error result
|
|
82
|
+
* rather than an error chunk, so the transform never rejects. The recovery
|
|
83
|
+
* branch it guards is reachable on its own.
|
|
84
|
+
*/
|
|
85
|
+
const killPipeline = (tracker: ToolInvocationTracker) => {
|
|
86
|
+
(tracker as unknown as { _pipelineDead: boolean })._pipelineDead = true;
|
|
87
|
+
};
|
|
88
|
+
|
|
79
89
|
describe("ToolInvocationTracker", () => {
|
|
80
90
|
it("does not crash and does not re-fire streamCall when tool argsText regresses mid-stream", async () => {
|
|
81
91
|
// The tracker holds the contract: streamCall fires exactly once per
|
|
@@ -237,6 +247,96 @@ describe("ToolInvocationTracker", () => {
|
|
|
237
247
|
}
|
|
238
248
|
});
|
|
239
249
|
|
|
250
|
+
it("keeps a human-input interrupt that execute requests before its first await", async () => {
|
|
251
|
+
const execute = vi.fn(async (_args, { human }) => ({
|
|
252
|
+
approved: (await human({ request: "approve" })) === true,
|
|
253
|
+
}));
|
|
254
|
+
const getTools = () => ({
|
|
255
|
+
weatherSearch: {
|
|
256
|
+
parameters: { type: "object", properties: {} },
|
|
257
|
+
execute,
|
|
258
|
+
} satisfies Tool,
|
|
259
|
+
});
|
|
260
|
+
const onResult = vi.fn();
|
|
261
|
+
let statuses: Record<string, ToolExecutionStatus> = {};
|
|
262
|
+
const onStatusesChange = (s: ReadonlyMap<string, ToolExecutionStatus>) => {
|
|
263
|
+
statuses = Object.fromEntries(s);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const tracker = new ToolInvocationTracker(getTools, {
|
|
267
|
+
onResult,
|
|
268
|
+
onStatusesChange,
|
|
269
|
+
});
|
|
270
|
+
tracker.setState(createState([], false));
|
|
271
|
+
tracker.setState(
|
|
272
|
+
createState(
|
|
273
|
+
[createAssistantMessage('{"query":"London"}', { query: "London" })],
|
|
274
|
+
false,
|
|
275
|
+
),
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
await waitFor(() => {
|
|
279
|
+
expect(statuses["tool-1"]?.type).toBe("interrupt");
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
expect(tracker.resume("tool-1", true)).toBe(true);
|
|
283
|
+
|
|
284
|
+
await waitFor(() => {
|
|
285
|
+
expect(onResult).toHaveBeenCalledWith(
|
|
286
|
+
expect.objectContaining({
|
|
287
|
+
toolCallId: "tool-1",
|
|
288
|
+
result: { approved: true },
|
|
289
|
+
}),
|
|
290
|
+
);
|
|
291
|
+
});
|
|
292
|
+
expect(statuses).toEqual({});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it("marks a fresh execution as executing when an earlier one left a human-input request behind", async () => {
|
|
296
|
+
const execute = vi
|
|
297
|
+
.fn()
|
|
298
|
+
.mockImplementationOnce((_args, { human }) =>
|
|
299
|
+
human({ request: "approve" }),
|
|
300
|
+
)
|
|
301
|
+
.mockImplementationOnce(() => new Promise(() => {}));
|
|
302
|
+
const getTools = () => ({
|
|
303
|
+
weatherSearch: {
|
|
304
|
+
parameters: { type: "object", properties: {} },
|
|
305
|
+
execute,
|
|
306
|
+
} satisfies Tool,
|
|
307
|
+
});
|
|
308
|
+
let statuses: Record<string, ToolExecutionStatus> = {};
|
|
309
|
+
const tracker = new ToolInvocationTracker(getTools, {
|
|
310
|
+
onResult: vi.fn(),
|
|
311
|
+
onStatusesChange: (s: ReadonlyMap<string, ToolExecutionStatus>) => {
|
|
312
|
+
statuses = Object.fromEntries(s);
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
tracker.setState(createState([], false));
|
|
316
|
+
tracker.setState(
|
|
317
|
+
createState(
|
|
318
|
+
[createAssistantMessage('{"query":"London"}', { query: "London" })],
|
|
319
|
+
false,
|
|
320
|
+
),
|
|
321
|
+
);
|
|
322
|
+
await waitFor(() => {
|
|
323
|
+
expect(statuses["tool-1"]?.type).toBe("interrupt");
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
killPipeline(tracker);
|
|
327
|
+
tracker.setState(
|
|
328
|
+
createState(
|
|
329
|
+
[createAssistantMessage('{"query":"Paris"}', { query: "Paris" })],
|
|
330
|
+
false,
|
|
331
|
+
),
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
await waitFor(() => {
|
|
335
|
+
expect(execute).toHaveBeenCalledTimes(2);
|
|
336
|
+
expect(statuses["tool-1"]?.type).toBe("executing");
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
240
340
|
it("does not auto-submit a parse-error result for a non-executable tool whose divergent argsText closes", async () => {
|
|
241
341
|
// Same close-gating mismatch as the executable case, but for a tool with
|
|
242
342
|
// no frontend execute. Closing on the divergent complete snapshot would
|
|
@@ -306,19 +406,21 @@ describe("ToolInvocationTracker", () => {
|
|
|
306
406
|
onResult,
|
|
307
407
|
onStatusesChange,
|
|
308
408
|
});
|
|
309
|
-
tracker.setState(createState([]));
|
|
409
|
+
tracker.setState(createState([], false));
|
|
310
410
|
|
|
311
411
|
// Single monotonic snapshot growing to a complete value triggers execute.
|
|
312
412
|
tracker.setState(
|
|
313
|
-
createState(
|
|
314
|
-
createAssistantMessage('{"query":"London"', { query: "London" }),
|
|
315
|
-
|
|
413
|
+
createState(
|
|
414
|
+
[createAssistantMessage('{"query":"London"', { query: "London" })],
|
|
415
|
+
false,
|
|
416
|
+
),
|
|
316
417
|
);
|
|
317
418
|
|
|
318
419
|
tracker.setState(
|
|
319
|
-
createState(
|
|
320
|
-
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
321
|
-
|
|
420
|
+
createState(
|
|
421
|
+
[createAssistantMessage('{"query":"London"}', { query: "London" })],
|
|
422
|
+
false,
|
|
423
|
+
),
|
|
322
424
|
);
|
|
323
425
|
|
|
324
426
|
await waitFor(() => {
|
|
@@ -394,20 +496,424 @@ describe("ToolInvocationTracker", () => {
|
|
|
394
496
|
{ toolName: "deleteFile", approval },
|
|
395
497
|
);
|
|
396
498
|
|
|
397
|
-
tracker.setState(createState([gated({ id: "approval-1" })], false));
|
|
499
|
+
tracker.setState(createState([gated({ id: "approval-1" })], false));
|
|
500
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
501
|
+
expect(execute).not.toHaveBeenCalled();
|
|
502
|
+
|
|
503
|
+
tracker.setState(
|
|
504
|
+
createState([gated({ id: "approval-1", approved: true })], true),
|
|
505
|
+
);
|
|
506
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
507
|
+
|
|
508
|
+
expect(execute).not.toHaveBeenCalled();
|
|
509
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
it("stops executing a live tool call once a provider approval lands", async () => {
|
|
513
|
+
const execute = vi.fn(async () => ({ deleted: true }));
|
|
514
|
+
const getTools = () => ({
|
|
515
|
+
deleteFile: {
|
|
516
|
+
parameters: { type: "object", properties: {} },
|
|
517
|
+
execute,
|
|
518
|
+
} satisfies Tool,
|
|
519
|
+
});
|
|
520
|
+
const onResult = vi.fn();
|
|
521
|
+
const tracker = new ToolInvocationTracker(getTools, {
|
|
522
|
+
onResult,
|
|
523
|
+
onStatusesChange: () => {},
|
|
524
|
+
});
|
|
525
|
+
tracker.setState(createState([]));
|
|
526
|
+
|
|
527
|
+
tracker.setState(
|
|
528
|
+
createState(
|
|
529
|
+
[
|
|
530
|
+
createAssistantMessage(
|
|
531
|
+
'{"path":"/tmp',
|
|
532
|
+
{},
|
|
533
|
+
{ toolName: "deleteFile" },
|
|
534
|
+
),
|
|
535
|
+
],
|
|
536
|
+
true,
|
|
537
|
+
),
|
|
538
|
+
);
|
|
539
|
+
tracker.setState(
|
|
540
|
+
createState(
|
|
541
|
+
[
|
|
542
|
+
createAssistantMessage(
|
|
543
|
+
'{"path":"/tmp/a"}',
|
|
544
|
+
{ path: "/tmp/a" },
|
|
545
|
+
{ toolName: "deleteFile", approval: { id: "approval-1" } },
|
|
546
|
+
),
|
|
547
|
+
],
|
|
548
|
+
true,
|
|
549
|
+
),
|
|
550
|
+
);
|
|
551
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
552
|
+
|
|
553
|
+
expect(execute).not.toHaveBeenCalled();
|
|
554
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
it("drops the result of an in-flight execute once a provider approval lands", async () => {
|
|
558
|
+
let resolveExecute!: (value: { deleted: boolean }) => void;
|
|
559
|
+
const execute = vi.fn(
|
|
560
|
+
() =>
|
|
561
|
+
new Promise<{ deleted: boolean }>((r) => {
|
|
562
|
+
resolveExecute = r;
|
|
563
|
+
}),
|
|
564
|
+
);
|
|
565
|
+
const getTools = () => ({
|
|
566
|
+
deleteFile: {
|
|
567
|
+
parameters: { type: "object", properties: {} },
|
|
568
|
+
execute,
|
|
569
|
+
} satisfies Tool,
|
|
570
|
+
});
|
|
571
|
+
const onResult = vi.fn();
|
|
572
|
+
const tracker = new ToolInvocationTracker(
|
|
573
|
+
getTools,
|
|
574
|
+
{ onResult, onStatusesChange: () => {} },
|
|
575
|
+
() => true,
|
|
576
|
+
);
|
|
577
|
+
tracker.setState(createState([]));
|
|
578
|
+
|
|
579
|
+
tracker.setState(
|
|
580
|
+
createState(
|
|
581
|
+
[
|
|
582
|
+
createAssistantMessage(
|
|
583
|
+
'{"path":"/tmp/a"}',
|
|
584
|
+
{ path: "/tmp/a" },
|
|
585
|
+
{
|
|
586
|
+
toolName: "deleteFile",
|
|
587
|
+
},
|
|
588
|
+
),
|
|
589
|
+
],
|
|
590
|
+
true,
|
|
591
|
+
),
|
|
592
|
+
);
|
|
593
|
+
await waitFor(() => expect(execute).toHaveBeenCalledTimes(1));
|
|
594
|
+
|
|
595
|
+
tracker.setState(
|
|
596
|
+
createState(
|
|
597
|
+
[
|
|
598
|
+
createAssistantMessage(
|
|
599
|
+
'{"path":"/tmp/a"}',
|
|
600
|
+
{ path: "/tmp/a" },
|
|
601
|
+
{
|
|
602
|
+
toolName: "deleteFile",
|
|
603
|
+
approval: { id: "approval-1" },
|
|
604
|
+
},
|
|
605
|
+
),
|
|
606
|
+
],
|
|
607
|
+
true,
|
|
608
|
+
),
|
|
609
|
+
);
|
|
610
|
+
resolveExecute({ deleted: true });
|
|
611
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
612
|
+
|
|
613
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
it("does not execute a registered tool while the provider's run is open", async () => {
|
|
617
|
+
const execute = vi.fn(async () => ({ deleted: true }));
|
|
618
|
+
const getTools = () => ({
|
|
619
|
+
deleteFile: {
|
|
620
|
+
parameters: { type: "object", properties: {} },
|
|
621
|
+
execute,
|
|
622
|
+
} satisfies Tool,
|
|
623
|
+
});
|
|
624
|
+
const onResult = vi.fn();
|
|
625
|
+
const tracker = new ToolInvocationTracker(getTools, {
|
|
626
|
+
onResult,
|
|
627
|
+
onStatusesChange: () => {},
|
|
628
|
+
});
|
|
629
|
+
tracker.setState(createState([]));
|
|
630
|
+
|
|
631
|
+
const complete = (isRunning: boolean) =>
|
|
632
|
+
createState(
|
|
633
|
+
[
|
|
634
|
+
createAssistantMessage(
|
|
635
|
+
'{"path":"/tmp/a"}',
|
|
636
|
+
{ path: "/tmp/a" },
|
|
637
|
+
{ toolName: "deleteFile" },
|
|
638
|
+
),
|
|
639
|
+
],
|
|
640
|
+
isRunning,
|
|
641
|
+
);
|
|
642
|
+
|
|
643
|
+
tracker.setState(complete(true));
|
|
644
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
645
|
+
expect(execute).not.toHaveBeenCalled();
|
|
646
|
+
|
|
647
|
+
tracker.setState(complete(false));
|
|
648
|
+
await waitFor(() => expect(execute).toHaveBeenCalledTimes(1));
|
|
649
|
+
await waitFor(() => expect(onResult).toHaveBeenCalledTimes(1));
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
it("streams a streamCall tool's args while the run is open and executes it after", async () => {
|
|
653
|
+
const streamed: unknown[] = [];
|
|
654
|
+
const streamCall = vi.fn(
|
|
655
|
+
async (reader: {
|
|
656
|
+
args: { streamValues: () => AsyncIterable<unknown> };
|
|
657
|
+
}) => {
|
|
658
|
+
for await (const partial of reader.args.streamValues())
|
|
659
|
+
streamed.push(partial);
|
|
660
|
+
},
|
|
661
|
+
);
|
|
662
|
+
const execute = vi.fn(async () => ({ deleted: true }));
|
|
663
|
+
const getTools = () => ({
|
|
664
|
+
deleteFile: {
|
|
665
|
+
parameters: { type: "object", properties: {} },
|
|
666
|
+
streamCall,
|
|
667
|
+
execute,
|
|
668
|
+
} satisfies Tool,
|
|
669
|
+
});
|
|
670
|
+
const onResult = vi.fn();
|
|
671
|
+
const tracker = new ToolInvocationTracker(getTools, {
|
|
672
|
+
onResult,
|
|
673
|
+
onStatusesChange: () => {},
|
|
674
|
+
});
|
|
675
|
+
tracker.setState(createState([], false));
|
|
676
|
+
|
|
677
|
+
tracker.setState(
|
|
678
|
+
createState([
|
|
679
|
+
createAssistantMessage(
|
|
680
|
+
'{"path":"/tmp/a"',
|
|
681
|
+
{ path: "/tmp/a" },
|
|
682
|
+
{
|
|
683
|
+
toolName: "deleteFile",
|
|
684
|
+
},
|
|
685
|
+
),
|
|
686
|
+
]),
|
|
687
|
+
);
|
|
688
|
+
tracker.setState(
|
|
689
|
+
createState([
|
|
690
|
+
createAssistantMessage(
|
|
691
|
+
'{"path":"/tmp/a"}',
|
|
692
|
+
{ path: "/tmp/a" },
|
|
693
|
+
{
|
|
694
|
+
toolName: "deleteFile",
|
|
695
|
+
},
|
|
696
|
+
),
|
|
697
|
+
]),
|
|
698
|
+
);
|
|
699
|
+
|
|
700
|
+
await waitFor(() => expect(streamCall).toHaveBeenCalledTimes(1));
|
|
701
|
+
await waitFor(() => expect(streamed.length).toBeGreaterThan(0));
|
|
702
|
+
expect(execute).not.toHaveBeenCalled();
|
|
703
|
+
|
|
704
|
+
tracker.setState(
|
|
705
|
+
createState(
|
|
706
|
+
[
|
|
707
|
+
createAssistantMessage(
|
|
708
|
+
'{"path":"/tmp/a"}',
|
|
709
|
+
{ path: "/tmp/a" },
|
|
710
|
+
{
|
|
711
|
+
toolName: "deleteFile",
|
|
712
|
+
},
|
|
713
|
+
),
|
|
714
|
+
],
|
|
715
|
+
false,
|
|
716
|
+
),
|
|
717
|
+
);
|
|
718
|
+
|
|
719
|
+
await waitFor(() => expect(execute).toHaveBeenCalledTimes(1));
|
|
720
|
+
await waitFor(() => expect(onResult).toHaveBeenCalledTimes(1));
|
|
721
|
+
expect(streamCall).toHaveBeenCalledTimes(1);
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
it("never executes a registered tool that was waiting when the turn was aborted", async () => {
|
|
725
|
+
const execute = vi.fn(async () => ({ deleted: true }));
|
|
726
|
+
const getTools = () => ({
|
|
727
|
+
deleteFile: {
|
|
728
|
+
parameters: { type: "object", properties: {} },
|
|
729
|
+
execute,
|
|
730
|
+
} satisfies Tool,
|
|
731
|
+
});
|
|
732
|
+
const onResult = vi.fn();
|
|
733
|
+
const tracker = new ToolInvocationTracker(getTools, {
|
|
734
|
+
onResult,
|
|
735
|
+
onStatusesChange: () => {},
|
|
736
|
+
});
|
|
737
|
+
tracker.setState(createState([], false));
|
|
738
|
+
|
|
739
|
+
const complete = (isRunning: boolean) =>
|
|
740
|
+
createState(
|
|
741
|
+
[
|
|
742
|
+
createAssistantMessage(
|
|
743
|
+
'{"path":"/tmp/a"}',
|
|
744
|
+
{ path: "/tmp/a" },
|
|
745
|
+
{ toolName: "deleteFile" },
|
|
746
|
+
),
|
|
747
|
+
],
|
|
748
|
+
isRunning,
|
|
749
|
+
);
|
|
750
|
+
|
|
751
|
+
tracker.setState(complete(true));
|
|
752
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
753
|
+
expect(execute).not.toHaveBeenCalled();
|
|
754
|
+
|
|
755
|
+
await tracker.abort({ discardPending: true });
|
|
756
|
+
|
|
757
|
+
tracker.setState(complete(false));
|
|
758
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
759
|
+
|
|
760
|
+
expect(execute).not.toHaveBeenCalled();
|
|
761
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
it("still executes a waiting tool when an abort only interrupts the turn", async () => {
|
|
765
|
+
const execute = vi.fn(async () => ({ deleted: true }));
|
|
766
|
+
const getTools = () => ({
|
|
767
|
+
deleteFile: {
|
|
768
|
+
parameters: { type: "object", properties: {} },
|
|
769
|
+
execute,
|
|
770
|
+
} satisfies Tool,
|
|
771
|
+
});
|
|
772
|
+
const onResult = vi.fn();
|
|
773
|
+
const tracker = new ToolInvocationTracker(getTools, {
|
|
774
|
+
onResult,
|
|
775
|
+
onStatusesChange: () => {},
|
|
776
|
+
});
|
|
777
|
+
tracker.setState(createState([], false));
|
|
778
|
+
|
|
779
|
+
const complete = (isRunning: boolean) =>
|
|
780
|
+
createState(
|
|
781
|
+
[
|
|
782
|
+
createAssistantMessage(
|
|
783
|
+
'{"path":"/tmp/a"}',
|
|
784
|
+
{ path: "/tmp/a" },
|
|
785
|
+
{ toolName: "deleteFile" },
|
|
786
|
+
),
|
|
787
|
+
],
|
|
788
|
+
isRunning,
|
|
789
|
+
);
|
|
790
|
+
|
|
791
|
+
tracker.setState(complete(true));
|
|
792
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
793
|
+
|
|
794
|
+
await tracker.abort();
|
|
795
|
+
|
|
796
|
+
tracker.setState(complete(false));
|
|
797
|
+
await waitFor(() => expect(execute).toHaveBeenCalledTimes(1));
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
it("keeps a discarded tool call skipped once its args complete", async () => {
|
|
801
|
+
const execute = vi.fn(async () => ({ deleted: true }));
|
|
802
|
+
const getTools = () => ({
|
|
803
|
+
deleteFile: {
|
|
804
|
+
parameters: { type: "object", properties: {} },
|
|
805
|
+
execute,
|
|
806
|
+
} satisfies Tool,
|
|
807
|
+
});
|
|
808
|
+
const onResult = vi.fn();
|
|
809
|
+
const tracker = new ToolInvocationTracker(getTools, {
|
|
810
|
+
onResult,
|
|
811
|
+
onStatusesChange: () => {},
|
|
812
|
+
});
|
|
813
|
+
tracker.setState(createState([], false));
|
|
814
|
+
|
|
815
|
+
const live = (argsText: string, isRunning: boolean) =>
|
|
816
|
+
createState(
|
|
817
|
+
[
|
|
818
|
+
createAssistantMessage(
|
|
819
|
+
argsText,
|
|
820
|
+
{ path: "/tmp/a" },
|
|
821
|
+
{ toolName: "deleteFile" },
|
|
822
|
+
),
|
|
823
|
+
],
|
|
824
|
+
isRunning,
|
|
825
|
+
);
|
|
826
|
+
|
|
827
|
+
tracker.setState(live('{"path":"/tm', true));
|
|
828
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
829
|
+
|
|
830
|
+
await tracker.abort({ discardPending: true });
|
|
831
|
+
|
|
832
|
+
tracker.setState(live('{"path":"/tmp/a"}', false));
|
|
833
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
834
|
+
|
|
835
|
+
expect(execute).not.toHaveBeenCalled();
|
|
836
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
it("keeps a discarded call skipped when the pipeline restarts before it settles", async () => {
|
|
840
|
+
const execute = vi.fn(async () => ({ deleted: true }));
|
|
841
|
+
const getTools = () => ({
|
|
842
|
+
deleteFile: {
|
|
843
|
+
parameters: { type: "object", properties: {} },
|
|
844
|
+
execute,
|
|
845
|
+
} satisfies Tool,
|
|
846
|
+
});
|
|
847
|
+
const onResult = vi.fn();
|
|
848
|
+
const tracker = new ToolInvocationTracker(getTools, {
|
|
849
|
+
onResult,
|
|
850
|
+
onStatusesChange: () => {},
|
|
851
|
+
});
|
|
852
|
+
tracker.setState(createState([], false));
|
|
853
|
+
|
|
854
|
+
const complete = (isRunning: boolean) =>
|
|
855
|
+
createState(
|
|
856
|
+
[
|
|
857
|
+
createAssistantMessage(
|
|
858
|
+
'{"path":"/tmp/a"}',
|
|
859
|
+
{ path: "/tmp/a" },
|
|
860
|
+
{ toolName: "deleteFile" },
|
|
861
|
+
),
|
|
862
|
+
],
|
|
863
|
+
isRunning,
|
|
864
|
+
);
|
|
865
|
+
|
|
866
|
+
tracker.setState(complete(true));
|
|
867
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
868
|
+
await tracker.abort({ discardPending: true });
|
|
869
|
+
|
|
870
|
+
killPipeline(tracker);
|
|
871
|
+
tracker.setState(complete(false));
|
|
872
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
873
|
+
|
|
874
|
+
expect(execute).not.toHaveBeenCalled();
|
|
875
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
it("still executes a waiting call when the pipeline restarts before it settles", async () => {
|
|
879
|
+
const execute = vi.fn(async () => ({ deleted: true }));
|
|
880
|
+
const getTools = () => ({
|
|
881
|
+
deleteFile: {
|
|
882
|
+
parameters: { type: "object", properties: {} },
|
|
883
|
+
execute,
|
|
884
|
+
} satisfies Tool,
|
|
885
|
+
});
|
|
886
|
+
const onResult = vi.fn();
|
|
887
|
+
const tracker = new ToolInvocationTracker(getTools, {
|
|
888
|
+
onResult,
|
|
889
|
+
onStatusesChange: () => {},
|
|
890
|
+
});
|
|
891
|
+
tracker.setState(createState([], false));
|
|
892
|
+
|
|
893
|
+
const complete = (isRunning: boolean) =>
|
|
894
|
+
createState(
|
|
895
|
+
[
|
|
896
|
+
createAssistantMessage(
|
|
897
|
+
'{"path":"/tmp/a"}',
|
|
898
|
+
{ path: "/tmp/a" },
|
|
899
|
+
{ toolName: "deleteFile" },
|
|
900
|
+
),
|
|
901
|
+
],
|
|
902
|
+
isRunning,
|
|
903
|
+
);
|
|
904
|
+
|
|
905
|
+
tracker.setState(complete(true));
|
|
398
906
|
await new Promise((r) => setTimeout(r, 0));
|
|
399
907
|
expect(execute).not.toHaveBeenCalled();
|
|
400
908
|
|
|
401
|
-
tracker
|
|
402
|
-
|
|
403
|
-
);
|
|
404
|
-
await new Promise((r) => setTimeout(r, 0));
|
|
909
|
+
killPipeline(tracker);
|
|
910
|
+
tracker.setState(complete(false));
|
|
405
911
|
|
|
406
|
-
expect(execute).
|
|
407
|
-
expect(onResult).
|
|
912
|
+
await waitFor(() => expect(execute).toHaveBeenCalledTimes(1));
|
|
913
|
+
await waitFor(() => expect(onResult).toHaveBeenCalledTimes(1));
|
|
408
914
|
});
|
|
409
915
|
|
|
410
|
-
it("
|
|
916
|
+
it("never executes a registered tool the provider gates before its run ends", async () => {
|
|
411
917
|
const execute = vi.fn(async () => ({ deleted: true }));
|
|
412
918
|
const getTools = () => ({
|
|
413
919
|
deleteFile: {
|
|
@@ -426,14 +932,16 @@ describe("ToolInvocationTracker", () => {
|
|
|
426
932
|
createState(
|
|
427
933
|
[
|
|
428
934
|
createAssistantMessage(
|
|
429
|
-
'{"path":"/tmp',
|
|
430
|
-
{},
|
|
935
|
+
'{"path":"/tmp/a"}',
|
|
936
|
+
{ path: "/tmp/a" },
|
|
431
937
|
{ toolName: "deleteFile" },
|
|
432
938
|
),
|
|
433
939
|
],
|
|
434
940
|
true,
|
|
435
941
|
),
|
|
436
942
|
);
|
|
943
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
944
|
+
|
|
437
945
|
tracker.setState(
|
|
438
946
|
createState(
|
|
439
947
|
[
|
|
@@ -443,7 +951,7 @@ describe("ToolInvocationTracker", () => {
|
|
|
443
951
|
{ toolName: "deleteFile", approval: { id: "approval-1" } },
|
|
444
952
|
),
|
|
445
953
|
],
|
|
446
|
-
|
|
954
|
+
false,
|
|
447
955
|
),
|
|
448
956
|
);
|
|
449
957
|
await new Promise((r) => setTimeout(r, 0));
|
|
@@ -452,14 +960,8 @@ describe("ToolInvocationTracker", () => {
|
|
|
452
960
|
expect(onResult).not.toHaveBeenCalled();
|
|
453
961
|
});
|
|
454
962
|
|
|
455
|
-
it("
|
|
456
|
-
|
|
457
|
-
const execute = vi.fn(
|
|
458
|
-
() =>
|
|
459
|
-
new Promise<{ deleted: boolean }>((r) => {
|
|
460
|
-
resolveExecute = r;
|
|
461
|
-
}),
|
|
462
|
-
);
|
|
963
|
+
it("never executes a tool call the adapter reports as provider-owned", async () => {
|
|
964
|
+
const execute = vi.fn(async () => ({ deleted: true }));
|
|
463
965
|
const getTools = () => ({
|
|
464
966
|
deleteFile: {
|
|
465
967
|
parameters: { type: "object", properties: {} },
|
|
@@ -467,10 +969,69 @@ describe("ToolInvocationTracker", () => {
|
|
|
467
969
|
} satisfies Tool,
|
|
468
970
|
});
|
|
469
971
|
const onResult = vi.fn();
|
|
470
|
-
const
|
|
471
|
-
|
|
472
|
-
|
|
972
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
973
|
+
|
|
974
|
+
try {
|
|
975
|
+
const tracker = new ToolInvocationTracker(
|
|
976
|
+
getTools,
|
|
977
|
+
{ onResult, onStatusesChange: () => {} },
|
|
978
|
+
() => false,
|
|
979
|
+
);
|
|
980
|
+
tracker.setState(createState([]));
|
|
981
|
+
|
|
982
|
+
tracker.setState(
|
|
983
|
+
createState(
|
|
984
|
+
[
|
|
985
|
+
createAssistantMessage(
|
|
986
|
+
'{"path":"/tmp/a"}',
|
|
987
|
+
{ path: "/tmp/a" },
|
|
988
|
+
{ toolName: "deleteFile" },
|
|
989
|
+
),
|
|
990
|
+
],
|
|
991
|
+
true,
|
|
992
|
+
),
|
|
993
|
+
);
|
|
994
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
995
|
+
|
|
996
|
+
expect(execute).not.toHaveBeenCalled();
|
|
997
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
998
|
+
expect(warnSpy).toHaveBeenCalledTimes(1);
|
|
999
|
+
|
|
1000
|
+
tracker.setState(
|
|
1001
|
+
createState(
|
|
1002
|
+
[
|
|
1003
|
+
createAssistantMessage(
|
|
1004
|
+
'{"path":"/tmp/a"}',
|
|
1005
|
+
{ path: "/tmp/a" },
|
|
1006
|
+
{ toolName: "deleteFile", result: { server: "deleted" } },
|
|
1007
|
+
),
|
|
1008
|
+
],
|
|
1009
|
+
false,
|
|
1010
|
+
),
|
|
1011
|
+
);
|
|
1012
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
1013
|
+
|
|
1014
|
+
expect(execute).not.toHaveBeenCalled();
|
|
1015
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
1016
|
+
} finally {
|
|
1017
|
+
warnSpy.mockRestore();
|
|
1018
|
+
}
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
it("executes a tool call the adapter reports as client-owned", async () => {
|
|
1022
|
+
const execute = vi.fn(async () => ({ deleted: true }));
|
|
1023
|
+
const getTools = () => ({
|
|
1024
|
+
deleteFile: {
|
|
1025
|
+
parameters: { type: "object", properties: {} },
|
|
1026
|
+
execute,
|
|
1027
|
+
} satisfies Tool,
|
|
473
1028
|
});
|
|
1029
|
+
const onResult = vi.fn();
|
|
1030
|
+
const tracker = new ToolInvocationTracker(
|
|
1031
|
+
getTools,
|
|
1032
|
+
{ onResult, onStatusesChange: () => {} },
|
|
1033
|
+
(toolCall) => toolCall.toolCallId === "tool-1",
|
|
1034
|
+
);
|
|
474
1035
|
tracker.setState(createState([]));
|
|
475
1036
|
|
|
476
1037
|
tracker.setState(
|
|
@@ -479,35 +1040,59 @@ describe("ToolInvocationTracker", () => {
|
|
|
479
1040
|
createAssistantMessage(
|
|
480
1041
|
'{"path":"/tmp/a"}',
|
|
481
1042
|
{ path: "/tmp/a" },
|
|
482
|
-
{
|
|
483
|
-
toolName: "deleteFile",
|
|
484
|
-
},
|
|
1043
|
+
{ toolName: "deleteFile" },
|
|
485
1044
|
),
|
|
486
1045
|
],
|
|
487
1046
|
true,
|
|
488
1047
|
),
|
|
489
1048
|
);
|
|
490
1049
|
await waitFor(() => expect(execute).toHaveBeenCalledTimes(1));
|
|
1050
|
+
await waitFor(() => expect(onResult).toHaveBeenCalledTimes(1));
|
|
1051
|
+
});
|
|
491
1052
|
|
|
492
|
-
|
|
1053
|
+
it("keeps the result of a call the adapter stops reporting as client-owned mid-execution", async () => {
|
|
1054
|
+
let resolveExecute!: (value: { deleted: boolean }) => void;
|
|
1055
|
+
const execute = vi.fn(
|
|
1056
|
+
() =>
|
|
1057
|
+
new Promise<{ deleted: boolean }>((r) => {
|
|
1058
|
+
resolveExecute = r;
|
|
1059
|
+
}),
|
|
1060
|
+
);
|
|
1061
|
+
const getTools = () => ({
|
|
1062
|
+
deleteFile: {
|
|
1063
|
+
parameters: { type: "object", properties: {} },
|
|
1064
|
+
execute,
|
|
1065
|
+
} satisfies Tool,
|
|
1066
|
+
});
|
|
1067
|
+
const onResult = vi.fn();
|
|
1068
|
+
let clientOwned = true;
|
|
1069
|
+
const tracker = new ToolInvocationTracker(
|
|
1070
|
+
getTools,
|
|
1071
|
+
{ onResult, onStatusesChange: () => {} },
|
|
1072
|
+
() => clientOwned,
|
|
1073
|
+
);
|
|
1074
|
+
tracker.setState(createState([]));
|
|
1075
|
+
|
|
1076
|
+
const live = () =>
|
|
493
1077
|
createState(
|
|
494
1078
|
[
|
|
495
1079
|
createAssistantMessage(
|
|
496
1080
|
'{"path":"/tmp/a"}',
|
|
497
1081
|
{ path: "/tmp/a" },
|
|
498
|
-
{
|
|
499
|
-
toolName: "deleteFile",
|
|
500
|
-
approval: { id: "approval-1" },
|
|
501
|
-
},
|
|
1082
|
+
{ toolName: "deleteFile" },
|
|
502
1083
|
),
|
|
503
1084
|
],
|
|
504
1085
|
true,
|
|
505
|
-
)
|
|
506
|
-
|
|
1086
|
+
);
|
|
1087
|
+
|
|
1088
|
+
tracker.setState(live());
|
|
1089
|
+
await waitFor(() => expect(execute).toHaveBeenCalledTimes(1));
|
|
1090
|
+
|
|
1091
|
+
clientOwned = false;
|
|
1092
|
+
tracker.setState(live());
|
|
507
1093
|
resolveExecute({ deleted: true });
|
|
508
|
-
await new Promise((r) => setTimeout(r, 0));
|
|
509
1094
|
|
|
510
|
-
expect(onResult).
|
|
1095
|
+
await waitFor(() => expect(onResult).toHaveBeenCalledTimes(1));
|
|
511
1096
|
});
|
|
512
1097
|
|
|
513
1098
|
it("does not re-execute asynchronously loaded resolved tool calls after reset", async () => {
|
|
@@ -525,12 +1110,13 @@ describe("ToolInvocationTracker", () => {
|
|
|
525
1110
|
onResult,
|
|
526
1111
|
onStatusesChange,
|
|
527
1112
|
});
|
|
528
|
-
tracker.setState(createState([]));
|
|
1113
|
+
tracker.setState(createState([], false));
|
|
529
1114
|
|
|
530
1115
|
tracker.setState(
|
|
531
|
-
createState(
|
|
532
|
-
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
533
|
-
|
|
1116
|
+
createState(
|
|
1117
|
+
[createAssistantMessage('{"query":"London"}', { query: "London" })],
|
|
1118
|
+
false,
|
|
1119
|
+
),
|
|
534
1120
|
);
|
|
535
1121
|
|
|
536
1122
|
await waitFor(() => {
|
|
@@ -541,16 +1127,19 @@ describe("ToolInvocationTracker", () => {
|
|
|
541
1127
|
|
|
542
1128
|
await Promise.resolve();
|
|
543
1129
|
|
|
544
|
-
tracker.setState(createState([]));
|
|
1130
|
+
tracker.setState(createState([], false));
|
|
545
1131
|
|
|
546
1132
|
tracker.setState(
|
|
547
|
-
createState(
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
1133
|
+
createState(
|
|
1134
|
+
[
|
|
1135
|
+
createAssistantMessage(
|
|
1136
|
+
'{"query":"London"}',
|
|
1137
|
+
{ query: "London" },
|
|
1138
|
+
{ result: { source: "history" } },
|
|
1139
|
+
),
|
|
1140
|
+
],
|
|
1141
|
+
false,
|
|
1142
|
+
),
|
|
554
1143
|
);
|
|
555
1144
|
|
|
556
1145
|
await waitFor(() => {
|
|
@@ -588,20 +1177,23 @@ describe("ToolInvocationTracker", () => {
|
|
|
588
1177
|
onResult,
|
|
589
1178
|
onStatusesChange,
|
|
590
1179
|
});
|
|
591
|
-
tracker.setState(createState([]));
|
|
1180
|
+
tracker.setState(createState([], false));
|
|
592
1181
|
|
|
593
1182
|
tracker.setState(
|
|
594
|
-
createState(
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
1183
|
+
createState(
|
|
1184
|
+
[
|
|
1185
|
+
createAssistantMessage(
|
|
1186
|
+
'{"query":"parent"}',
|
|
1187
|
+
{ query: "parent" },
|
|
1188
|
+
{
|
|
1189
|
+
result: { source: "history" },
|
|
1190
|
+
toolName: "resolvedOnly",
|
|
1191
|
+
nestedMessages: [nestedMessage],
|
|
1192
|
+
},
|
|
1193
|
+
),
|
|
1194
|
+
],
|
|
1195
|
+
false,
|
|
1196
|
+
),
|
|
605
1197
|
);
|
|
606
1198
|
|
|
607
1199
|
await waitFor(() => {
|
|
@@ -747,15 +1339,18 @@ describe("ToolInvocationTracker", () => {
|
|
|
747
1339
|
onResult,
|
|
748
1340
|
onStatusesChange,
|
|
749
1341
|
});
|
|
750
|
-
tracker.setState(createState([]));
|
|
1342
|
+
tracker.setState(createState([], false));
|
|
751
1343
|
|
|
752
1344
|
tracker.setState(
|
|
753
|
-
createState(
|
|
754
|
-
|
|
755
|
-
a:
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
1345
|
+
createState(
|
|
1346
|
+
[
|
|
1347
|
+
createAssistantMessage('{"a":1,"b":2}', {
|
|
1348
|
+
a: 1,
|
|
1349
|
+
b: 2,
|
|
1350
|
+
}),
|
|
1351
|
+
],
|
|
1352
|
+
false,
|
|
1353
|
+
),
|
|
759
1354
|
);
|
|
760
1355
|
|
|
761
1356
|
await waitFor(() => {
|
|
@@ -763,18 +1358,21 @@ describe("ToolInvocationTracker", () => {
|
|
|
763
1358
|
});
|
|
764
1359
|
|
|
765
1360
|
tracker.setState(
|
|
766
|
-
createState(
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
1361
|
+
createState(
|
|
1362
|
+
[
|
|
1363
|
+
createAssistantMessage(
|
|
1364
|
+
'{"b":2,"a":1}',
|
|
1365
|
+
{
|
|
1366
|
+
a: 1,
|
|
1367
|
+
b: 2,
|
|
1368
|
+
},
|
|
1369
|
+
{
|
|
1370
|
+
result: { source: "backend" },
|
|
1371
|
+
},
|
|
1372
|
+
),
|
|
1373
|
+
],
|
|
1374
|
+
false,
|
|
1375
|
+
),
|
|
778
1376
|
);
|
|
779
1377
|
|
|
780
1378
|
resolveExecute?.({ source: "client" });
|
|
@@ -1332,11 +1930,12 @@ describe("ToolInvocationTracker reset", () => {
|
|
|
1332
1930
|
execute: vi.fn(() => new Promise(() => {})),
|
|
1333
1931
|
} satisfies Tool,
|
|
1334
1932
|
});
|
|
1335
|
-
tracker.setState(createState([]));
|
|
1933
|
+
tracker.setState(createState([], false));
|
|
1336
1934
|
tracker.setState(
|
|
1337
|
-
createState(
|
|
1338
|
-
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
1339
|
-
|
|
1935
|
+
createState(
|
|
1936
|
+
[createAssistantMessage('{"query":"London"}', { query: "London" })],
|
|
1937
|
+
false,
|
|
1938
|
+
),
|
|
1340
1939
|
);
|
|
1341
1940
|
await waitFor(() => {
|
|
1342
1941
|
expect(statuses()["tool-1"]?.type).toBe("executing");
|
|
@@ -1350,15 +1949,18 @@ describe("ToolInvocationTracker reset", () => {
|
|
|
1350
1949
|
// discarded id back in through the whole-map republication. The first
|
|
1351
1950
|
// post-reset snapshot is the fresh session's empty state, consuming the
|
|
1352
1951
|
// pending-restore mark.
|
|
1353
|
-
tracker.setState(createState([]));
|
|
1952
|
+
tracker.setState(createState([], false));
|
|
1354
1953
|
tracker.setState(
|
|
1355
|
-
createState(
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1954
|
+
createState(
|
|
1955
|
+
[
|
|
1956
|
+
createAssistantMessage(
|
|
1957
|
+
'{"query":"Paris"}',
|
|
1958
|
+
{ query: "Paris" },
|
|
1959
|
+
{ toolCallId: "tool-2" },
|
|
1960
|
+
),
|
|
1961
|
+
],
|
|
1962
|
+
false,
|
|
1963
|
+
),
|
|
1362
1964
|
);
|
|
1363
1965
|
await waitFor(() => {
|
|
1364
1966
|
expect(statuses()["tool-2"]?.type).toBe("executing");
|
|
@@ -1386,19 +1988,22 @@ describe("ToolInvocationTracker reset", () => {
|
|
|
1386
1988
|
execute: vi.fn(() => new Promise(() => {})),
|
|
1387
1989
|
} satisfies Tool,
|
|
1388
1990
|
});
|
|
1389
|
-
tracker.setState(createState([]));
|
|
1991
|
+
tracker.setState(createState([], false));
|
|
1390
1992
|
tracker.setState(
|
|
1391
|
-
createState(
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1993
|
+
createState(
|
|
1994
|
+
[
|
|
1995
|
+
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
1996
|
+
createAssistantMessage(
|
|
1997
|
+
'{"query":"London"}',
|
|
1998
|
+
{ query: "London" },
|
|
1999
|
+
{
|
|
2000
|
+
toolCallId: "tool-2",
|
|
2001
|
+
toolName: "pressureSearch",
|
|
2002
|
+
},
|
|
2003
|
+
),
|
|
2004
|
+
],
|
|
2005
|
+
false,
|
|
2006
|
+
),
|
|
1402
2007
|
);
|
|
1403
2008
|
await waitFor(() => {
|
|
1404
2009
|
expect(statuses()["tool-1"]?.type).toBe("executing");
|
|
@@ -1426,11 +2031,12 @@ describe("ToolInvocationTracker reset", () => {
|
|
|
1426
2031
|
}),
|
|
1427
2032
|
} satisfies Tool,
|
|
1428
2033
|
});
|
|
1429
|
-
tracker.setState(createState([]));
|
|
2034
|
+
tracker.setState(createState([], false));
|
|
1430
2035
|
tracker.setState(
|
|
1431
|
-
createState(
|
|
1432
|
-
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
1433
|
-
|
|
2036
|
+
createState(
|
|
2037
|
+
[createAssistantMessage('{"query":"London"}', { query: "London" })],
|
|
2038
|
+
false,
|
|
2039
|
+
),
|
|
1434
2040
|
);
|
|
1435
2041
|
await waitFor(() => {
|
|
1436
2042
|
expect(statuses()["tool-1"]?.type).toBe("executing");
|
|
@@ -1457,11 +2063,12 @@ describe("ToolInvocationTracker reset", () => {
|
|
|
1457
2063
|
} satisfies Tool,
|
|
1458
2064
|
});
|
|
1459
2065
|
|
|
1460
|
-
tracker.setState(createState([]));
|
|
2066
|
+
tracker.setState(createState([], false));
|
|
1461
2067
|
tracker.setState(
|
|
1462
|
-
createState(
|
|
1463
|
-
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
1464
|
-
|
|
2068
|
+
createState(
|
|
2069
|
+
[createAssistantMessage('{"query":"London"}', { query: "London" })],
|
|
2070
|
+
false,
|
|
2071
|
+
),
|
|
1465
2072
|
);
|
|
1466
2073
|
await waitFor(() => {
|
|
1467
2074
|
expect(humanFns).toHaveLength(1);
|
|
@@ -1469,15 +2076,18 @@ describe("ToolInvocationTracker reset", () => {
|
|
|
1469
2076
|
});
|
|
1470
2077
|
|
|
1471
2078
|
tracker.reset();
|
|
1472
|
-
tracker.setState(createState([]));
|
|
2079
|
+
tracker.setState(createState([], false));
|
|
1473
2080
|
tracker.setState(
|
|
1474
|
-
createState(
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
2081
|
+
createState(
|
|
2082
|
+
[
|
|
2083
|
+
createAssistantMessage(
|
|
2084
|
+
'{"query":"Paris"}',
|
|
2085
|
+
{ query: "Paris" },
|
|
2086
|
+
{ toolCallId: "tool-1" },
|
|
2087
|
+
),
|
|
2088
|
+
],
|
|
2089
|
+
false,
|
|
2090
|
+
),
|
|
1481
2091
|
);
|
|
1482
2092
|
await waitFor(() => expect(humanFns).toHaveLength(2));
|
|
1483
2093
|
|
|
@@ -1518,24 +2128,28 @@ describe("ToolInvocationTracker reset", () => {
|
|
|
1518
2128
|
{ onResult, onStatusesChange: vi.fn() },
|
|
1519
2129
|
);
|
|
1520
2130
|
|
|
1521
|
-
tracker.setState(createState([]));
|
|
2131
|
+
tracker.setState(createState([], false));
|
|
1522
2132
|
tracker.setState(
|
|
1523
|
-
createState(
|
|
1524
|
-
createAssistantMessage('{"query":"London"}', { query: "London" }),
|
|
1525
|
-
|
|
2133
|
+
createState(
|
|
2134
|
+
[createAssistantMessage('{"query":"London"}', { query: "London" })],
|
|
2135
|
+
false,
|
|
2136
|
+
),
|
|
1526
2137
|
);
|
|
1527
2138
|
await waitFor(() => expect(executions).toHaveLength(1));
|
|
1528
2139
|
|
|
1529
2140
|
tracker.reset();
|
|
1530
|
-
tracker.setState(createState([]));
|
|
2141
|
+
tracker.setState(createState([], false));
|
|
1531
2142
|
tracker.setState(
|
|
1532
|
-
createState(
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
2143
|
+
createState(
|
|
2144
|
+
[
|
|
2145
|
+
createAssistantMessage(
|
|
2146
|
+
'{"query":"Paris"}',
|
|
2147
|
+
{ query: "Paris" },
|
|
2148
|
+
{ toolCallId: "tool-1" },
|
|
2149
|
+
),
|
|
2150
|
+
],
|
|
2151
|
+
false,
|
|
2152
|
+
),
|
|
1539
2153
|
);
|
|
1540
2154
|
await waitFor(() => expect(executions).toHaveLength(2));
|
|
1541
2155
|
await new Promise((resolve) => setTimeout(resolve, 0));
|