@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
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { act, cleanup, render, waitFor } from "@testing-library/react";
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
|
|
6
|
+
import { makeAdapter } from "../../tests/remote-thread-list-test-helpers";
|
|
7
|
+
import { AssistantRuntimeProvider } from "../AssistantRuntimeProvider";
|
|
8
|
+
import { useExternalStoreRuntime } from "./useExternalStoreRuntime";
|
|
9
|
+
import { useRemoteThreadListRuntime } from "./useRemoteThreadListRuntime";
|
|
10
|
+
|
|
11
|
+
const EMPTY_MESSAGES: readonly never[] = [];
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
cleanup();
|
|
15
|
+
vi.restoreAllMocks();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("useRemoteThreadListRuntime load recovery", () => {
|
|
19
|
+
it("reloads once when the browser comes online after a failed load", async () => {
|
|
20
|
+
const error = new Error("offline");
|
|
21
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
22
|
+
const list = vi
|
|
23
|
+
.fn()
|
|
24
|
+
.mockRejectedValueOnce(error)
|
|
25
|
+
.mockResolvedValueOnce({ threads: [] });
|
|
26
|
+
const adapter = makeAdapter({ list });
|
|
27
|
+
const runtimeRef: { current: AssistantRuntime | null } = { current: null };
|
|
28
|
+
const useThreadRuntime = () =>
|
|
29
|
+
useExternalStoreRuntime({
|
|
30
|
+
messages: EMPTY_MESSAGES,
|
|
31
|
+
onNew: async () => {},
|
|
32
|
+
} as never);
|
|
33
|
+
|
|
34
|
+
const App = () => {
|
|
35
|
+
const runtime = useRemoteThreadListRuntime({
|
|
36
|
+
adapter,
|
|
37
|
+
runtimeHook: useThreadRuntime,
|
|
38
|
+
});
|
|
39
|
+
runtimeRef.current = runtime;
|
|
40
|
+
return (
|
|
41
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
42
|
+
{null}
|
|
43
|
+
</AssistantRuntimeProvider>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
render(<App />);
|
|
48
|
+
await waitFor(() => expect(list).toHaveBeenCalledTimes(1));
|
|
49
|
+
await waitFor(() =>
|
|
50
|
+
expect(runtimeRef.current!.threads.getState().loadError).toBe(error),
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
act(() => window.dispatchEvent(new Event("online")));
|
|
54
|
+
|
|
55
|
+
await waitFor(() => expect(list).toHaveBeenCalledTimes(2));
|
|
56
|
+
await act(async () => {});
|
|
57
|
+
expect(list).toHaveBeenCalledTimes(2);
|
|
58
|
+
expect(runtimeRef.current!.threads.getState().loadError).toBeUndefined();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("reloads once when the page becomes visible after a failed load", async () => {
|
|
62
|
+
const error = new Error("offline");
|
|
63
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
64
|
+
vi.spyOn(document, "visibilityState", "get").mockReturnValue("visible");
|
|
65
|
+
const list = vi
|
|
66
|
+
.fn()
|
|
67
|
+
.mockRejectedValueOnce(error)
|
|
68
|
+
.mockResolvedValueOnce({ threads: [] });
|
|
69
|
+
const adapter = makeAdapter({ list });
|
|
70
|
+
const runtimeRef: { current: AssistantRuntime | null } = { current: null };
|
|
71
|
+
const useThreadRuntime = () =>
|
|
72
|
+
useExternalStoreRuntime({
|
|
73
|
+
messages: EMPTY_MESSAGES,
|
|
74
|
+
onNew: async () => {},
|
|
75
|
+
} as never);
|
|
76
|
+
|
|
77
|
+
const App = () => {
|
|
78
|
+
const runtime = useRemoteThreadListRuntime({
|
|
79
|
+
adapter,
|
|
80
|
+
runtimeHook: useThreadRuntime,
|
|
81
|
+
});
|
|
82
|
+
runtimeRef.current = runtime;
|
|
83
|
+
return (
|
|
84
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
85
|
+
{null}
|
|
86
|
+
</AssistantRuntimeProvider>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
render(<App />);
|
|
91
|
+
await waitFor(() => expect(list).toHaveBeenCalledTimes(1));
|
|
92
|
+
await waitFor(() =>
|
|
93
|
+
expect(runtimeRef.current!.threads.getState().loadError).toBe(error),
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
act(() => document.dispatchEvent(new Event("visibilitychange")));
|
|
97
|
+
|
|
98
|
+
await waitFor(() => expect(list).toHaveBeenCalledTimes(2));
|
|
99
|
+
await waitFor(() =>
|
|
100
|
+
expect(runtimeRef.current!.threads.getState().loadError).toBeUndefined(),
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
act(() => document.dispatchEvent(new Event("visibilitychange")));
|
|
104
|
+
await act(async () => {});
|
|
105
|
+
|
|
106
|
+
expect(list).toHaveBeenCalledTimes(2);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useState,
|
|
3
3
|
useEffect,
|
|
4
|
+
useInsertionEffect,
|
|
4
5
|
useMemo,
|
|
5
6
|
useRef,
|
|
6
7
|
useCallback,
|
|
@@ -12,6 +13,8 @@ import type { RemoteThreadListOptions } from "../../runtimes/remote-thread-list/
|
|
|
12
13
|
import type { AssistantRuntimeCore } from "../../runtime/interfaces/assistant-runtime-core";
|
|
13
14
|
import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
|
|
14
15
|
import { RemoteThreadListThreadListRuntimeCore } from "./RemoteThreadListThreadListRuntimeCore";
|
|
16
|
+
import { WritableSubscribable } from "../../subscribable/subscribable";
|
|
17
|
+
import { useSubscribable } from "../../store/runtime-clients/useSubscribable";
|
|
15
18
|
import { useAui } from "@assistant-ui/store";
|
|
16
19
|
|
|
17
20
|
class RemoteThreadListRuntimeCore
|
|
@@ -37,25 +40,73 @@ const useRemoteThreadListRuntimeImpl = (
|
|
|
37
40
|
options: RemoteThreadListOptions,
|
|
38
41
|
): AssistantRuntime => {
|
|
39
42
|
const [runtime] = useState(() => new RemoteThreadListRuntimeCore(options));
|
|
43
|
+
|
|
44
|
+
// Insertion-effect cleanup runs only when React deletes the fiber, so a
|
|
45
|
+
// hidden <Activity> or a re-suspended boundary keeps the threads alive; the
|
|
46
|
+
// disposal is deferred to a microtask because it notifies subscribers and
|
|
47
|
+
// React forbids scheduling updates from an insertion effect.
|
|
48
|
+
useInsertionEffect(
|
|
49
|
+
() => () => queueMicrotask(() => runtime.threads.__internal_dispose()),
|
|
50
|
+
[runtime],
|
|
51
|
+
);
|
|
52
|
+
|
|
40
53
|
useEffect(() => {
|
|
41
54
|
runtime.threads.__internal_setOptions(options);
|
|
42
55
|
runtime.threads.__internal_load();
|
|
43
56
|
}, [runtime, options]);
|
|
44
57
|
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const reloadAfterError = () => {
|
|
64
|
+
if (runtime.threads.loadError !== undefined) {
|
|
65
|
+
void runtime.threads.reload();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const reloadAfterVisible = () => {
|
|
69
|
+
if (document.visibilityState === "visible") reloadAfterError();
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
window.addEventListener("online", reloadAfterError);
|
|
73
|
+
document.addEventListener("visibilitychange", reloadAfterVisible);
|
|
74
|
+
return () => {
|
|
75
|
+
window.removeEventListener("online", reloadAfterError);
|
|
76
|
+
document.removeEventListener("visibilitychange", reloadAfterVisible);
|
|
77
|
+
};
|
|
78
|
+
}, [runtime]);
|
|
79
|
+
|
|
45
80
|
return useMemo(() => new AssistantRuntimeImpl(runtime), [runtime]);
|
|
46
81
|
};
|
|
47
82
|
|
|
48
83
|
export const useRemoteThreadListRuntime = (
|
|
49
84
|
options: RemoteThreadListOptions,
|
|
50
85
|
): AssistantRuntime => {
|
|
51
|
-
const
|
|
52
|
-
|
|
86
|
+
const [runtimeHookStore] = useState(
|
|
87
|
+
() => new WritableSubscribable(options.runtimeHook),
|
|
88
|
+
);
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
runtimeHookStore.setState(options.runtimeHook);
|
|
91
|
+
}, [runtimeHookStore, options.runtimeHook]);
|
|
53
92
|
|
|
54
93
|
const initialThreadIdRef = useRef(options.initialThreadId);
|
|
55
94
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
95
|
+
// Thread resources subscribe to the store rather than reading a ref, so a
|
|
96
|
+
// hook published at commit reaches exactly the resources that use it and an
|
|
97
|
+
// abandoned render publishes nothing. The store pins its server snapshot to
|
|
98
|
+
// the constructor value for hydration, which tap reads on any never-mounted
|
|
99
|
+
// fiber, so the live state serves as the server snapshot here.
|
|
100
|
+
const stableRuntimeHook = useCallback(
|
|
101
|
+
function useCommittedRuntimeHook() {
|
|
102
|
+
return useSubscribable({
|
|
103
|
+
subscribe: runtimeHookStore.subscribe,
|
|
104
|
+
getState: runtimeHookStore.getState,
|
|
105
|
+
getServerSnapshot: runtimeHookStore.getState,
|
|
106
|
+
})();
|
|
107
|
+
},
|
|
108
|
+
[runtimeHookStore],
|
|
109
|
+
);
|
|
59
110
|
|
|
60
111
|
const onThreadIdChange = useEffectEvent((threadId: string | undefined) => {
|
|
61
112
|
options.onThreadIdChange?.(threadId);
|
|
@@ -91,7 +142,7 @@ export const useRemoteThreadListRuntime = (
|
|
|
91
142
|
|
|
92
143
|
// If allowNesting is true and already inside a thread list context,
|
|
93
144
|
// just call the runtimeHook directly (no-op behavior)
|
|
94
|
-
return
|
|
145
|
+
return options.runtimeHook();
|
|
95
146
|
}
|
|
96
147
|
|
|
97
148
|
const runtime = useRemoteThreadListRuntimeImpl(stableOptions);
|
|
@@ -83,10 +83,14 @@ export type ToolCallMessagePartProps<
|
|
|
83
83
|
/**
|
|
84
84
|
* Responds to a server-side tool approval gate. Only valid while
|
|
85
85
|
* `approval` is set on the part, `approval.approved === undefined`, and
|
|
86
|
-
* no `approval.resolution` is recorded. Accepts a boolean decision
|
|
87
|
-
* id of one of `approval.options
|
|
86
|
+
* no `approval.resolution` is recorded. Accepts a boolean decision, the
|
|
87
|
+
* id of one of `approval.options` (option kinds resolve to the boolean),
|
|
88
|
+
* or a free-form answer when the request accepts one.
|
|
89
|
+
*
|
|
90
|
+
* Resolves once the runtime has accepted the response, and rejects when
|
|
91
|
+
* it could not be recorded, so the controls can stay retryable.
|
|
88
92
|
*/
|
|
89
|
-
respondToApproval: (response: ToolApprovalResponse) => void
|
|
93
|
+
respondToApproval: (response: ToolApprovalResponse) => Promise<void>;
|
|
90
94
|
};
|
|
91
95
|
|
|
92
96
|
/** Component used to render a tool-call message part. */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ToolCallMessagePartComponent } from "../MessagePartComponentTypes";
|
|
2
2
|
import type { Unsubscribe } from "../../..";
|
|
3
|
+
import type { ToolCallText } from "../../../model-context/tool-call-text";
|
|
3
4
|
|
|
4
5
|
export type McpAppResourceOutput = {
|
|
5
6
|
readonly render: ToolCallMessagePartComponent;
|
|
@@ -12,6 +13,7 @@ export type McpAppResourceOutput = {
|
|
|
12
13
|
*/
|
|
13
14
|
type ToolRegistration = {
|
|
14
15
|
readonly render: ToolCallMessagePartComponent;
|
|
16
|
+
readonly renderText?: ToolCallText<any, any, unknown> | undefined;
|
|
15
17
|
/** Whether this UI renders standalone, outside the chain-of-thought trace. */
|
|
16
18
|
readonly standalone: boolean;
|
|
17
19
|
};
|
|
@@ -28,7 +28,7 @@ type MessagePartSnapshotBinding = SubscribableWithState<
|
|
|
28
28
|
export type MessagePartRuntime = {
|
|
29
29
|
addToolResult(result: any | ToolResponse<any>): void;
|
|
30
30
|
resumeToolCall(payload: unknown): void;
|
|
31
|
-
respondToToolApproval(response: ToolApprovalResponse): void
|
|
31
|
+
respondToToolApproval(response: ToolApprovalResponse): Promise<void>;
|
|
32
32
|
|
|
33
33
|
readonly path: MessagePartRuntimePath;
|
|
34
34
|
getState(): MessagePartState;
|
|
@@ -113,7 +113,7 @@ export class MessagePartRuntimeImpl implements MessagePartRuntime {
|
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
public respondToToolApproval(response: ToolApprovalResponse) {
|
|
116
|
+
public respondToToolApproval(response: ToolApprovalResponse): Promise<void> {
|
|
117
117
|
const state = this.contentBinding.getState();
|
|
118
118
|
if (!state) throw new Error("Message part is not available");
|
|
119
119
|
|
|
@@ -131,7 +131,7 @@ export class MessagePartRuntimeImpl implements MessagePartRuntime {
|
|
|
131
131
|
|
|
132
132
|
if (!this.threadApi) throw new Error("Thread API is not available");
|
|
133
133
|
|
|
134
|
-
this.threadApi
|
|
134
|
+
return this.threadApi
|
|
135
135
|
.getState()
|
|
136
136
|
.respondToToolApproval(
|
|
137
137
|
resolveToolApprovalResponse(state.approval, response),
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
type MessageStateBinding,
|
|
12
12
|
} from "./message-runtime";
|
|
13
13
|
import { toMessagePartStatus } from "../../utils/normalizePartStatus";
|
|
14
|
+
import { convertExternalMessageChunk } from "../utils/external-message-conversion";
|
|
14
15
|
|
|
15
16
|
const messagePath = {
|
|
16
17
|
ref: "threads.main.messages[0]",
|
|
@@ -256,6 +257,80 @@ describe("toMessagePartStatus", () => {
|
|
|
256
257
|
});
|
|
257
258
|
|
|
258
259
|
describe("MessageRuntimeImpl paths", () => {
|
|
260
|
+
it.each([undefined, ""])(
|
|
261
|
+
"looks up separate tool calls with ID %s without breaking provider result matching",
|
|
262
|
+
(toolCallId) => {
|
|
263
|
+
const id = toolCallId === undefined ? {} : { toolCallId };
|
|
264
|
+
const converted = convertExternalMessageChunk(
|
|
265
|
+
{
|
|
266
|
+
inputs: [{}],
|
|
267
|
+
outputs: [
|
|
268
|
+
{
|
|
269
|
+
role: "assistant",
|
|
270
|
+
content: [
|
|
271
|
+
{ type: "tool-call", ...id, toolName: "weather", args: {} },
|
|
272
|
+
{ type: "tool-call", ...id, toolName: "search", args: {} },
|
|
273
|
+
{
|
|
274
|
+
type: "tool-call",
|
|
275
|
+
toolCallId: "provider-call",
|
|
276
|
+
toolName: "calendar",
|
|
277
|
+
args: { day: "Monday" },
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
role: "assistant",
|
|
283
|
+
content: [
|
|
284
|
+
{
|
|
285
|
+
type: "tool-call",
|
|
286
|
+
toolCallId: "provider-call",
|
|
287
|
+
toolName: "calendar",
|
|
288
|
+
args: { day: "Tuesday" },
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
role: "tool",
|
|
294
|
+
toolCallId: "provider-call",
|
|
295
|
+
toolName: "calendar",
|
|
296
|
+
result: "Meeting at noon",
|
|
297
|
+
},
|
|
298
|
+
],
|
|
299
|
+
},
|
|
300
|
+
0,
|
|
301
|
+
1,
|
|
302
|
+
false,
|
|
303
|
+
undefined,
|
|
304
|
+
);
|
|
305
|
+
const runtime = new MessageRuntimeImpl(
|
|
306
|
+
{
|
|
307
|
+
...messageBinding,
|
|
308
|
+
getState: () => ({ ...message, ...converted }),
|
|
309
|
+
},
|
|
310
|
+
threadBinding,
|
|
311
|
+
);
|
|
312
|
+
const calls = converted.content.filter(
|
|
313
|
+
(part) => part.type === "tool-call",
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
expect(
|
|
317
|
+
calls.map((call) =>
|
|
318
|
+
runtime.getMessagePartByToolCallId(call.toolCallId).getState(),
|
|
319
|
+
),
|
|
320
|
+
).toMatchObject([
|
|
321
|
+
{ type: "tool-call", toolName: "weather" },
|
|
322
|
+
{ type: "tool-call", toolName: "search" },
|
|
323
|
+
{
|
|
324
|
+
type: "tool-call",
|
|
325
|
+
toolCallId: "provider-call",
|
|
326
|
+
toolName: "calendar",
|
|
327
|
+
args: { day: "Tuesday" },
|
|
328
|
+
result: "Meeting at noon",
|
|
329
|
+
},
|
|
330
|
+
]);
|
|
331
|
+
},
|
|
332
|
+
);
|
|
333
|
+
|
|
259
334
|
it("appends nested selectors to the message path", () => {
|
|
260
335
|
const runtime = new MessageRuntimeImpl(messageBinding, threadBinding);
|
|
261
336
|
|
|
@@ -30,12 +30,17 @@ import type { ThreadListItemStatus } from "../interfaces/thread-list-runtime-cor
|
|
|
30
30
|
|
|
31
31
|
export type { ThreadListItemState, ThreadListItemStatus };
|
|
32
32
|
|
|
33
|
+
export type ThreadListItemGenerateTitleOptions = {
|
|
34
|
+
/** Marks a generation started by the automatic title trigger. */
|
|
35
|
+
automatic?: boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
33
38
|
export type ThreadListItemRuntime = {
|
|
34
39
|
readonly path: ThreadListItemRuntimePath;
|
|
35
40
|
getState(): ThreadListItemState;
|
|
36
41
|
|
|
37
42
|
initialize(): Promise<{ remoteId: string; externalId: string | undefined }>;
|
|
38
|
-
generateTitle(): Promise<void>;
|
|
43
|
+
generateTitle(options?: ThreadListItemGenerateTitleOptions): Promise<void>;
|
|
39
44
|
|
|
40
45
|
switchTo(options?: { unarchive?: boolean }): Promise<void>;
|
|
41
46
|
rename(newTitle: string): Promise<void>;
|
|
@@ -147,9 +152,11 @@ export class ThreadListItemRuntimeImpl implements ThreadListItemRuntime {
|
|
|
147
152
|
return this._threadListBinding.initialize(state.id);
|
|
148
153
|
}
|
|
149
154
|
|
|
150
|
-
public generateTitle(
|
|
155
|
+
public generateTitle(
|
|
156
|
+
options?: ThreadListItemGenerateTitleOptions,
|
|
157
|
+
): Promise<void> {
|
|
151
158
|
const state = this._core.getState();
|
|
152
|
-
return this._threadListBinding.generateTitle(state.id);
|
|
159
|
+
return this._threadListBinding.generateTitle(state.id, options);
|
|
153
160
|
}
|
|
154
161
|
|
|
155
162
|
public unstable_on<E extends ThreadListItemEventType>(
|
|
@@ -7,11 +7,15 @@ import {
|
|
|
7
7
|
SKIP_UPDATE,
|
|
8
8
|
ShallowMemoizeSubject,
|
|
9
9
|
} from "../../subscribable/subscribable";
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
ThreadListRuntimeCore,
|
|
12
|
+
ThreadListRuntimeEvent,
|
|
13
|
+
} from "../interfaces/thread-list-runtime-core";
|
|
11
14
|
import {
|
|
12
15
|
type ThreadListItemRuntime,
|
|
13
16
|
ThreadListItemRuntimeImpl,
|
|
14
17
|
type ThreadListItemState,
|
|
18
|
+
type ThreadListItemStateBinding,
|
|
15
19
|
} from "./thread-list-item-runtime";
|
|
16
20
|
import {
|
|
17
21
|
type ThreadListItemRuntimeBinding,
|
|
@@ -21,6 +25,7 @@ import {
|
|
|
21
25
|
} from "./thread-runtime";
|
|
22
26
|
|
|
23
27
|
const RESOLVED_PROMISE = Promise.resolve();
|
|
28
|
+
const NOOP_UNSUBSCRIBE = () => {};
|
|
24
29
|
|
|
25
30
|
export type ThreadListState = {
|
|
26
31
|
readonly mainThreadId: string;
|
|
@@ -28,6 +33,8 @@ export type ThreadListState = {
|
|
|
28
33
|
readonly threadIds: readonly string[];
|
|
29
34
|
readonly archivedThreadIds: readonly string[];
|
|
30
35
|
readonly isLoading: boolean;
|
|
36
|
+
/** The error thrown by the most recent thread list load that failed, cleared when a later load starts. */
|
|
37
|
+
readonly loadError: unknown;
|
|
31
38
|
readonly isLoadingMore: boolean;
|
|
32
39
|
readonly hasMore: boolean;
|
|
33
40
|
readonly threadItems: Readonly<
|
|
@@ -57,6 +64,16 @@ export type ThreadListRuntime = {
|
|
|
57
64
|
): Promise<void>;
|
|
58
65
|
switchToNewThread(): Promise<void>;
|
|
59
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Observes lifecycle events on every thread this list keeps alive, so an
|
|
69
|
+
* event that fires while its thread is not selected stays observable. Thread
|
|
70
|
+
* lists that mount only the main thread never emit; their main thread's
|
|
71
|
+
* runtime is observed directly.
|
|
72
|
+
*/
|
|
73
|
+
unstable_subscribeThreadEvents(
|
|
74
|
+
callback: (event: ThreadListRuntimeEvent) => void,
|
|
75
|
+
): Unsubscribe;
|
|
76
|
+
|
|
60
77
|
getLoadThreadsPromise(): Promise<void>;
|
|
61
78
|
reload(): Promise<void>;
|
|
62
79
|
/**
|
|
@@ -83,6 +100,7 @@ const getThreadListState = (
|
|
|
83
100
|
threadIds: threadList.threadIds,
|
|
84
101
|
archivedThreadIds: threadList.archivedThreadIds,
|
|
85
102
|
isLoading: threadList.isLoading,
|
|
103
|
+
loadError: threadList.loadError,
|
|
86
104
|
isLoadingMore: threadList.isLoadingMore ?? false,
|
|
87
105
|
hasMore: threadList.hasMore ?? false,
|
|
88
106
|
threadItems: threadList.threadItems,
|
|
@@ -171,6 +189,8 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
|
171
189
|
protected __internal_bindMethods() {
|
|
172
190
|
this.switchToThread = this.switchToThread.bind(this);
|
|
173
191
|
this.switchToNewThread = this.switchToNewThread.bind(this);
|
|
192
|
+
this.unstable_subscribeThreadEvents =
|
|
193
|
+
this.unstable_subscribeThreadEvents.bind(this);
|
|
174
194
|
this.getLoadThreadsPromise = this.getLoadThreadsPromise.bind(this);
|
|
175
195
|
this.reload = this.reload.bind(this);
|
|
176
196
|
this.reloadMainThread = this.reloadMainThread.bind(this);
|
|
@@ -194,6 +214,14 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
|
194
214
|
return this._core.switchToNewThread();
|
|
195
215
|
}
|
|
196
216
|
|
|
217
|
+
public unstable_subscribeThreadEvents(
|
|
218
|
+
callback: (event: ThreadListRuntimeEvent) => void,
|
|
219
|
+
): Unsubscribe {
|
|
220
|
+
return (
|
|
221
|
+
this._core.unstable_subscribeThreadEvents?.(callback) ?? NOOP_UNSUBSCRIBE
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
197
225
|
public getLoadThreadsPromise(): Promise<void> {
|
|
198
226
|
return this._core.getLoadThreadsPromise();
|
|
199
227
|
}
|
|
@@ -226,6 +254,21 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
|
226
254
|
return this._mainThreadListItemRuntime;
|
|
227
255
|
}
|
|
228
256
|
|
|
257
|
+
private _createItemStateBinding(
|
|
258
|
+
threadId: string,
|
|
259
|
+
): ThreadListItemStateBinding {
|
|
260
|
+
return new ShallowMemoizeSubject({
|
|
261
|
+
path: {
|
|
262
|
+
ref: `threadItems[threadId=${threadId}]`,
|
|
263
|
+
threadSelector: { type: "threadId", threadId },
|
|
264
|
+
},
|
|
265
|
+
getState: () => {
|
|
266
|
+
return getThreadListItemState(this._core, threadId);
|
|
267
|
+
},
|
|
268
|
+
subscribe: (callback) => this._core.subscribe(callback),
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
229
272
|
public getById(threadId: string) {
|
|
230
273
|
return new this._runtimeFactory(
|
|
231
274
|
new NestedSubscriptionSubject({
|
|
@@ -236,7 +279,7 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
|
236
279
|
getState: () => this._core.getThreadRuntimeCore(threadId),
|
|
237
280
|
subscribe: (callback) => this._core.subscribe(callback),
|
|
238
281
|
}),
|
|
239
|
-
this.
|
|
282
|
+
this._createItemStateBinding(threadId),
|
|
240
283
|
);
|
|
241
284
|
}
|
|
242
285
|
|
|
@@ -277,16 +320,7 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
|
277
320
|
|
|
278
321
|
public getItemById(threadId: string) {
|
|
279
322
|
return new ThreadListItemRuntimeImpl(
|
|
280
|
-
|
|
281
|
-
path: {
|
|
282
|
-
ref: `threadItems[threadId=${threadId}]`,
|
|
283
|
-
threadSelector: { type: "threadId", threadId },
|
|
284
|
-
},
|
|
285
|
-
getState: () => {
|
|
286
|
-
return getThreadListItemState(this._core, threadId);
|
|
287
|
-
},
|
|
288
|
-
subscribe: (callback) => this._core.subscribe(callback),
|
|
289
|
-
}),
|
|
323
|
+
this._createItemStateBinding(threadId),
|
|
290
324
|
this._core,
|
|
291
325
|
);
|
|
292
326
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { LocalRuntimeCore } from "../../runtimes/local/local-runtime-core";
|
|
3
|
+
import { ExternalStoreRuntimeCore } from "../../runtimes/external-store/external-store-runtime-core";
|
|
4
|
+
import { AssistantRuntimeImpl } from "./assistant-runtime";
|
|
5
|
+
|
|
6
|
+
describe("ThreadRuntime.append", () => {
|
|
7
|
+
it.each([
|
|
8
|
+
{ parent: { parentId: null }, expectedParent: null, visible: ["new"] },
|
|
9
|
+
{
|
|
10
|
+
parent: {},
|
|
11
|
+
expectedParent: "tail",
|
|
12
|
+
visible: ["root", "tail", "new"],
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
parent: { parentId: "root" },
|
|
16
|
+
expectedParent: "root",
|
|
17
|
+
visible: ["root", "new"],
|
|
18
|
+
},
|
|
19
|
+
])(
|
|
20
|
+
"selects the branch under $expectedParent",
|
|
21
|
+
({ parent, expectedParent, visible }) => {
|
|
22
|
+
const core = new LocalRuntimeCore(
|
|
23
|
+
{ adapters: { chatModel: { run: async () => ({ content: [] }) } } },
|
|
24
|
+
[
|
|
25
|
+
{ id: "root", role: "user", content: "root" },
|
|
26
|
+
{ id: "tail", role: "assistant", content: "tail" },
|
|
27
|
+
],
|
|
28
|
+
);
|
|
29
|
+
const thread = new AssistantRuntimeImpl(core).thread;
|
|
30
|
+
|
|
31
|
+
thread.append({
|
|
32
|
+
...parent,
|
|
33
|
+
content: [{ type: "text", text: "new" }],
|
|
34
|
+
startRun: false,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
expect(
|
|
38
|
+
thread.getState().messages.map((message) => message.content),
|
|
39
|
+
).toEqual(visible.map((text) => [{ type: "text", text }]));
|
|
40
|
+
expect(thread.export().messages.at(-1)?.parentId).toBe(expectedParent);
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("ThreadRuntime.append with an external store", () => {
|
|
46
|
+
it("routes an explicit root parent to onEdit instead of onNew", async () => {
|
|
47
|
+
const onNew = vi.fn(async () => {});
|
|
48
|
+
const onEdit = vi.fn(async () => {});
|
|
49
|
+
const core = new ExternalStoreRuntimeCore({
|
|
50
|
+
messages: [
|
|
51
|
+
{
|
|
52
|
+
id: "old",
|
|
53
|
+
role: "user",
|
|
54
|
+
content: [{ type: "text", text: "old" }],
|
|
55
|
+
createdAt: new Date(0),
|
|
56
|
+
attachments: [],
|
|
57
|
+
metadata: { custom: {} },
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
onNew,
|
|
61
|
+
onEdit,
|
|
62
|
+
});
|
|
63
|
+
const thread = new AssistantRuntimeImpl(core).thread;
|
|
64
|
+
|
|
65
|
+
thread.append({
|
|
66
|
+
parentId: null,
|
|
67
|
+
content: [{ type: "text", text: "new root" }],
|
|
68
|
+
startRun: false,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
await vi.waitFor(() =>
|
|
72
|
+
expect(onEdit).toHaveBeenCalledExactlyOnceWith(
|
|
73
|
+
expect.objectContaining({ parentId: null }),
|
|
74
|
+
),
|
|
75
|
+
);
|
|
76
|
+
expect(onNew).not.toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -77,6 +77,10 @@ const toStartRunConfig = (message: CreateStartRunConfig): StartRunConfig => {
|
|
|
77
77
|
export type CreateAppendMessage =
|
|
78
78
|
| string
|
|
79
79
|
| {
|
|
80
|
+
/**
|
|
81
|
+
* An omitted value or `undefined` selects the current tail.
|
|
82
|
+
* `null` selects a root branch.
|
|
83
|
+
*/
|
|
80
84
|
parentId?: string | null | undefined;
|
|
81
85
|
sourceId?: string | null | undefined;
|
|
82
86
|
role?: AppendMessage["role"] | undefined;
|
|
@@ -107,7 +111,10 @@ const toAppendMessage = (
|
|
|
107
111
|
|
|
108
112
|
return {
|
|
109
113
|
createdAt: message.createdAt ?? new Date(),
|
|
110
|
-
parentId:
|
|
114
|
+
parentId:
|
|
115
|
+
message.parentId === undefined
|
|
116
|
+
? (messages.at(-1)?.id ?? null)
|
|
117
|
+
: message.parentId,
|
|
111
118
|
sourceId: message.sourceId ?? null,
|
|
112
119
|
role: message.role ?? "user",
|
|
113
120
|
content: message.content,
|