@assistant-ui/core 0.3.17 → 0.3.19
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/adapters/speech.d.ts.map +1 -1
- package/dist/adapters/speech.js +13 -3
- package/dist/adapters/speech.js.map +1 -1
- package/dist/adapters/thread-history.d.ts +4 -0
- package/dist/adapters/thread-history.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +4 -3
- package/dist/internal.js +3 -2
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +35 -14
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/frame/provider.d.ts +2 -0
- package/dist/model-context/frame/provider.d.ts.map +1 -1
- package/dist/model-context/frame/provider.js +30 -7
- 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 +27 -18
- 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/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/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js +45 -7
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/DataRenderers.d.ts.map +1 -1
- package/dist/react/client/DataRenderers.js +20 -15
- package/dist/react/client/DataRenderers.js.map +1 -1
- package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
- package/dist/react/client/InMemoryThreadList.js +62 -56
- 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 +35 -32
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/RemoteThreadList.d.ts +1 -0
- package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
- package/dist/react/client/RemoteThreadList.js +154 -143
- 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 +18 -16
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/client/interactable-model-context.d.ts.map +1 -1
- package/dist/react/client/interactable-model-context.js +3 -2
- package/dist/react/client/interactable-model-context.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +2 -2
- package/dist/react/interactables-legacy/Interactables.js +242 -121
- package/dist/react/interactables-legacy/Interactables.js.map +1 -1
- package/dist/react/interactables-legacy/useAssistantInteractable.d.ts.map +1 -1
- package/dist/react/interactables-legacy/useAssistantInteractable.js +3 -0
- package/dist/react/interactables-legacy/useAssistantInteractable.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/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/useInteractable.d.ts.map +1 -1
- package/dist/react/model-context/useInteractable.js +4 -1
- package/dist/react/model-context/useInteractable.js.map +1 -1
- package/dist/react/model-context/useInteractableVersions.js +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/primitives/message/MessageGroupedParts.d.ts +11 -2
- package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.js +3 -2
- package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
- package/dist/react/primitives/part/PartMessages.d.ts +1 -0
- package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
- package/dist/react/primitives/part/PartMessages.js +1 -0
- package/dist/react/primitives/part/PartMessages.js.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.js +6 -5
- package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +16 -8
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +5 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +105 -104
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.d.ts +1 -0
- package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.js +13 -11
- package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +5 -24
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +354 -226
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +1 -0
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +22 -2
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +40 -15
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js +62 -15
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts +2 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +6 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/sdkIdentity.d.ts +6 -0
- package/dist/react/runtimes/cloud/sdkIdentity.d.ts.map +1 -0
- package/dist/react/runtimes/cloud/sdkIdentity.js +9 -0
- package/dist/react/runtimes/cloud/sdkIdentity.js.map +1 -0
- package/dist/react/runtimes/external-message-converter.d.ts +12 -2
- package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
- package/dist/react/runtimes/external-message-converter.js +26 -61
- 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 +64 -24
- package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
- package/dist/react/utils/groupParts.d.ts +6 -1
- package/dist/react/utils/groupParts.d.ts.map +1 -1
- package/dist/react/utils/groupParts.js +6 -0
- package/dist/react/utils/groupParts.js.map +1 -1
- package/dist/react/utils/useJSONEqual.d.ts +3 -1
- package/dist/react/utils/useJSONEqual.d.ts.map +1 -1
- package/dist/react/utils/useJSONEqual.js +6 -1
- package/dist/react/utils/useJSONEqual.js.map +1 -1
- package/dist/react/utils/useJSONSchemaDependency.d.ts +7 -0
- package/dist/react/utils/useJSONSchemaDependency.d.ts.map +1 -0
- package/dist/react/utils/useJSONSchemaDependency.js +20 -0
- package/dist/react/utils/useJSONSchemaDependency.js.map +1 -0
- 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 +3 -0
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +18 -14
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +4 -0
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +3 -6
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -0
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +62 -22
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -0
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +161 -69
- 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 +4 -1
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/queue/message-queue.d.ts +5 -0
- package/dist/runtime/queue/message-queue.d.ts.map +1 -1
- package/dist/runtime/queue/message-queue.js +61 -6
- package/dist/runtime/queue/message-queue.js.map +1 -1
- package/dist/runtime/utils/auto-status.d.ts +6 -2
- package/dist/runtime/utils/auto-status.d.ts.map +1 -1
- package/dist/runtime/utils/auto-status.js +12 -4
- package/dist/runtime/utils/auto-status.js.map +1 -1
- package/dist/runtime/utils/external-message-conversion.d.ts +16 -4
- package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -1
- package/dist/runtime/utils/external-message-conversion.js +49 -13
- 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 +18 -9
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/thread-message-like.d.ts +2 -1
- package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
- package/dist/runtime/utils/thread-message-like.js +5 -3
- package/dist/runtime/utils/thread-message-like.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +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.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +8 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/internal.d.ts +3 -3
- 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 +4 -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 +130 -42
- 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 +3 -1
- package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/title.js +9 -1
- package/dist/runtimes/remote-thread-list/title.js.map +1 -1
- package/dist/runtimes/remote-thread-list/types.d.ts +10 -0
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +2 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/external-thread.d.ts.map +1 -1
- package/dist/store/clients/external-thread.js +260 -203
- 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 +1 -0
- 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 +5 -4
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/clients/thread-tasks.d.ts +13 -0
- package/dist/store/clients/thread-tasks.d.ts.map +1 -0
- package/dist/store/clients/thread-tasks.js +69 -0
- package/dist/store/clients/thread-tasks.js.map +1 -0
- package/dist/store/index.d.ts +3 -2
- package/dist/store/index.js +3 -3
- package/dist/store/primitive-predicates.d.ts.map +1 -1
- package/dist/store/primitive-predicates.js +4 -4
- 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 +97 -61
- 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 +1 -1
- 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 +54 -52
- 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 +246 -126
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scope-registration.d.ts +2 -0
- package/dist/store/scope-registration.d.ts.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/task.d.ts +36 -0
- package/dist/store/scopes/task.d.ts.map +1 -0
- package/dist/store/scopes/task.js +0 -0
- 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 +28 -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 +2 -1
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/subscribable/subscribable.js +23 -15
- 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/index.d.ts +2 -2
- package/dist/types/message.d.ts +8 -1
- package/dist/types/message.d.ts.map +1 -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 +88 -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/getGroupStatus.d.ts +18 -2
- package/dist/utils/getGroupStatus.d.ts.map +1 -1
- package/dist/utils/getGroupStatus.js +32 -7
- package/dist/utils/getGroupStatus.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/dist/utils/wire-media.d.ts.map +1 -1
- package/dist/utils/wire-media.js +2 -2
- package/dist/utils/wire-media.js.map +1 -1
- package/package.json +11 -11
- package/src/adapters/attachment.test.ts +50 -1
- package/src/adapters/attachment.ts +7 -4
- package/src/adapters/speech.test.ts +236 -0
- package/src/adapters/speech.ts +17 -10
- package/src/adapters/thread-history.ts +3 -0
- package/src/index.ts +2 -0
- package/src/internal.ts +4 -0
- package/src/model-context/frame/host.test.ts +137 -1
- package/src/model-context/frame/host.ts +49 -16
- package/src/model-context/frame/provider.test.ts +71 -0
- package/src/model-context/frame/provider.ts +37 -7
- package/src/model-context/interactable-composer-metadata.test.ts +58 -0
- package/src/model-context/interactable-composer-metadata.ts +19 -13
- package/src/model-context/registry.test.ts +12 -0
- package/src/model-context/registry.ts +3 -2
- package/src/model-context/types.test.ts +25 -0
- package/src/model-context/types.ts +9 -4
- package/src/react/RuntimeAdapter.test.ts +34 -0
- package/src/react/adapters/LocalStorageThreadListAdapter.test.ts +244 -0
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +104 -7
- package/src/react/client/DataRenderers.test.tsx +45 -0
- package/src/react/client/DataRenderers.ts +13 -9
- package/src/react/client/InMemoryThreadList.ts +1 -0
- package/src/react/client/Interactables.test.ts +72 -1
- package/src/react/client/Interactables.ts +22 -14
- package/src/react/client/RemoteThreadList.background.test.ts +148 -6
- package/src/react/client/RemoteThreadList.concurrent.test.tsx +42 -1
- package/src/react/client/RemoteThreadList.test.ts +386 -4
- package/src/react/client/RemoteThreadList.ts +181 -112
- package/src/react/client/Tools.ts +22 -11
- package/src/react/client/interactable-model-context.test.ts +44 -0
- package/src/react/client/interactable-model-context.ts +3 -2
- package/src/react/index.ts +5 -1
- package/src/react/interactables-legacy/Interactables.ts +16 -16
- package/src/react/interactables-legacy/useAssistantInteractable.test.tsx +132 -0
- package/src/react/interactables-legacy/useAssistantInteractable.ts +10 -1
- package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +9 -10
- package/src/react/model-context/makeAssistantTool.ts +2 -2
- package/src/react/model-context/useAssistantTool.ts +2 -2
- package/src/react/model-context/useInteractable.test.tsx +177 -0
- package/src/react/model-context/useInteractable.ts +3 -0
- package/src/react/model-context/useToolArgsStatus.test.tsx +30 -0
- package/src/react/model-context/useToolArgsStatus.ts +2 -1
- package/src/react/primitive-hooks/useActionBarCopy.test.ts +0 -1
- package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +0 -1
- package/src/react/primitives/message/MessageGroupedParts.test.tsx +96 -0
- package/src/react/primitives/message/MessageGroupedParts.tsx +15 -4
- package/src/react/primitives/part/PartMessages.test.tsx +104 -1
- package/src/react/primitives/part/PartMessages.tsx +1 -0
- package/src/react/primitives/thread/ThreadMessages.test.tsx +142 -0
- package/src/react/primitives/thread/ThreadMessages.tsx +8 -5
- package/src/react/providers/ReadonlyThreadProvider.test.tsx +56 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.destroy.test.tsx +172 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +33 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +7 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +28 -5
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.load-error.test.ts +132 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +105 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +143 -112
- package/src/react/runtimes/RemoteThreadResource.test.ts +9 -0
- package/src/react/runtimes/RemoteThreadResource.ts +19 -12
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +20 -14
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +703 -6
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +492 -402
- package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.test.ts +77 -0
- package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +27 -1
- package/src/react/runtimes/cloud/auiV0.ts +160 -25
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +36 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +8 -1
- package/src/react/runtimes/cloud/sdkIdentity.ts +9 -0
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +18 -4
- package/src/react/runtimes/external-message-converter.test.ts +136 -1
- package/src/react/runtimes/external-message-converter.ts +39 -93
- 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.load-error.test.tsx +108 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.ts +34 -1
- package/src/react/utils/groupParts.ts +12 -1
- package/src/react/utils/useJSONEqual.ts +9 -0
- package/src/react/utils/useJSONSchemaDependency.ts +22 -0
- 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 +21 -11
- package/src/runtime/api/thread-runtime.test.ts +136 -0
- package/src/runtime/api/thread-runtime.ts +10 -5
- package/src/runtime/base/base-composer-runtime-core.ts +105 -24
- package/src/runtime/base/base-thread-runtime-core.test.ts +1063 -2
- package/src/runtime/base/base-thread-runtime-core.ts +228 -87
- package/src/runtime/interfaces/composer-runtime-core.ts +10 -5
- package/src/runtime/interfaces/thread-list-runtime-core.ts +5 -1
- package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
- package/src/runtime/queue/message-queue.ts +68 -6
- package/src/runtime/utils/auto-status.test.ts +112 -1
- package/src/runtime/utils/auto-status.ts +31 -5
- package/src/runtime/utils/external-message-conversion.test.ts +202 -0
- package/src/runtime/utils/external-message-conversion.ts +123 -32
- package/src/runtime/utils/message-repository.test.ts +49 -0
- package/src/runtime/utils/message-repository.ts +32 -20
- package/src/runtime/utils/thread-message-like.test.ts +52 -0
- package/src/runtime/utils/thread-message-like.ts +5 -1
- 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 +31 -1
- package/src/runtimes/internal.ts +1 -0
- package/src/runtimes/local/local-thread-runtime-core.test.ts +21 -0
- package/src/runtimes/local/local-thread-runtime-core.ts +11 -1
- package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +128 -2
- package/src/runtimes/remote-thread-list/remote-thread-state.ts +182 -42
- 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 +13 -0
- package/src/runtimes/remote-thread-list/types.ts +10 -0
- package/src/runtimes/tool-invocations/EDGE_CASES.md +2 -6
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +133 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +10 -6
- package/src/store/clients/external-thread.ts +67 -4
- 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 +40 -0
- package/src/store/clients/suggestions.ts +13 -10
- package/src/store/clients/thread-tasks.test.ts +274 -0
- package/src/store/clients/thread-tasks.ts +138 -0
- package/src/store/index.ts +8 -0
- package/src/store/primitive-predicates.test.ts +48 -5
- package/src/store/primitive-predicates.ts +7 -2
- 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 +1 -0
- package/src/store/runtime-clients/thread-runtime-client.ts +89 -11
- package/src/store/scope-registration.ts +2 -0
- package/src/store/scopes/composer.ts +16 -4
- package/src/store/scopes/message.ts +14 -0
- package/src/store/scopes/task.ts +34 -0
- package/src/store/scopes/thread-list-item.ts +5 -2
- package/src/store/scopes/thread.ts +20 -0
- package/src/store/scopes/threads.ts +1 -0
- package/src/store/thread-tasks.test.tsx +209 -0
- package/src/subscribable/subscribable.test.ts +156 -1
- package/src/subscribable/subscribable.ts +25 -15
- package/src/tests/MessageRepository.test.ts +117 -5
- 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 +47 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +89 -0
- package/src/tests/attachment-adapters.test.ts +14 -0
- package/src/tests/auiV0Encode.test.ts +300 -0
- package/src/tests/base-composer-runtime-core-send.test.ts +51 -0
- package/src/tests/base-composer-runtime-core.test.ts +353 -2
- package/src/tests/external-store-thread-list-runtime-core.test.ts +83 -0
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +178 -18
- package/src/tests/external-thread-attachments.test.tsx +208 -0
- package/src/tests/external-thread-parity.test.tsx +57 -0
- package/src/tests/groupParts.test.ts +71 -0
- package/src/tests/message-queue.test.ts +253 -0
- package/src/tests/remote-thread-list-isLoading.test.ts +1 -0
- package/src/tests/remote-thread-list-reactive-threadId.test.ts +51 -0
- package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
- package/src/tests/thread-switch-events.test.tsx +78 -0
- package/src/tests/tools-scope-migration.test.tsx +28 -0
- package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +43 -0
- package/src/types/attachment.ts +4 -0
- package/src/types/index.ts +1 -0
- package/src/types/message.ts +8 -0
- package/src/utils/abortable-iterable.test.ts +328 -0
- package/src/utils/abortable-iterable.ts +104 -0
- package/src/utils/composite-context-provider.test.ts +25 -0
- package/src/utils/composite-context-provider.ts +23 -2
- package/src/utils/getGroupStatus.test.ts +70 -4
- package/src/utils/getGroupStatus.ts +35 -12
- package/src/utils/record.test.ts +48 -0
- package/src/utils/record.ts +11 -0
- package/src/utils/wire-media.test.ts +10 -0
- package/src/utils/wire-media.ts +6 -2
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import type { ThreadMessage } from "../../types/message";
|
|
3
|
+
import { ExportedMessageRepository } from "./message-repository";
|
|
4
|
+
|
|
5
|
+
const nestedRunningAssistant: ThreadMessage = {
|
|
6
|
+
id: "nested-assistant",
|
|
7
|
+
createdAt: new Date(0),
|
|
8
|
+
role: "assistant",
|
|
9
|
+
content: [],
|
|
10
|
+
status: { type: "running" },
|
|
11
|
+
metadata: {
|
|
12
|
+
unstable_state: {},
|
|
13
|
+
unstable_annotations: [],
|
|
14
|
+
unstable_data: [],
|
|
15
|
+
steps: [],
|
|
16
|
+
custom: {},
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const delegating = {
|
|
21
|
+
id: "assistant-1",
|
|
22
|
+
role: "assistant" as const,
|
|
23
|
+
content: [
|
|
24
|
+
{
|
|
25
|
+
type: "tool-call" as const,
|
|
26
|
+
toolCallId: "delegate-1",
|
|
27
|
+
toolName: "delegate",
|
|
28
|
+
args: {},
|
|
29
|
+
argsText: "",
|
|
30
|
+
messages: [nestedRunningAssistant],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
describe("ExportedMessageRepository", () => {
|
|
36
|
+
it("imports a message saved mid-delegation as pending, not running", () => {
|
|
37
|
+
const fromArray = ExportedMessageRepository.fromArray([delegating]);
|
|
38
|
+
const fromBranchable = ExportedMessageRepository.fromBranchableArray([
|
|
39
|
+
{ message: delegating, parentId: null },
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
for (const repository of [fromArray, fromBranchable]) {
|
|
43
|
+
expect(repository.messages[0]?.message.status).toMatchObject({
|
|
44
|
+
type: "requires-action",
|
|
45
|
+
reason: "tool-calls",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -2,7 +2,7 @@ import type { ThreadMessage } from "../../types/message";
|
|
|
2
2
|
import type { RunConfig } from "../../types/message";
|
|
3
3
|
import { generateId } from "../../utils/id";
|
|
4
4
|
import type { ThreadMessageLike } from "./thread-message-like";
|
|
5
|
-
import {
|
|
5
|
+
import { getRepositoryContentAutoStatus } from "./auto-status";
|
|
6
6
|
import { fromThreadMessageLike } from "./thread-message-like";
|
|
7
7
|
|
|
8
8
|
export type ExportedMessageRepositoryItem = {
|
|
@@ -28,7 +28,7 @@ export const ExportedMessageRepository = {
|
|
|
28
28
|
fromThreadMessageLike(
|
|
29
29
|
m,
|
|
30
30
|
generateId(),
|
|
31
|
-
|
|
31
|
+
getRepositoryContentAutoStatus(m.content),
|
|
32
32
|
),
|
|
33
33
|
);
|
|
34
34
|
|
|
@@ -62,7 +62,7 @@ export const ExportedMessageRepository = {
|
|
|
62
62
|
message: fromThreadMessageLike(
|
|
63
63
|
message,
|
|
64
64
|
message.id,
|
|
65
|
-
|
|
65
|
+
getRepositoryContentAutoStatus(message.content),
|
|
66
66
|
),
|
|
67
67
|
};
|
|
68
68
|
}),
|
|
@@ -134,6 +134,16 @@ export class MessageRepository {
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
private selectPathTo(message: RepositoryMessage) {
|
|
138
|
+
for (
|
|
139
|
+
let current: RepositoryMessage | null = message;
|
|
140
|
+
current;
|
|
141
|
+
current = current.prev
|
|
142
|
+
) {
|
|
143
|
+
(current.prev ?? this.root).next = current;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
137
147
|
private performOp(
|
|
138
148
|
newParent: RepositoryMessage | null,
|
|
139
149
|
child: RepositoryMessage,
|
|
@@ -182,12 +192,17 @@ export class MessageRepository {
|
|
|
182
192
|
child.current.id,
|
|
183
193
|
];
|
|
184
194
|
|
|
185
|
-
|
|
195
|
+
child.prev = newParent;
|
|
196
|
+
|
|
197
|
+
if (findHead(child) === this.head) {
|
|
198
|
+
this.selectPathTo(child);
|
|
199
|
+
} else if (newParentOrRoot.next === null) {
|
|
186
200
|
newParentOrRoot.next = child;
|
|
201
|
+
if (this.head === newParentOrRoot) {
|
|
202
|
+
this.head = findHead(child);
|
|
203
|
+
}
|
|
187
204
|
}
|
|
188
205
|
|
|
189
|
-
child.prev = newParent;
|
|
190
|
-
|
|
191
206
|
const newLevel = newParent ? newParent.level + 1 : 0;
|
|
192
207
|
this.updateLevels(child, newLevel);
|
|
193
208
|
}
|
|
@@ -381,8 +396,7 @@ export class MessageRepository {
|
|
|
381
396
|
);
|
|
382
397
|
|
|
383
398
|
const previousHead = this.head;
|
|
384
|
-
|
|
385
|
-
prevOrRoot.next = message;
|
|
399
|
+
this.selectPathTo(message);
|
|
386
400
|
|
|
387
401
|
this.head = findHead(message);
|
|
388
402
|
|
|
@@ -423,17 +437,7 @@ export class MessageRepository {
|
|
|
423
437
|
}
|
|
424
438
|
|
|
425
439
|
this.head = message;
|
|
426
|
-
|
|
427
|
-
let current: RepositoryMessage | null = message;
|
|
428
|
-
current;
|
|
429
|
-
current = current.prev
|
|
430
|
-
) {
|
|
431
|
-
if (current.prev) {
|
|
432
|
-
current.prev.next = current;
|
|
433
|
-
} else {
|
|
434
|
-
this.root.next = current;
|
|
435
|
-
}
|
|
436
|
-
}
|
|
440
|
+
this.selectPathTo(message);
|
|
437
441
|
|
|
438
442
|
this.evictOffBranchOptimisticMessages(previousHead, this.head);
|
|
439
443
|
|
|
@@ -456,7 +460,15 @@ export class MessageRepository {
|
|
|
456
460
|
// Optimistic messages are ephemeral and never persisted. A persisted child
|
|
457
461
|
// of an optimistic node is re-parented onto its nearest persisted ancestor
|
|
458
462
|
// so the exported tree never references a skipped id.
|
|
459
|
-
|
|
463
|
+
// Import and external-state conversion require parents before children, so
|
|
464
|
+
// the tree is walked in pre-order rather than iterated in insertion order.
|
|
465
|
+
const pending = [...this.root.children].reverse();
|
|
466
|
+
while (pending.length > 0) {
|
|
467
|
+
const message = this.messages.get(pending.pop()!);
|
|
468
|
+
if (!message) continue;
|
|
469
|
+
for (let i = message.children.length - 1; i >= 0; i--) {
|
|
470
|
+
pending.push(message.children[i]!);
|
|
471
|
+
}
|
|
460
472
|
if (message.current.metadata?.isOptimistic) continue;
|
|
461
473
|
let prev = message.prev;
|
|
462
474
|
while (prev && prev.current.metadata?.isOptimistic) {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { fromThreadMessageLike } from "./thread-message-like";
|
|
3
|
+
|
|
4
|
+
describe("fromThreadMessageLike", () => {
|
|
5
|
+
it("preserves modality on user and assistant messages", () => {
|
|
6
|
+
const user = fromThreadMessageLike(
|
|
7
|
+
{
|
|
8
|
+
role: "user",
|
|
9
|
+
content: "Hello",
|
|
10
|
+
metadata: { modality: "voice" },
|
|
11
|
+
},
|
|
12
|
+
"user-id",
|
|
13
|
+
{ type: "complete", reason: "unknown" },
|
|
14
|
+
);
|
|
15
|
+
const assistant = fromThreadMessageLike(
|
|
16
|
+
{
|
|
17
|
+
role: "assistant",
|
|
18
|
+
content: "Hi",
|
|
19
|
+
metadata: { modality: "voice" },
|
|
20
|
+
},
|
|
21
|
+
"assistant-id",
|
|
22
|
+
{ type: "complete", reason: "unknown" },
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
expect(user.metadata.modality).toBe("voice");
|
|
26
|
+
expect(assistant.metadata.modality).toBe("voice");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("leaves modality absent when the input has none", () => {
|
|
30
|
+
const message = fromThreadMessageLike(
|
|
31
|
+
{ role: "user", content: "Hello" },
|
|
32
|
+
"user-id",
|
|
33
|
+
{ type: "complete", reason: "unknown" },
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
expect(message.metadata).not.toHaveProperty("modality");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("ignores modality on system messages", () => {
|
|
40
|
+
const message = fromThreadMessageLike(
|
|
41
|
+
{
|
|
42
|
+
role: "system",
|
|
43
|
+
content: "Instructions",
|
|
44
|
+
metadata: { modality: "voice" },
|
|
45
|
+
},
|
|
46
|
+
"system-id",
|
|
47
|
+
{ type: "complete", reason: "unknown" },
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
expect(message.metadata).not.toHaveProperty("modality");
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
} from "../../types/message";
|
|
21
21
|
import type { CompleteAttachment } from "../../types/attachment";
|
|
22
22
|
import type {
|
|
23
|
+
MessageModality,
|
|
23
24
|
MessageTiming,
|
|
24
25
|
PartProviderMetadata,
|
|
25
26
|
TextMessagePart,
|
|
@@ -88,6 +89,7 @@ export type ThreadMessageLike = {
|
|
|
88
89
|
readonly timing?: MessageTiming | undefined;
|
|
89
90
|
readonly submittedFeedback?: { readonly type: "positive" | "negative" };
|
|
90
91
|
readonly isOptimistic?: boolean | undefined;
|
|
92
|
+
readonly modality?: MessageModality | undefined;
|
|
91
93
|
readonly custom?: Record<string, unknown> | undefined;
|
|
92
94
|
}
|
|
93
95
|
| undefined;
|
|
@@ -179,7 +181,7 @@ export const fromThreadMessageLike = (
|
|
|
179
181
|
const { parentId, messages, ...basePart } = part;
|
|
180
182
|
const commonProps = {
|
|
181
183
|
...basePart,
|
|
182
|
-
toolCallId: part.toolCallId
|
|
184
|
+
toolCallId: part.toolCallId || `tool-${generateId()}`,
|
|
183
185
|
...(parentId !== undefined && { parentId }),
|
|
184
186
|
...(messages !== undefined && { messages }),
|
|
185
187
|
};
|
|
@@ -223,6 +225,7 @@ export const fromThreadMessageLike = (
|
|
|
223
225
|
submittedFeedback: metadata.submittedFeedback,
|
|
224
226
|
}),
|
|
225
227
|
...(metadata?.isOptimistic && { isOptimistic: true }),
|
|
228
|
+
...(metadata?.modality && { modality: metadata.modality }),
|
|
226
229
|
},
|
|
227
230
|
} satisfies ThreadAssistantMessage;
|
|
228
231
|
|
|
@@ -263,6 +266,7 @@ export const fromThreadMessageLike = (
|
|
|
263
266
|
metadata: {
|
|
264
267
|
custom: metadata?.custom ?? {},
|
|
265
268
|
...(metadata?.isOptimistic && { isOptimistic: true }),
|
|
269
|
+
...(metadata?.modality && { modality: metadata.modality }),
|
|
266
270
|
},
|
|
267
271
|
} satisfies ThreadUserMessage;
|
|
268
272
|
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
import type { ExternalStoreThreadListAdapter } from "./external-store-adapter";
|
|
7
7
|
import { invalidateThreadRuntime } from "../../runtime/utils/thread-runtime-lifecycle";
|
|
8
8
|
import { BaseSubscribable } from "../../subscribable/subscribable";
|
|
9
|
+
import { nullProtoRecord } from "../../utils/record";
|
|
9
10
|
|
|
10
11
|
export type ExternalStoreThreadFactory = () => ExternalStoreThreadRuntimeCore;
|
|
11
12
|
|
|
@@ -19,9 +20,11 @@ const DEFAULT_THREAD = Object.freeze({
|
|
|
19
20
|
status: "regular",
|
|
20
21
|
});
|
|
21
22
|
const RESOLVED_PROMISE = Promise.resolve();
|
|
22
|
-
const DEFAULT_THREAD_DATA = Object.freeze(
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const DEFAULT_THREAD_DATA = Object.freeze(
|
|
24
|
+
nullProtoRecord<ThreadListItemCoreState>({
|
|
25
|
+
[DEFAULT_THREAD_ID]: DEFAULT_THREAD,
|
|
26
|
+
}),
|
|
27
|
+
);
|
|
25
28
|
|
|
26
29
|
export class ExternalStoreThreadListRuntimeCore
|
|
27
30
|
extends BaseSubscribable
|
|
@@ -84,7 +87,9 @@ export class ExternalStoreThreadListRuntimeCore
|
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
public getItemById(threadId: string) {
|
|
87
|
-
return this._threadData
|
|
90
|
+
return Object.hasOwn(this._threadData, threadId)
|
|
91
|
+
? this._threadData[threadId]
|
|
92
|
+
: undefined;
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
public __internal_setAdapter(
|
|
@@ -105,6 +110,7 @@ export class ExternalStoreThreadListRuntimeCore
|
|
|
105
110
|
|
|
106
111
|
if (
|
|
107
112
|
!initialLoad &&
|
|
113
|
+
(previousAdapter.isLoading ?? false) === (adapter.isLoading ?? false) &&
|
|
108
114
|
previousThreadId === newThreadId &&
|
|
109
115
|
previousThreads === newThreads &&
|
|
110
116
|
previousArchivedThreads === newArchivedThreads
|
|
@@ -117,9 +123,9 @@ export class ExternalStoreThreadListRuntimeCore
|
|
|
117
123
|
previousArchivedThreads !== newArchivedThreads ||
|
|
118
124
|
previousThreadId !== newThreadId
|
|
119
125
|
) {
|
|
120
|
-
this._threadData =
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
this._threadData = nullProtoRecord(
|
|
127
|
+
DEFAULT_THREAD_DATA,
|
|
128
|
+
Object.fromEntries(
|
|
123
129
|
adapter.threads?.map((t) => [
|
|
124
130
|
t.id,
|
|
125
131
|
{
|
|
@@ -130,7 +136,7 @@ export class ExternalStoreThreadListRuntimeCore
|
|
|
130
136
|
},
|
|
131
137
|
]) ?? [],
|
|
132
138
|
),
|
|
133
|
-
|
|
139
|
+
Object.fromEntries(
|
|
134
140
|
adapter.archivedThreads?.map((t) => [
|
|
135
141
|
t.id,
|
|
136
142
|
{
|
|
@@ -141,7 +147,7 @@ export class ExternalStoreThreadListRuntimeCore
|
|
|
141
147
|
},
|
|
142
148
|
]) ?? [],
|
|
143
149
|
),
|
|
144
|
-
|
|
150
|
+
);
|
|
145
151
|
}
|
|
146
152
|
|
|
147
153
|
if (previousThreads !== newThreads) {
|
|
@@ -160,16 +166,15 @@ export class ExternalStoreThreadListRuntimeCore
|
|
|
160
166
|
this._mainThread = this.threadFactory();
|
|
161
167
|
}
|
|
162
168
|
|
|
163
|
-
if (!this._threadData
|
|
164
|
-
this._threadData = {
|
|
165
|
-
...this._threadData,
|
|
169
|
+
if (!Object.hasOwn(this._threadData, this._mainThreadId)) {
|
|
170
|
+
this._threadData = nullProtoRecord(this._threadData, {
|
|
166
171
|
[this._mainThreadId]: {
|
|
167
172
|
id: this._mainThreadId,
|
|
168
173
|
remoteId: undefined,
|
|
169
174
|
externalId: undefined,
|
|
170
175
|
status: "regular",
|
|
171
176
|
},
|
|
172
|
-
};
|
|
177
|
+
});
|
|
173
178
|
}
|
|
174
179
|
|
|
175
180
|
this._notifySubscribers();
|
|
@@ -637,6 +637,8 @@ export class ExternalStoreThreadRuntimeCore
|
|
|
637
637
|
}
|
|
638
638
|
|
|
639
639
|
public async append(rawMessage: AppendMessage): Promise<void> {
|
|
640
|
+
if (this._isVoiceMessage(rawMessage.sourceId))
|
|
641
|
+
throw new Error("Voice transcript messages cannot be edited");
|
|
640
642
|
// sourceId marks an edit send; the parent may coincide with the head
|
|
641
643
|
// after a resync (e.g. cancelRun dropped the edited message).
|
|
642
644
|
const isEdit =
|
|
@@ -786,6 +788,8 @@ export class ExternalStoreThreadRuntimeCore
|
|
|
786
788
|
public async startRun(config: StartRunConfig): Promise<void> {
|
|
787
789
|
if (!this._store.onReload)
|
|
788
790
|
throw new Error("Runtime does not support reloading messages.");
|
|
791
|
+
if (this._isVoiceMessage(config.sourceId))
|
|
792
|
+
throw new Error("Voice transcript messages cannot be reloaded");
|
|
789
793
|
|
|
790
794
|
this._pendingDeleteEvictions.clear();
|
|
791
795
|
|
|
@@ -800,6 +804,8 @@ export class ExternalStoreThreadRuntimeCore
|
|
|
800
804
|
public async resumeRun(config: ResumeRunConfig): Promise<void> {
|
|
801
805
|
if (!this._store.onResume)
|
|
802
806
|
throw new Error("Runtime does not support resuming runs.");
|
|
807
|
+
if (this._isVoiceMessage(config.sourceId))
|
|
808
|
+
throw new Error("Voice transcript messages cannot be reloaded");
|
|
803
809
|
|
|
804
810
|
await this._store.onResume(config);
|
|
805
811
|
}
|
|
@@ -961,8 +967,32 @@ export class ExternalStoreThreadRuntimeCore
|
|
|
961
967
|
): Promise<void> {
|
|
962
968
|
if (!this._store.onRespondToToolApproval)
|
|
963
969
|
throw new Error("Runtime does not support tool approvals.");
|
|
970
|
+
const message = this.messages.findLast(
|
|
971
|
+
(candidate) =>
|
|
972
|
+
candidate.role === "assistant" &&
|
|
973
|
+
candidate.content.some(
|
|
974
|
+
(part) =>
|
|
975
|
+
part.type === "tool-call" &&
|
|
976
|
+
part.approval?.id === options.approvalId,
|
|
977
|
+
),
|
|
978
|
+
);
|
|
979
|
+
const toolCall = message?.content.find(
|
|
980
|
+
(part) =>
|
|
981
|
+
part.type === "tool-call" && part.approval?.id === options.approvalId,
|
|
982
|
+
);
|
|
964
983
|
try {
|
|
965
|
-
return Promise.resolve(this._store.onRespondToToolApproval(options))
|
|
984
|
+
return Promise.resolve(this._store.onRespondToToolApproval(options)).then(
|
|
985
|
+
() => {
|
|
986
|
+
if (message && toolCall?.type === "tool-call") {
|
|
987
|
+
this._notifyToolApprovalAnswered(
|
|
988
|
+
message.id,
|
|
989
|
+
toolCall.toolCallId,
|
|
990
|
+
toolCall.toolName,
|
|
991
|
+
options.approved,
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
},
|
|
995
|
+
);
|
|
966
996
|
} catch (error) {
|
|
967
997
|
return Promise.reject(error);
|
|
968
998
|
}
|
package/src/runtimes/internal.ts
CHANGED
|
@@ -427,6 +427,27 @@ describe("LocalThreadRuntimeCore state", () => {
|
|
|
427
427
|
});
|
|
428
428
|
|
|
429
429
|
describe("LocalThreadRuntimeCore tool approvals", () => {
|
|
430
|
+
it("emits a decision with its message and tool call IDs", async () => {
|
|
431
|
+
const { thread } = createApprovalThread(
|
|
432
|
+
toolCallResult("send_email", { id: "a1" }),
|
|
433
|
+
);
|
|
434
|
+
const answered = vi.fn();
|
|
435
|
+
thread.unstable_on("toolApprovalAnswered", answered);
|
|
436
|
+
|
|
437
|
+
await thread.append(userMessage("send an email"));
|
|
438
|
+
await flush();
|
|
439
|
+
const messageId = thread.messages.at(-1)?.id;
|
|
440
|
+
|
|
441
|
+
await thread.respondToToolApproval({ approvalId: "a1", approved: false });
|
|
442
|
+
|
|
443
|
+
expect(answered).toHaveBeenCalledWith({
|
|
444
|
+
messageId,
|
|
445
|
+
toolCallId: "call-send_email",
|
|
446
|
+
toolName: "send_email",
|
|
447
|
+
approved: false,
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
|
|
430
451
|
it("pauses the run while an approval is pending, even for unlisted tools", async () => {
|
|
431
452
|
const { thread, runs } = createApprovalThread(
|
|
432
453
|
toolCallResult("deploy", { id: "a1" }),
|
|
@@ -342,6 +342,8 @@ export class LocalThreadRuntimeCore
|
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
public async append(message: AppendMessage): Promise<void> {
|
|
345
|
+
if (this._isVoiceMessage(message.sourceId))
|
|
346
|
+
throw new Error("Voice transcript messages cannot be edited");
|
|
345
347
|
const isTail = message.parentId === (this.messages.at(-1)?.id ?? null);
|
|
346
348
|
const willRun = message.startRun ?? message.role === "user";
|
|
347
349
|
if (this._queue && willRun && isTail) {
|
|
@@ -488,10 +490,12 @@ export class LocalThreadRuntimeCore
|
|
|
488
490
|
}
|
|
489
491
|
|
|
490
492
|
public async startRun(
|
|
491
|
-
{ parentId, runConfig }: StartRunConfig,
|
|
493
|
+
{ parentId, sourceId, runConfig }: StartRunConfig,
|
|
492
494
|
runCallback?: ChatModelAdapter["run"],
|
|
493
495
|
): Promise<void> {
|
|
494
496
|
this.ensureInitialized();
|
|
497
|
+
if (this._isVoiceMessage(sourceId))
|
|
498
|
+
throw new Error("Voice transcript messages cannot be reloaded");
|
|
495
499
|
|
|
496
500
|
// add assistant message
|
|
497
501
|
const id = generateId();
|
|
@@ -961,6 +965,12 @@ export class LocalThreadRuntimeCore
|
|
|
961
965
|
const { parentId } = this.repository.getMessage(message.id);
|
|
962
966
|
this.repository.addOrUpdateMessage(parentId, message);
|
|
963
967
|
this._notifySubscribers();
|
|
968
|
+
this._notifyToolApprovalAnswered(
|
|
969
|
+
message.id,
|
|
970
|
+
target.toolCallId,
|
|
971
|
+
target.toolName,
|
|
972
|
+
approved,
|
|
973
|
+
);
|
|
964
974
|
|
|
965
975
|
if (
|
|
966
976
|
this.repository.headId === message.id &&
|
|
@@ -3,6 +3,9 @@ import {
|
|
|
3
3
|
classifyThreads,
|
|
4
4
|
createEmptyRemoteThreadState,
|
|
5
5
|
createThreadMappingId,
|
|
6
|
+
getThreadData,
|
|
7
|
+
promoteNewThreadReducer,
|
|
8
|
+
reconcileInitializedThread,
|
|
6
9
|
seedNewThread,
|
|
7
10
|
updateStatusReducer,
|
|
8
11
|
} from "./remote-thread-state";
|
|
@@ -13,12 +16,16 @@ import type {
|
|
|
13
16
|
|
|
14
17
|
const initializedDraft = () => {
|
|
15
18
|
const seeded = seedNewThread(createEmptyRemoteThreadState());
|
|
16
|
-
const regular = updateStatusReducer(seeded.state, seeded.id, "regular");
|
|
17
|
-
const mappingId = regular.threadIdMap[seeded.id]!;
|
|
18
19
|
const initializeTask = Promise.resolve({
|
|
19
20
|
remoteId: "remote-1",
|
|
20
21
|
externalId: "remote-1",
|
|
21
22
|
});
|
|
23
|
+
const regular = promoteNewThreadReducer(
|
|
24
|
+
seeded.state,
|
|
25
|
+
seeded.id,
|
|
26
|
+
initializeTask,
|
|
27
|
+
);
|
|
28
|
+
const mappingId = regular.threadIdMap[seeded.id]!;
|
|
22
29
|
return {
|
|
23
30
|
id: seeded.id,
|
|
24
31
|
mappingId,
|
|
@@ -54,6 +61,7 @@ describe("remote thread state", () => {
|
|
|
54
61
|
it("creates an empty state", () => {
|
|
55
62
|
expect(createEmptyRemoteThreadState()).toEqual({
|
|
56
63
|
isLoading: true,
|
|
64
|
+
loadError: undefined,
|
|
57
65
|
isLoadingMore: false,
|
|
58
66
|
cursor: undefined,
|
|
59
67
|
newThreadId: undefined,
|
|
@@ -80,6 +88,39 @@ describe("remote thread state", () => {
|
|
|
80
88
|
expect(Object.keys(second.state.threadData)).toEqual([first.id, second.id]);
|
|
81
89
|
});
|
|
82
90
|
|
|
91
|
+
it("carries the initialization task onto the promoted slot", () => {
|
|
92
|
+
const seeded = seedNewThread(createEmptyRemoteThreadState());
|
|
93
|
+
const initializeTask = Promise.resolve({
|
|
94
|
+
remoteId: "remote-1",
|
|
95
|
+
externalId: "external-1",
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const promoted = promoteNewThreadReducer(
|
|
99
|
+
seeded.state,
|
|
100
|
+
seeded.id,
|
|
101
|
+
initializeTask,
|
|
102
|
+
);
|
|
103
|
+
const data = getThreadData(promoted, seeded.id);
|
|
104
|
+
|
|
105
|
+
expect(data?.status).toBe("regular");
|
|
106
|
+
expect(data?.status === "new" ? undefined : data?.initializeTask).toBe(
|
|
107
|
+
initializeTask,
|
|
108
|
+
);
|
|
109
|
+
expect(promoted.newThreadId).toBeUndefined();
|
|
110
|
+
expect(promoted.threadIds).toEqual([seeded.id]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it.each(["regular", "archived"] as const)(
|
|
114
|
+
"leaves a new thread untouched when moved to %s without an initialization task",
|
|
115
|
+
(newStatus) => {
|
|
116
|
+
const seeded = seedNewThread(createEmptyRemoteThreadState());
|
|
117
|
+
|
|
118
|
+
expect(updateStatusReducer(seeded.state, seeded.id, newStatus)).toBe(
|
|
119
|
+
seeded.state,
|
|
120
|
+
);
|
|
121
|
+
},
|
|
122
|
+
);
|
|
123
|
+
|
|
83
124
|
it("refreshes the local slot when a listed thread already has a mapping", () => {
|
|
84
125
|
const draft = initializedDraft();
|
|
85
126
|
|
|
@@ -131,6 +172,91 @@ describe("remote thread state", () => {
|
|
|
131
172
|
expect(listed.threadData[createThreadMappingId("a")]?.title).toBe("second");
|
|
132
173
|
});
|
|
133
174
|
|
|
175
|
+
it("retains a listed external id when that slot survives reconciliation", async () => {
|
|
176
|
+
const seeded = seedNewThread(createEmptyRemoteThreadState());
|
|
177
|
+
const regular = promoteNewThreadReducer(
|
|
178
|
+
seeded.state,
|
|
179
|
+
seeded.id,
|
|
180
|
+
Promise.resolve({ remoteId: "remote-1", externalId: "external-1" }),
|
|
181
|
+
);
|
|
182
|
+
const classified = classifyThreads(
|
|
183
|
+
[
|
|
184
|
+
{
|
|
185
|
+
status: "regular",
|
|
186
|
+
remoteId: "remote-1",
|
|
187
|
+
externalId: "external-1",
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
{
|
|
191
|
+
threadIds: [...regular.threadIds],
|
|
192
|
+
archivedThreadIds: [...regular.archivedThreadIds],
|
|
193
|
+
threadIdMap: { ...regular.threadIdMap },
|
|
194
|
+
threadData: { ...regular.threadData },
|
|
195
|
+
},
|
|
196
|
+
);
|
|
197
|
+
const state = { ...regular, ...classified };
|
|
198
|
+
|
|
199
|
+
const reconciled = reconcileInitializedThread(
|
|
200
|
+
state,
|
|
201
|
+
seeded.id,
|
|
202
|
+
"remote-1",
|
|
203
|
+
undefined,
|
|
204
|
+
"remote-1",
|
|
205
|
+
);
|
|
206
|
+
const survivor = reconciled.state.threadData[reconciled.survivorMappingId]!;
|
|
207
|
+
|
|
208
|
+
expect(survivor.externalId).toBe("external-1");
|
|
209
|
+
if (survivor.status === "new") throw new Error("Expected initialized slot");
|
|
210
|
+
await expect(survivor.initializeTask).resolves.toEqual({
|
|
211
|
+
remoteId: "remote-1",
|
|
212
|
+
externalId: "external-1",
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it.each(["__proto__", "constructor", "toString"])(
|
|
217
|
+
"handles a prototype-named remote id %s",
|
|
218
|
+
(remoteId) => {
|
|
219
|
+
const classified = classifyThreads(
|
|
220
|
+
[
|
|
221
|
+
{
|
|
222
|
+
status: "regular",
|
|
223
|
+
remoteId,
|
|
224
|
+
externalId: undefined,
|
|
225
|
+
title: `title-${remoteId}`,
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
status: "regular",
|
|
229
|
+
remoteId: "ok",
|
|
230
|
+
externalId: undefined,
|
|
231
|
+
title: "title-ok",
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
{
|
|
235
|
+
threadIds: [],
|
|
236
|
+
archivedThreadIds: [],
|
|
237
|
+
threadIdMap: {},
|
|
238
|
+
threadData: {},
|
|
239
|
+
},
|
|
240
|
+
);
|
|
241
|
+
const listed: RemoteThreadState = {
|
|
242
|
+
...createEmptyRemoteThreadState(),
|
|
243
|
+
threadIds: classified.threadIds,
|
|
244
|
+
archivedThreadIds: classified.archivedThreadIds,
|
|
245
|
+
threadIdMap: classified.threadIdMap,
|
|
246
|
+
threadData: classified.threadData,
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
expect(Object.keys(listed.threadIdMap)).toEqual([remoteId, "ok"]);
|
|
250
|
+
expect(typeof listed.threadIdMap[remoteId]).toBe("string");
|
|
251
|
+
expect(Object.keys(listed.threadData)).toEqual([remoteId, "ok"]);
|
|
252
|
+
|
|
253
|
+
const deleted = updateStatusReducer(listed, remoteId, "deleted");
|
|
254
|
+
expect(Object.keys(deleted.threadIdMap)).toEqual(["ok"]);
|
|
255
|
+
expect(Object.keys(deleted.threadData)).toEqual(["ok"]);
|
|
256
|
+
expect(deleted.threadIds).toEqual(["ok"]);
|
|
257
|
+
},
|
|
258
|
+
);
|
|
259
|
+
|
|
134
260
|
it("deletes every alias of an identity, by either id", () => {
|
|
135
261
|
for (const target of ["remote-1", "local"] as const) {
|
|
136
262
|
const draft = initializedDraft();
|