@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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MessageTiming, ThreadMessage } from "../../types/message.js";
|
|
2
2
|
import { ThreadMessageLike } from "./thread-message-like.js";
|
|
3
3
|
import { ToolExecutionStatus } from "../../runtimes/tool-invocations/ToolInvocationTracker.js";
|
|
4
|
+
import { ThreadMessageConverter } from "../../runtimes/external-store/thread-message-converter.js";
|
|
4
5
|
import { ReadonlyJSONValue } from "assistant-stream/utils";
|
|
5
6
|
//#region src/runtime/utils/external-message-conversion.d.ts
|
|
6
7
|
type JoinStrategy = "concat-content" | "none";
|
|
@@ -36,13 +37,24 @@ declare const convertExternalMessageCallback: <T>(input: T, callback: ExternalMe
|
|
|
36
37
|
declare const joinExternalMessages: (messages: readonly ExternalMessageConverterMessage[]) => ThreadMessageLike;
|
|
37
38
|
declare const chunkExternalMessages: <T>(callbackResults: ExternalMessageConverterCallbackResult<T>[], joinStrategy?: JoinStrategy) => ExternalMessageConverterChunk<T>[];
|
|
38
39
|
declare const shallowArrayEqual: (a: readonly unknown[], b: readonly unknown[]) => boolean;
|
|
39
|
-
type
|
|
40
|
+
type ExternalMessageChunkConversionCache = {
|
|
40
41
|
message: ThreadMessage | undefined;
|
|
41
42
|
generatedFallbackMessages: WeakSet<object>;
|
|
42
43
|
};
|
|
43
|
-
|
|
44
|
+
type ExternalMessageConversionCallbackCacheEntry<T> = ExternalMessageConverterCallbackResult<T> & {
|
|
45
|
+
metadata: ExternalMessageConverterMetadata;
|
|
46
|
+
callback: ExternalMessageConverterCallback<T>;
|
|
47
|
+
};
|
|
48
|
+
type InternalExternalMessageConversionCache<T extends WeakKey = WeakKey> = {
|
|
49
|
+
callbackCache: WeakMap<T, ExternalMessageConversionCallbackCacheEntry<T>>;
|
|
50
|
+
chunkCache: WeakMap<ExternalMessageConverterMessage, ExternalMessageConverterChunk<T>>;
|
|
51
|
+
converterCache: ThreadMessageConverter;
|
|
52
|
+
generatedFallbackMessages: WeakSet<object>;
|
|
53
|
+
};
|
|
54
|
+
declare const createExternalMessageConversionCache: <T extends WeakKey = WeakKey>() => InternalExternalMessageConversionCache<T>;
|
|
55
|
+
declare const convertExternalMessageChunk: <T>(message: ExternalMessageConverterChunk<T>, idx: number, chunkCount: number, isRunning: boolean, error: ReadonlyJSONValue | undefined, cache?: ExternalMessageChunkConversionCache, cancelledMessageIds?: ReadonlySet<string>) => ThreadMessage;
|
|
44
56
|
declare const completeExternalMessageConversion: (messages: ThreadMessage[], error: ReadonlyJSONValue | undefined) => ThreadMessage[];
|
|
45
|
-
declare const convertExternalMessages: <T extends WeakKey>(messages: T[], callback: ExternalMessageConverterCallback<T>, isRunning: boolean, metadata: ExternalMessageConverterMetadata) => ThreadMessage[];
|
|
57
|
+
declare const convertExternalMessages: <T extends WeakKey>(messages: T[], callback: ExternalMessageConverterCallback<T>, isRunning: boolean, metadata: ExternalMessageConverterMetadata, joinStrategy?: JoinStrategy, cache?: InternalExternalMessageConversionCache<T>) => ThreadMessage[];
|
|
46
58
|
//#endregion
|
|
47
|
-
export { ExternalMessageConverterCallback, ExternalMessageConverterCallbackResult, ExternalMessageConverterChunk, ExternalMessageConverterMessage, ExternalMessageConverterMetadata, JoinStrategy, chunkExternalMessages, completeExternalMessageConversion, convertExternalMessageCallback, convertExternalMessageChunk, convertExternalMessages, joinExternalMessages, shallowArrayEqual };
|
|
59
|
+
export { ExternalMessageConverterCallback, ExternalMessageConverterCallbackResult, ExternalMessageConverterChunk, ExternalMessageConverterMessage, ExternalMessageConverterMetadata, InternalExternalMessageConversionCache, JoinStrategy, chunkExternalMessages, completeExternalMessageConversion, convertExternalMessageCallback, convertExternalMessageChunk, convertExternalMessages, createExternalMessageConversionCache, joinExternalMessages, shallowArrayEqual };
|
|
48
60
|
//# sourceMappingURL=external-message-conversion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-message-conversion.d.ts","names":[],"sources":["../../../src/runtime/utils/external-message-conversion.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"external-message-conversion.d.ts","names":[],"sources":["../../../src/runtime/utils/external-message-conversion.ts"],"mappings":";;;;;;KA6BY;KAEA,mCACP;WACU;aACE,eAAe;;;EAI1B;EACA;EACA;EACA;EACA;EACA;EACA,oBAAoB;;KAGd;WACD,eAAe,eAAe;WAC9B,QAAQ;WACR,sBAAsB;WACtB,gBAAgB,eAAe;;KAG9B,iCAAiC,MAC3C,SAAS,GACT,UAAU,qCACP,kCAAkC;KAE3B,uCAAuC;EACjD,OAAO;EACP,SAAS;;KAGC,8BAA8B;EACxC,QAAQ;EACR,SAAS;;cAsDE,iCAAkC,GAC7C,OAAO,GACP,UAAU,iCAAiC,IAC3C,UAAU,qCACT,uCAAuC;cAe7B,uBACX,mBAAmB,sCAClB;cAwLU,wBAAyB,GACpC,iBAAiB,uCAAuC,MACxD,eAAe,iBAAY,8BAAA;cAmDhB,oBACX,uBACA;KASG;EACH,SAAS;EACT,2BAA2B;;KAGxB,4CAA4C,KAC/C,uCAAuC;EACrC,UAAU;EACV,UAAU,iCAAiC;;KAGnC,uCACV,UAAU,UAAU;EAEpB,eAAe,QAAQ,GAAG,4CAA4C;EACtE,YAAY,QACV,iCACA,8BAA8B;EAEhC,gBAAgB;EAEhB,2BAA2B;;cAGhB,uCACX,UAAU,UAAU,cACjB,uCAAuC;cAO/B,8BAA+B,GAC1C,SAAS,8BAA8B,IACvC,aACA,oBACA,oBACA,OAAO,+BACP,QAAQ,qCACR,sBAAsB,wBAAmB;cA8F9B,oCACX,UAAU,iBACV,OAAO,kCAA6B;cAWzB,0BAA2B,UAAU,SAChD,UAAU,KACV,UAAU,iCAAiC,IAC3C,oBACA,UAAU,kCACV,eAAe,cACf,QAAQ,uCAAuC,OAAE"}
|
|
@@ -2,7 +2,8 @@ import { isJSONValueEqual } from "../../utils/json/is-json-equal.js";
|
|
|
2
2
|
import { generateErrorMessageId } from "../../utils/id.js";
|
|
3
3
|
import { fromThreadMessageLike } from "./thread-message-like.js";
|
|
4
4
|
import { FALLBACK_ID_PREFIX, bindExternalStoreMessage, getExternalStoreMessages, symbolInnerMessage } from "./external-store-message.js";
|
|
5
|
-
import { getAutoStatus, isAutoStatus, isInterruptedToolCall, isPendingToolCall } from "./auto-status.js";
|
|
5
|
+
import { getAutoStatus, isAutoStatus, isBackgroundToolCall, isInterruptedToolCall, isPendingToolCall } from "./auto-status.js";
|
|
6
|
+
import { ThreadMessageConverter } from "../../runtimes/external-store/thread-message-converter.js";
|
|
6
7
|
//#region src/runtime/utils/external-message-conversion.ts
|
|
7
8
|
const stringifyForError = (value) => {
|
|
8
9
|
let text;
|
|
@@ -31,13 +32,16 @@ const convertExternalMessageCallback = (input, callback, metadata) => ({
|
|
|
31
32
|
outputs: toCallbackOutputs(callback(input, metadata), input)
|
|
32
33
|
});
|
|
33
34
|
const mergeInnerMessages = (existing, incoming) => ({ [symbolInnerMessage]: [...existing[symbolInnerMessage] ?? [], ...incoming[symbolInnerMessage] ?? []] });
|
|
35
|
+
const isNaNToolCallId = (toolCallId) => typeof toolCallId === "number" && Number.isNaN(toolCallId);
|
|
34
36
|
const joinExternalMessages = (messages) => {
|
|
35
37
|
const assistantMessage = {
|
|
36
38
|
role: "assistant",
|
|
37
39
|
content: []
|
|
38
40
|
};
|
|
41
|
+
const toolCallIndices = /* @__PURE__ */ new Map();
|
|
42
|
+
const reasoningIndices = /* @__PURE__ */ new Map();
|
|
39
43
|
for (const output of messages) if (output.role === "tool") {
|
|
40
|
-
const toolCallIdx =
|
|
44
|
+
const toolCallIdx = !isNaNToolCallId(output.toolCallId) ? toolCallIndices.get(output.toolCallId) ?? -1 : -1;
|
|
41
45
|
if (toolCallIdx !== -1) {
|
|
42
46
|
const toolCall = assistantMessage.content[toolCallIdx];
|
|
43
47
|
if (output.toolName != null) {
|
|
@@ -85,13 +89,14 @@ const joinExternalMessages = (messages) => {
|
|
|
85
89
|
...output.metadata.custom
|
|
86
90
|
};
|
|
87
91
|
if (output.metadata.timing) assistantMessage.metadata.timing = output.metadata.timing;
|
|
92
|
+
if (output.metadata.modality) assistantMessage.metadata.modality = output.metadata.modality;
|
|
88
93
|
if (output.metadata.submittedFeedback) assistantMessage.metadata.submittedFeedback = output.metadata.submittedFeedback;
|
|
89
94
|
if (output.metadata.isOptimistic) assistantMessage.metadata.isOptimistic = true;
|
|
90
95
|
}
|
|
91
96
|
for (const part of content) {
|
|
92
|
-
if (part.type === "tool-call") {
|
|
93
|
-
const existingIdx =
|
|
94
|
-
if (existingIdx !==
|
|
97
|
+
if (part.type === "tool-call" && part.toolCallId) {
|
|
98
|
+
const existingIdx = toolCallIndices.get(part.toolCallId);
|
|
99
|
+
if (existingIdx !== void 0) {
|
|
95
100
|
const existing = assistantMessage.content[existingIdx];
|
|
96
101
|
assistantMessage.content[existingIdx] = {
|
|
97
102
|
...existing,
|
|
@@ -102,8 +107,8 @@ const joinExternalMessages = (messages) => {
|
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
109
|
if (part.type === "reasoning" && "parentId" in part && part.parentId) {
|
|
105
|
-
const existingIdx =
|
|
106
|
-
if (existingIdx !==
|
|
110
|
+
const existingIdx = reasoningIndices.get(part.parentId);
|
|
111
|
+
if (existingIdx !== void 0) {
|
|
107
112
|
const existing = assistantMessage.content[existingIdx];
|
|
108
113
|
assistantMessage.content[existingIdx] = {
|
|
109
114
|
...existing,
|
|
@@ -113,7 +118,10 @@ const joinExternalMessages = (messages) => {
|
|
|
113
118
|
continue;
|
|
114
119
|
}
|
|
115
120
|
}
|
|
121
|
+
const partIdx = assistantMessage.content.length;
|
|
116
122
|
assistantMessage.content.push(part);
|
|
123
|
+
if (part.type === "tool-call" && !isNaNToolCallId(part.toolCallId) && !toolCallIndices.has(part.toolCallId)) toolCallIndices.set(part.toolCallId, partIdx);
|
|
124
|
+
else if (part.type === "reasoning" && "parentId" in part && part.parentId) reasoningIndices.set(part.parentId, partIdx);
|
|
117
125
|
}
|
|
118
126
|
break;
|
|
119
127
|
default: throw new Error(`Unknown message role: ${role}`);
|
|
@@ -152,13 +160,20 @@ const shallowArrayEqual = (a, b) => {
|
|
|
152
160
|
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
153
161
|
return true;
|
|
154
162
|
};
|
|
163
|
+
const createExternalMessageConversionCache = () => ({
|
|
164
|
+
callbackCache: /* @__PURE__ */ new WeakMap(),
|
|
165
|
+
chunkCache: /* @__PURE__ */ new WeakMap(),
|
|
166
|
+
converterCache: new ThreadMessageConverter(),
|
|
167
|
+
generatedFallbackMessages: /* @__PURE__ */ new WeakSet()
|
|
168
|
+
});
|
|
155
169
|
const convertExternalMessageChunk = (message, idx, chunkCount, isRunning, error, cache, cancelledMessageIds) => {
|
|
156
170
|
const isLast = idx === chunkCount - 1;
|
|
157
171
|
const joined = joinExternalMessages(message.outputs);
|
|
158
172
|
const isCancelled = cancelledMessageIds !== void 0 && message.outputs.some((output) => output.role !== "tool" && output.id != null && cancelledMessageIds.has(output.id));
|
|
159
173
|
const hasInterruptedToolCalls = typeof joined.content === "object" && joined.content.some(isInterruptedToolCall);
|
|
160
174
|
const hasPendingToolCalls = typeof joined.content === "object" && joined.content.some(isPendingToolCall);
|
|
161
|
-
const
|
|
175
|
+
const hasBackgroundToolCalls = typeof joined.content === "object" && joined.content.some(isBackgroundToolCall);
|
|
176
|
+
const autoStatus = getAutoStatus(isLast, isRunning, hasInterruptedToolCalls, hasPendingToolCalls, isLast ? error : void 0, isCancelled, hasBackgroundToolCalls);
|
|
162
177
|
const fallbackId = `${FALLBACK_ID_PREFIX}${idx}`;
|
|
163
178
|
const cachedMessage = cache?.message;
|
|
164
179
|
if (cachedMessage && (cachedMessage.role !== "assistant" || !isAutoStatus(cachedMessage.status) || cachedMessage.status === autoStatus || cachedMessage.status.type === "incomplete" && cachedMessage.status.reason === "error" && cachedMessage.status.error !== void 0 && autoStatus.type === "incomplete" && autoStatus.reason === "error" && autoStatus.error !== void 0 && (cachedMessage.status.error === autoStatus.error || isJSONValueEqual(cachedMessage.status.error, autoStatus.error)))) {
|
|
@@ -210,13 +225,34 @@ const completeExternalMessageConversion = (messages, error) => {
|
|
|
210
225
|
}
|
|
211
226
|
return messages;
|
|
212
227
|
};
|
|
213
|
-
const convertExternalMessages = (messages, callback, isRunning, metadata) => {
|
|
214
|
-
const callbackResults = messages.map((message) =>
|
|
215
|
-
|
|
216
|
-
|
|
228
|
+
const convertExternalMessages = (messages, callback, isRunning, metadata, joinStrategy, cache) => {
|
|
229
|
+
const callbackResults = messages.map((message) => {
|
|
230
|
+
let result = cache?.callbackCache.get(message);
|
|
231
|
+
if (!result || result.metadata !== metadata || result.callback !== callback) {
|
|
232
|
+
result = {
|
|
233
|
+
...convertExternalMessageCallback(message, callback, metadata),
|
|
234
|
+
metadata,
|
|
235
|
+
callback
|
|
236
|
+
};
|
|
237
|
+
cache?.callbackCache.set(message, result);
|
|
238
|
+
}
|
|
239
|
+
return result;
|
|
240
|
+
});
|
|
241
|
+
const chunks = chunkExternalMessages(callbackResults, joinStrategy).map((message) => {
|
|
242
|
+
const key = message.outputs[0];
|
|
243
|
+
if (!key || !cache) return message;
|
|
244
|
+
const cached = cache.chunkCache.get(key);
|
|
245
|
+
if (cached && shallowArrayEqual(cached.outputs, message.outputs)) return cached;
|
|
246
|
+
cache.chunkCache.set(key, message);
|
|
247
|
+
return message;
|
|
248
|
+
});
|
|
249
|
+
const result = cache ? cache.converterCache.convertMessages(chunks, (cached, message, idx) => convertExternalMessageChunk(message, idx, chunks.length, isRunning, metadata.error, {
|
|
250
|
+
message: cached,
|
|
251
|
+
generatedFallbackMessages: cache.generatedFallbackMessages
|
|
252
|
+
}, metadata.cancelledMessageIds)) : chunks.map((message, idx) => convertExternalMessageChunk(message, idx, chunks.length, isRunning, metadata.error, void 0, metadata.cancelledMessageIds));
|
|
217
253
|
return completeExternalMessageConversion(result, metadata.error);
|
|
218
254
|
};
|
|
219
255
|
//#endregion
|
|
220
|
-
export { chunkExternalMessages, completeExternalMessageConversion, convertExternalMessageCallback, convertExternalMessageChunk, convertExternalMessages, joinExternalMessages, shallowArrayEqual };
|
|
256
|
+
export { chunkExternalMessages, completeExternalMessageConversion, convertExternalMessageCallback, convertExternalMessageChunk, convertExternalMessages, createExternalMessageConversionCache, joinExternalMessages, shallowArrayEqual };
|
|
221
257
|
|
|
222
258
|
//# sourceMappingURL=external-message-conversion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-message-conversion.js","names":["ReadonlyJSONValue","ToolExecutionStatus","ThreadAssistantMessage","ThreadMessage","ToolCallMessagePart","MessageTiming","generateErrorMessageId","isJSONValueEqual","getAutoStatus","isAutoStatus","isInterruptedToolCall","isPendingToolCall","bindExternalStoreMessage","FALLBACK_ID_PREFIX","getExternalStoreMessages","symbolInnerMessage","fromThreadMessageLike","ThreadMessageLike","JoinStrategy","ExternalMessageConverterMessage","convertConfig","joinStrategy","role","toolCallId","toolName","result","artifact","isError","messages","ExternalMessageConverterMetadata","toolStatuses","Record","error","cancelledMessageIds","ReadonlySet","messageTiming","ExternalMessageConverterCallback","message","T","metadata","ExternalMessageConverterCallbackResult","input","outputs","ExternalMessageConverterChunk","inputs","Mutable","P","stringifyForError","value","text","Error","String","JSON","stringify","length","slice","toCallbackOutputs","output","Array","isArray","o","valid","content","filter","warnedDroppedToolResults","has","add","console","warn","WeakSet","convertExternalMessageCallback","callback","mergeInnerMessages","existing","incoming","joinExternalMessages","assistantMessage","Omit","Exclude","toolCallIdx","findIndex","c","type","toolCall","const","map","id","createdAt","status","attachments","unstable_state","undefined","unstable_annotations","unstable_data","steps","custom","timing","submittedFeedback","isOptimistic","part","existingIdx","parentId","push","unsupportedRole","chunkExternalMessages","callbackResults","results","isAssistant","pendingNone","flush","callbackResult","at","shallowArrayEqual","a","b","i","ExternalMessageConversionCache","generatedFallbackMessages","convertExternalMessageChunk","idx","chunkCount","isRunning","cache","isLast","joined","isCancelled","some","hasInterruptedToolCalls","hasPendingToolCalls","autoStatus","fallbackId","cachedMessage","reason","updated","newMessage","createErrorAssistantMessage","msg","Date","completeExternalMessageConversion","lastMessage","convertExternalMessages","WeakKey","chunks"],"sources":["../../../src/runtime/utils/external-message-conversion.ts"],"sourcesContent":["import type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport type { ToolExecutionStatus } from \"../../runtimes/tool-invocations/ToolInvocationTracker\";\nimport type {\n ThreadAssistantMessage,\n ThreadMessage,\n ToolCallMessagePart,\n} from \"../../types/message\";\nimport type { MessageTiming } from \"../../types/message\";\nimport { generateErrorMessageId } from \"../../utils/id\";\nimport { isJSONValueEqual } from \"../../utils/json/is-json-equal\";\nimport {\n getAutoStatus,\n isAutoStatus,\n isInterruptedToolCall,\n isPendingToolCall,\n} from \"./auto-status\";\nimport {\n bindExternalStoreMessage,\n FALLBACK_ID_PREFIX,\n getExternalStoreMessages,\n symbolInnerMessage,\n} from \"./external-store-message\";\nimport {\n fromThreadMessageLike,\n type ThreadMessageLike,\n} from \"./thread-message-like\";\n\nexport type JoinStrategy = \"concat-content\" | \"none\";\n\nexport type ExternalMessageConverterMessage =\n | (ThreadMessageLike & {\n readonly convertConfig?: {\n readonly joinStrategy?: JoinStrategy;\n };\n })\n | {\n role: \"tool\";\n toolCallId: string;\n toolName?: string | undefined;\n result: any;\n artifact?: any;\n isError?: boolean;\n messages?: readonly ThreadMessage[];\n };\n\nexport type ExternalMessageConverterMetadata = {\n readonly toolStatuses?: Record<string, ToolExecutionStatus>;\n readonly error?: ReadonlyJSONValue;\n readonly cancelledMessageIds?: ReadonlySet<string>;\n readonly messageTiming?: Record<string, MessageTiming>;\n};\n\nexport type ExternalMessageConverterCallback<T> = (\n message: T,\n metadata: ExternalMessageConverterMetadata,\n) => ExternalMessageConverterMessage | ExternalMessageConverterMessage[];\n\nexport type ExternalMessageConverterCallbackResult<T> = {\n input: T;\n outputs: ExternalMessageConverterMessage[];\n};\n\nexport type ExternalMessageConverterChunk<T> = {\n inputs: T[];\n outputs: ExternalMessageConverterMessage[];\n};\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: T[P];\n};\n\nconst stringifyForError = (value: unknown) => {\n let text;\n try {\n text = value instanceof Error ? String(value) : JSON.stringify(value);\n } catch {\n /* circular */\n }\n text ??= String(value);\n return text.length > 200 ? `${text.slice(0, 200)}…` : text;\n};\n\nconst toCallbackOutputs = (\n output: ExternalMessageConverterMessage | ExternalMessageConverterMessage[],\n input: unknown,\n): ExternalMessageConverterMessage[] => {\n const outputs = Array.isArray(output) ? output : [output];\n for (const o of outputs) {\n const valid =\n typeof o === \"object\" &&\n o !== null &&\n (o.role === \"tool\" ||\n ((o.role === \"assistant\" || o.role === \"user\" || o.role === \"system\") &&\n (typeof o.content === \"string\" || Array.isArray(o.content))));\n if (!valid)\n throw new Error(\n `External message converter: the converter callback returned an invalid message (${stringifyForError(o)}) for input ${stringifyForError(input)}. Return an empty array to skip a message.`,\n );\n }\n // Providers can emit tool results without a usable id (react-langchain maps\n // a missing tool_call_id to \"\"); converters must not throw on those, so the\n // result is dropped like any other orphaned tool output.\n return outputs.filter((o) => {\n if (o.role !== \"tool\") return true;\n if (typeof o.toolCallId === \"string\" && o.toolCallId.length > 0)\n return true;\n if (!warnedDroppedToolResults.has(o)) {\n warnedDroppedToolResults.add(o);\n console.warn(\n `External message converter: dropping a tool result without a toolCallId (${stringifyForError(o)}) for input ${stringifyForError(input)}.`,\n );\n }\n return false;\n });\n};\n\nconst warnedDroppedToolResults = new WeakSet<object>();\n\nexport const convertExternalMessageCallback = <T>(\n input: T,\n callback: ExternalMessageConverterCallback<T>,\n metadata: ExternalMessageConverterMetadata,\n): ExternalMessageConverterCallbackResult<T> => ({\n input,\n outputs: toCallbackOutputs(callback(input, metadata), input),\n});\n\nconst mergeInnerMessages = (existing: object, incoming: object) => ({\n [symbolInnerMessage]: [\n ...((existing as any)[symbolInnerMessage] ?? []),\n ...((incoming as any)[symbolInnerMessage] ?? []),\n ],\n});\n\nexport const joinExternalMessages = (\n messages: readonly ExternalMessageConverterMessage[],\n): ThreadMessageLike => {\n const assistantMessage: Mutable<Omit<ThreadMessageLike, \"metadata\">> & {\n content: Exclude<ThreadMessageLike[\"content\"][0], string>[];\n metadata?: Mutable<ThreadMessageLike[\"metadata\"]>;\n } = {\n role: \"assistant\",\n content: [],\n };\n for (const output of messages) {\n if (output.role === \"tool\") {\n const toolCallIdx = assistantMessage.content.findIndex(\n (c) => c.type === \"tool-call\" && c.toolCallId === output.toolCallId,\n );\n // Ignore orphaned tool results so one bad tool message does not\n // prevent rendering the rest of the conversation.\n if (toolCallIdx !== -1) {\n const toolCall = assistantMessage.content[\n toolCallIdx\n ]! as ToolCallMessagePart;\n if (output.toolName != null) {\n if (toolCall.toolName !== output.toolName)\n throw new Error(\n `Tool call name ${output.toolCallId} ${output.toolName} does not match existing tool call ${toolCall.toolName}`,\n );\n }\n assistantMessage.content[toolCallIdx] = {\n ...toolCall,\n ...{\n [symbolInnerMessage]: [\n ...((toolCall as any)[symbolInnerMessage] ?? []),\n output,\n ],\n },\n result: output.result,\n artifact: output.artifact,\n isError: output.isError,\n messages: output.messages,\n };\n }\n } else {\n const role = output.role;\n const content = (\n typeof output.content === \"string\"\n ? [{ type: \"text\" as const, text: output.content }]\n : output.content\n ).map((c) => ({\n ...c,\n ...{ [symbolInnerMessage]: [output] },\n }));\n switch (role) {\n case \"system\":\n case \"user\":\n return {\n ...output,\n content,\n };\n case \"assistant\":\n if (assistantMessage.content.length === 0) {\n assistantMessage.id = output.id;\n assistantMessage.createdAt ??= output.createdAt;\n assistantMessage.status ??= output.status;\n\n if (output.attachments) {\n assistantMessage.attachments = [\n ...(assistantMessage.attachments ?? []),\n ...output.attachments,\n ];\n }\n }\n\n if (output.metadata) {\n assistantMessage.metadata ??= {};\n if (output.metadata.unstable_state !== undefined) {\n assistantMessage.metadata.unstable_state =\n output.metadata.unstable_state;\n }\n if (output.metadata.unstable_annotations) {\n assistantMessage.metadata.unstable_annotations = [\n ...(assistantMessage.metadata.unstable_annotations ?? []),\n ...output.metadata.unstable_annotations,\n ];\n }\n if (output.metadata.unstable_data) {\n assistantMessage.metadata.unstable_data = [\n ...(assistantMessage.metadata.unstable_data ?? []),\n ...output.metadata.unstable_data,\n ];\n }\n if (output.metadata.steps) {\n assistantMessage.metadata.steps = [\n ...(assistantMessage.metadata.steps ?? []),\n ...output.metadata.steps,\n ];\n }\n if (output.metadata.custom) {\n assistantMessage.metadata.custom = {\n ...(assistantMessage.metadata.custom ?? {}),\n ...output.metadata.custom,\n };\n }\n\n if (output.metadata.timing) {\n assistantMessage.metadata.timing = output.metadata.timing;\n }\n\n if (output.metadata.submittedFeedback) {\n assistantMessage.metadata.submittedFeedback =\n output.metadata.submittedFeedback;\n }\n\n if (output.metadata.isOptimistic) {\n assistantMessage.metadata.isOptimistic = true;\n }\n // TODO keep this in sync with ThreadMessageLike[\"metadata\"] / fromThreadMessageLike\n }\n\n // Add content parts, merging reasoning parts with same parentId\n for (const part of content) {\n if (part.type === \"tool-call\") {\n const existingIdx = assistantMessage.content.findIndex(\n (c) =>\n c.type === \"tool-call\" && c.toolCallId === part.toolCallId,\n );\n if (existingIdx !== -1) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n ...part,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n\n if (\n part.type === \"reasoning\" &&\n \"parentId\" in part &&\n part.parentId\n ) {\n const existingIdx = assistantMessage.content.findIndex(\n (c) =>\n c.type === \"reasoning\" &&\n \"parentId\" in c &&\n c.parentId === part.parentId,\n );\n if (existingIdx !== -1) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n text: `${existing.text}\\n\\n${part.text}`,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n assistantMessage.content.push(part);\n }\n break;\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n }\n }\n return assistantMessage;\n};\n\nexport const chunkExternalMessages = <T>(\n callbackResults: ExternalMessageConverterCallbackResult<T>[],\n joinStrategy?: JoinStrategy,\n) => {\n const results: ExternalMessageConverterChunk<T>[] = [];\n let isAssistant = false;\n let pendingNone = false; // true if the previous assistant message had joinStrategy \"none\"\n let inputs: T[] = [];\n let outputs: ExternalMessageConverterMessage[] = [];\n\n const flush = () => {\n if (outputs.length) {\n results.push({\n inputs,\n outputs,\n });\n }\n inputs = [];\n outputs = [];\n isAssistant = false;\n pendingNone = false;\n };\n\n for (const callbackResult of callbackResults) {\n for (const output of callbackResult.outputs) {\n if (\n (pendingNone && output.role !== \"tool\") ||\n !isAssistant ||\n output.role === \"user\" ||\n output.role === \"system\"\n ) {\n flush();\n }\n isAssistant = output.role === \"assistant\" || output.role === \"tool\";\n\n if (inputs.at(-1) !== callbackResult.input) {\n inputs.push(callbackResult.input);\n }\n outputs.push(output);\n\n if (\n output.role === \"assistant\" &&\n (output.convertConfig?.joinStrategy === \"none\" ||\n joinStrategy === \"none\")\n ) {\n pendingNone = true;\n }\n }\n }\n flush();\n return results;\n};\n\nexport const shallowArrayEqual = (\n a: readonly unknown[],\n b: readonly unknown[],\n) => {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n};\n\ntype ExternalMessageConversionCache = {\n message: ThreadMessage | undefined;\n generatedFallbackMessages: WeakSet<object>;\n};\n\nexport const convertExternalMessageChunk = <T>(\n message: ExternalMessageConverterChunk<T>,\n idx: number,\n chunkCount: number,\n isRunning: boolean,\n error: ReadonlyJSONValue | undefined,\n cache?: ExternalMessageConversionCache,\n cancelledMessageIds?: ReadonlySet<string>,\n) => {\n const isLast = idx === chunkCount - 1;\n const joined = joinExternalMessages(message.outputs);\n const isCancelled =\n cancelledMessageIds !== undefined &&\n message.outputs.some(\n (output) =>\n output.role !== \"tool\" &&\n output.id != null &&\n cancelledMessageIds.has(output.id),\n );\n const hasInterruptedToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isInterruptedToolCall);\n const hasPendingToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isPendingToolCall);\n const autoStatus = getAutoStatus(\n isLast,\n isRunning,\n hasInterruptedToolCalls,\n hasPendingToolCalls,\n isLast ? error : undefined,\n isCancelled,\n );\n const fallbackId = `${FALLBACK_ID_PREFIX}${idx}`;\n\n const cachedMessage = cache?.message;\n if (\n cachedMessage &&\n (cachedMessage.role !== \"assistant\" ||\n !isAutoStatus(cachedMessage.status) ||\n cachedMessage.status === autoStatus ||\n (cachedMessage.status.type === \"incomplete\" &&\n cachedMessage.status.reason === \"error\" &&\n cachedMessage.status.error !== undefined &&\n autoStatus.type === \"incomplete\" &&\n autoStatus.reason === \"error\" &&\n autoStatus.error !== undefined &&\n (cachedMessage.status.error === autoStatus.error ||\n isJSONValueEqual(cachedMessage.status.error, autoStatus.error))))\n ) {\n const inputs = getExternalStoreMessages<T>(cachedMessage);\n if (shallowArrayEqual(inputs, message.inputs)) {\n // A positional fallback id goes stale when messages are prepended\n // or reordered; serving it unchanged makes two messages collide on\n // one id and the dedup downstream drops one of them.\n if (\n cache.generatedFallbackMessages.has(cachedMessage) &&\n cachedMessage.id !== fallbackId\n ) {\n const updated = { ...cachedMessage, id: fallbackId };\n cache.generatedFallbackMessages.add(updated);\n bindExternalStoreMessage(updated, message.inputs);\n return updated;\n }\n return cachedMessage;\n }\n }\n\n const newMessage = fromThreadMessageLike(joined, fallbackId, autoStatus);\n if (cache && joined.id == null) {\n cache.generatedFallbackMessages.add(newMessage);\n }\n bindExternalStoreMessage(newMessage, message.inputs);\n return newMessage;\n};\n\nfunction createErrorAssistantMessage(\n error: ReadonlyJSONValue,\n): ThreadAssistantMessage {\n const msg: ThreadAssistantMessage = {\n id: generateErrorMessageId(),\n role: \"assistant\",\n content: [],\n status: { type: \"incomplete\", reason: \"error\", error },\n createdAt: new Date(),\n metadata: {\n unstable_state: null,\n unstable_annotations: [],\n unstable_data: [],\n custom: {},\n steps: [],\n },\n };\n bindExternalStoreMessage(msg, []);\n return msg;\n}\n\nexport const completeExternalMessageConversion = (\n messages: ThreadMessage[],\n error: ReadonlyJSONValue | undefined,\n) => {\n if (error) {\n const lastMessage = messages.at(-1);\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n messages.push(createErrorAssistantMessage(error));\n }\n }\n return messages;\n};\n\nexport const convertExternalMessages = <T extends WeakKey>(\n messages: T[],\n callback: ExternalMessageConverterCallback<T>,\n isRunning: boolean,\n metadata: ExternalMessageConverterMetadata,\n) => {\n const callbackResults = messages.map((message) =>\n convertExternalMessageCallback(message, callback, metadata),\n );\n const chunks = chunkExternalMessages(callbackResults);\n const result = chunks.map((message, idx) =>\n convertExternalMessageChunk(\n message,\n idx,\n chunks.length,\n isRunning,\n metadata.error,\n undefined,\n metadata.cancelledMessageIds,\n ),\n );\n return completeExternalMessageConversion(result, metadata.error);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"external-message-conversion.js","names":["ReadonlyJSONValue","ToolExecutionStatus","ThreadMessageConverter","ThreadAssistantMessage","ThreadMessage","ToolCallMessagePart","MessageTiming","generateErrorMessageId","isJSONValueEqual","getAutoStatus","isAutoStatus","isBackgroundToolCall","isInterruptedToolCall","isPendingToolCall","bindExternalStoreMessage","FALLBACK_ID_PREFIX","getExternalStoreMessages","symbolInnerMessage","fromThreadMessageLike","ThreadMessageLike","JoinStrategy","ExternalMessageConverterMessage","convertConfig","joinStrategy","role","toolCallId","toolName","result","artifact","isError","messages","ExternalMessageConverterMetadata","toolStatuses","Record","error","cancelledMessageIds","ReadonlySet","messageTiming","ExternalMessageConverterCallback","message","T","metadata","ExternalMessageConverterCallbackResult","input","outputs","ExternalMessageConverterChunk","inputs","Mutable","P","stringifyForError","value","text","Error","String","JSON","stringify","length","slice","toCallbackOutputs","output","Array","isArray","o","valid","content","filter","warnedDroppedToolResults","has","add","console","warn","WeakSet","convertExternalMessageCallback","callback","mergeInnerMessages","existing","incoming","isNaNToolCallId","Number","isNaN","joinExternalMessages","assistantMessage","Omit","Exclude","toolCallIndices","Map","reasoningIndices","toolCallIdx","get","toolCall","type","const","map","c","id","createdAt","status","attachments","unstable_state","undefined","unstable_annotations","unstable_data","steps","custom","timing","modality","submittedFeedback","isOptimistic","part","existingIdx","parentId","partIdx","push","set","unsupportedRole","chunkExternalMessages","callbackResults","results","isAssistant","pendingNone","flush","callbackResult","at","shallowArrayEqual","a","b","i","ExternalMessageChunkConversionCache","generatedFallbackMessages","ExternalMessageConversionCallbackCacheEntry","InternalExternalMessageConversionCache","WeakKey","callbackCache","WeakMap","chunkCache","converterCache","createExternalMessageConversionCache","convertExternalMessageChunk","idx","chunkCount","isRunning","cache","isLast","joined","isCancelled","some","hasInterruptedToolCalls","hasPendingToolCalls","hasBackgroundToolCalls","autoStatus","fallbackId","cachedMessage","reason","updated","newMessage","createErrorAssistantMessage","msg","Date","completeExternalMessageConversion","lastMessage","convertExternalMessages","chunks","key","cached","convertMessages"],"sources":["../../../src/runtime/utils/external-message-conversion.ts"],"sourcesContent":["import type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport type { ToolExecutionStatus } from \"../../runtimes/tool-invocations/ToolInvocationTracker\";\nimport { ThreadMessageConverter } from \"../../runtimes/external-store/thread-message-converter\";\nimport type {\n ThreadAssistantMessage,\n ThreadMessage,\n ToolCallMessagePart,\n} from \"../../types/message\";\nimport type { MessageTiming } from \"../../types/message\";\nimport { generateErrorMessageId } from \"../../utils/id\";\nimport { isJSONValueEqual } from \"../../utils/json/is-json-equal\";\nimport {\n getAutoStatus,\n isAutoStatus,\n isBackgroundToolCall,\n isInterruptedToolCall,\n isPendingToolCall,\n} from \"./auto-status\";\nimport {\n bindExternalStoreMessage,\n FALLBACK_ID_PREFIX,\n getExternalStoreMessages,\n symbolInnerMessage,\n} from \"./external-store-message\";\nimport {\n fromThreadMessageLike,\n type ThreadMessageLike,\n} from \"./thread-message-like\";\n\nexport type JoinStrategy = \"concat-content\" | \"none\";\n\nexport type ExternalMessageConverterMessage =\n | (ThreadMessageLike & {\n readonly convertConfig?: {\n readonly joinStrategy?: JoinStrategy;\n };\n })\n | {\n role: \"tool\";\n toolCallId: string;\n toolName?: string | undefined;\n result: any;\n artifact?: any;\n isError?: boolean;\n messages?: readonly ThreadMessage[];\n };\n\nexport type ExternalMessageConverterMetadata = {\n readonly toolStatuses?: Record<string, ToolExecutionStatus>;\n readonly error?: ReadonlyJSONValue;\n readonly cancelledMessageIds?: ReadonlySet<string>;\n readonly messageTiming?: Record<string, MessageTiming>;\n};\n\nexport type ExternalMessageConverterCallback<T> = (\n message: T,\n metadata: ExternalMessageConverterMetadata,\n) => ExternalMessageConverterMessage | ExternalMessageConverterMessage[];\n\nexport type ExternalMessageConverterCallbackResult<T> = {\n input: T;\n outputs: ExternalMessageConverterMessage[];\n};\n\nexport type ExternalMessageConverterChunk<T> = {\n inputs: T[];\n outputs: ExternalMessageConverterMessage[];\n};\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: T[P];\n};\n\nconst stringifyForError = (value: unknown) => {\n let text;\n try {\n text = value instanceof Error ? String(value) : JSON.stringify(value);\n } catch {\n /* circular */\n }\n text ??= String(value);\n return text.length > 200 ? `${text.slice(0, 200)}…` : text;\n};\n\nconst toCallbackOutputs = (\n output: ExternalMessageConverterMessage | ExternalMessageConverterMessage[],\n input: unknown,\n): ExternalMessageConverterMessage[] => {\n const outputs = Array.isArray(output) ? output : [output];\n for (const o of outputs) {\n const valid =\n typeof o === \"object\" &&\n o !== null &&\n (o.role === \"tool\" ||\n ((o.role === \"assistant\" || o.role === \"user\" || o.role === \"system\") &&\n (typeof o.content === \"string\" || Array.isArray(o.content))));\n if (!valid)\n throw new Error(\n `External message converter: the converter callback returned an invalid message (${stringifyForError(o)}) for input ${stringifyForError(input)}. Return an empty array to skip a message.`,\n );\n }\n // Providers can emit tool results without a usable id (react-langchain maps\n // a missing tool_call_id to \"\"); converters must not throw on those, so the\n // result is dropped like any other orphaned tool output.\n return outputs.filter((o) => {\n if (o.role !== \"tool\") return true;\n if (typeof o.toolCallId === \"string\" && o.toolCallId.length > 0)\n return true;\n if (!warnedDroppedToolResults.has(o)) {\n warnedDroppedToolResults.add(o);\n console.warn(\n `External message converter: dropping a tool result without a toolCallId (${stringifyForError(o)}) for input ${stringifyForError(input)}.`,\n );\n }\n return false;\n });\n};\n\nconst warnedDroppedToolResults = new WeakSet<object>();\n\nexport const convertExternalMessageCallback = <T>(\n input: T,\n callback: ExternalMessageConverterCallback<T>,\n metadata: ExternalMessageConverterMetadata,\n): ExternalMessageConverterCallbackResult<T> => ({\n input,\n outputs: toCallbackOutputs(callback(input, metadata), input),\n});\n\nconst mergeInnerMessages = (existing: object, incoming: object) => ({\n [symbolInnerMessage]: [\n ...((existing as any)[symbolInnerMessage] ?? []),\n ...((incoming as any)[symbolInnerMessage] ?? []),\n ],\n});\n\nconst isNaNToolCallId = (toolCallId: unknown) =>\n typeof toolCallId === \"number\" && Number.isNaN(toolCallId);\n\nexport const joinExternalMessages = (\n messages: readonly ExternalMessageConverterMessage[],\n): ThreadMessageLike => {\n const assistantMessage: Mutable<Omit<ThreadMessageLike, \"metadata\">> & {\n content: Exclude<ThreadMessageLike[\"content\"][0], string>[];\n metadata?: Mutable<ThreadMessageLike[\"metadata\"]>;\n } = {\n role: \"assistant\",\n content: [],\n };\n const toolCallIndices = new Map<unknown, number>();\n const reasoningIndices = new Map<string, number>();\n for (const output of messages) {\n if (output.role === \"tool\") {\n const toolCallIdx = !isNaNToolCallId(output.toolCallId)\n ? (toolCallIndices.get(output.toolCallId) ?? -1)\n : -1;\n // Ignore orphaned tool results so one bad tool message does not\n // prevent rendering the rest of the conversation.\n if (toolCallIdx !== -1) {\n const toolCall = assistantMessage.content[\n toolCallIdx\n ]! as ToolCallMessagePart;\n if (output.toolName != null) {\n if (toolCall.toolName !== output.toolName)\n throw new Error(\n `Tool call name ${output.toolCallId} ${output.toolName} does not match existing tool call ${toolCall.toolName}`,\n );\n }\n assistantMessage.content[toolCallIdx] = {\n ...toolCall,\n ...{\n [symbolInnerMessage]: [\n ...((toolCall as any)[symbolInnerMessage] ?? []),\n output,\n ],\n },\n result: output.result,\n artifact: output.artifact,\n isError: output.isError,\n messages: output.messages,\n };\n }\n } else {\n const role = output.role;\n const content = (\n typeof output.content === \"string\"\n ? [{ type: \"text\" as const, text: output.content }]\n : output.content\n ).map((c) => ({\n ...c,\n ...{ [symbolInnerMessage]: [output] },\n }));\n switch (role) {\n case \"system\":\n case \"user\":\n return {\n ...output,\n content,\n };\n case \"assistant\":\n if (assistantMessage.content.length === 0) {\n assistantMessage.id = output.id;\n assistantMessage.createdAt ??= output.createdAt;\n assistantMessage.status ??= output.status;\n\n if (output.attachments) {\n assistantMessage.attachments = [\n ...(assistantMessage.attachments ?? []),\n ...output.attachments,\n ];\n }\n }\n\n if (output.metadata) {\n assistantMessage.metadata ??= {};\n if (output.metadata.unstable_state !== undefined) {\n assistantMessage.metadata.unstable_state =\n output.metadata.unstable_state;\n }\n if (output.metadata.unstable_annotations) {\n assistantMessage.metadata.unstable_annotations = [\n ...(assistantMessage.metadata.unstable_annotations ?? []),\n ...output.metadata.unstable_annotations,\n ];\n }\n if (output.metadata.unstable_data) {\n assistantMessage.metadata.unstable_data = [\n ...(assistantMessage.metadata.unstable_data ?? []),\n ...output.metadata.unstable_data,\n ];\n }\n if (output.metadata.steps) {\n assistantMessage.metadata.steps = [\n ...(assistantMessage.metadata.steps ?? []),\n ...output.metadata.steps,\n ];\n }\n if (output.metadata.custom) {\n assistantMessage.metadata.custom = {\n ...(assistantMessage.metadata.custom ?? {}),\n ...output.metadata.custom,\n };\n }\n\n if (output.metadata.timing) {\n assistantMessage.metadata.timing = output.metadata.timing;\n }\n\n if (output.metadata.modality) {\n assistantMessage.metadata.modality = output.metadata.modality;\n }\n\n if (output.metadata.submittedFeedback) {\n assistantMessage.metadata.submittedFeedback =\n output.metadata.submittedFeedback;\n }\n\n if (output.metadata.isOptimistic) {\n assistantMessage.metadata.isOptimistic = true;\n }\n // TODO keep this in sync with ThreadMessageLike[\"metadata\"] / fromThreadMessageLike\n }\n\n // Add content parts, merging reasoning parts with same parentId\n for (const part of content) {\n if (part.type === \"tool-call\" && part.toolCallId) {\n const existingIdx = toolCallIndices.get(part.toolCallId);\n if (existingIdx !== undefined) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n ...part,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n\n if (\n part.type === \"reasoning\" &&\n \"parentId\" in part &&\n part.parentId\n ) {\n const existingIdx = reasoningIndices.get(part.parentId);\n if (existingIdx !== undefined) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n text: `${existing.text}\\n\\n${part.text}`,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n const partIdx = assistantMessage.content.length;\n assistantMessage.content.push(part);\n if (\n part.type === \"tool-call\" &&\n !isNaNToolCallId(part.toolCallId) &&\n !toolCallIndices.has(part.toolCallId)\n ) {\n toolCallIndices.set(part.toolCallId, partIdx);\n } else if (\n part.type === \"reasoning\" &&\n \"parentId\" in part &&\n part.parentId\n ) {\n reasoningIndices.set(part.parentId, partIdx);\n }\n }\n break;\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n }\n }\n return assistantMessage;\n};\n\nexport const chunkExternalMessages = <T>(\n callbackResults: ExternalMessageConverterCallbackResult<T>[],\n joinStrategy?: JoinStrategy,\n) => {\n const results: ExternalMessageConverterChunk<T>[] = [];\n let isAssistant = false;\n let pendingNone = false; // true if the previous assistant message had joinStrategy \"none\"\n let inputs: T[] = [];\n let outputs: ExternalMessageConverterMessage[] = [];\n\n const flush = () => {\n if (outputs.length) {\n results.push({\n inputs,\n outputs,\n });\n }\n inputs = [];\n outputs = [];\n isAssistant = false;\n pendingNone = false;\n };\n\n for (const callbackResult of callbackResults) {\n for (const output of callbackResult.outputs) {\n if (\n (pendingNone && output.role !== \"tool\") ||\n !isAssistant ||\n output.role === \"user\" ||\n output.role === \"system\"\n ) {\n flush();\n }\n isAssistant = output.role === \"assistant\" || output.role === \"tool\";\n\n if (inputs.at(-1) !== callbackResult.input) {\n inputs.push(callbackResult.input);\n }\n outputs.push(output);\n\n if (\n output.role === \"assistant\" &&\n (output.convertConfig?.joinStrategy === \"none\" ||\n joinStrategy === \"none\")\n ) {\n pendingNone = true;\n }\n }\n }\n flush();\n return results;\n};\n\nexport const shallowArrayEqual = (\n a: readonly unknown[],\n b: readonly unknown[],\n) => {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n};\n\ntype ExternalMessageChunkConversionCache = {\n message: ThreadMessage | undefined;\n generatedFallbackMessages: WeakSet<object>;\n};\n\ntype ExternalMessageConversionCallbackCacheEntry<T> =\n ExternalMessageConverterCallbackResult<T> & {\n metadata: ExternalMessageConverterMetadata;\n callback: ExternalMessageConverterCallback<T>;\n };\n\nexport type InternalExternalMessageConversionCache<\n T extends WeakKey = WeakKey,\n> = {\n callbackCache: WeakMap<T, ExternalMessageConversionCallbackCacheEntry<T>>;\n chunkCache: WeakMap<\n ExternalMessageConverterMessage,\n ExternalMessageConverterChunk<T>\n >;\n converterCache: ThreadMessageConverter;\n // Generatedness is tracked by identity, not by id shape: a caller-supplied id that happens to match the generated pattern must never be rewritten.\n generatedFallbackMessages: WeakSet<object>;\n};\n\nexport const createExternalMessageConversionCache = <\n T extends WeakKey = WeakKey,\n>(): InternalExternalMessageConversionCache<T> => ({\n callbackCache: new WeakMap(),\n chunkCache: new WeakMap(),\n converterCache: new ThreadMessageConverter(),\n generatedFallbackMessages: new WeakSet(),\n});\n\nexport const convertExternalMessageChunk = <T>(\n message: ExternalMessageConverterChunk<T>,\n idx: number,\n chunkCount: number,\n isRunning: boolean,\n error: ReadonlyJSONValue | undefined,\n cache?: ExternalMessageChunkConversionCache,\n cancelledMessageIds?: ReadonlySet<string>,\n) => {\n const isLast = idx === chunkCount - 1;\n const joined = joinExternalMessages(message.outputs);\n const isCancelled =\n cancelledMessageIds !== undefined &&\n message.outputs.some(\n (output) =>\n output.role !== \"tool\" &&\n output.id != null &&\n cancelledMessageIds.has(output.id),\n );\n const hasInterruptedToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isInterruptedToolCall);\n const hasPendingToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isPendingToolCall);\n const hasBackgroundToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isBackgroundToolCall);\n const autoStatus = getAutoStatus(\n isLast,\n isRunning,\n hasInterruptedToolCalls,\n hasPendingToolCalls,\n isLast ? error : undefined,\n isCancelled,\n hasBackgroundToolCalls,\n );\n const fallbackId = `${FALLBACK_ID_PREFIX}${idx}`;\n\n const cachedMessage = cache?.message;\n if (\n cachedMessage &&\n (cachedMessage.role !== \"assistant\" ||\n !isAutoStatus(cachedMessage.status) ||\n cachedMessage.status === autoStatus ||\n (cachedMessage.status.type === \"incomplete\" &&\n cachedMessage.status.reason === \"error\" &&\n cachedMessage.status.error !== undefined &&\n autoStatus.type === \"incomplete\" &&\n autoStatus.reason === \"error\" &&\n autoStatus.error !== undefined &&\n (cachedMessage.status.error === autoStatus.error ||\n isJSONValueEqual(cachedMessage.status.error, autoStatus.error))))\n ) {\n const inputs = getExternalStoreMessages<T>(cachedMessage);\n if (shallowArrayEqual(inputs, message.inputs)) {\n // A positional fallback id goes stale when messages are prepended\n // or reordered; serving it unchanged makes two messages collide on\n // one id and the dedup downstream drops one of them.\n if (\n cache.generatedFallbackMessages.has(cachedMessage) &&\n cachedMessage.id !== fallbackId\n ) {\n const updated = { ...cachedMessage, id: fallbackId };\n cache.generatedFallbackMessages.add(updated);\n bindExternalStoreMessage(updated, message.inputs);\n return updated;\n }\n return cachedMessage;\n }\n }\n\n const newMessage = fromThreadMessageLike(joined, fallbackId, autoStatus);\n if (cache && joined.id == null) {\n cache.generatedFallbackMessages.add(newMessage);\n }\n bindExternalStoreMessage(newMessage, message.inputs);\n return newMessage;\n};\n\nfunction createErrorAssistantMessage(\n error: ReadonlyJSONValue,\n): ThreadAssistantMessage {\n const msg: ThreadAssistantMessage = {\n id: generateErrorMessageId(),\n role: \"assistant\",\n content: [],\n status: { type: \"incomplete\", reason: \"error\", error },\n createdAt: new Date(),\n metadata: {\n unstable_state: null,\n unstable_annotations: [],\n unstable_data: [],\n custom: {},\n steps: [],\n },\n };\n bindExternalStoreMessage(msg, []);\n return msg;\n}\n\nexport const completeExternalMessageConversion = (\n messages: ThreadMessage[],\n error: ReadonlyJSONValue | undefined,\n) => {\n if (error) {\n const lastMessage = messages.at(-1);\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n messages.push(createErrorAssistantMessage(error));\n }\n }\n return messages;\n};\n\nexport const convertExternalMessages = <T extends WeakKey>(\n messages: T[],\n callback: ExternalMessageConverterCallback<T>,\n isRunning: boolean,\n metadata: ExternalMessageConverterMetadata,\n joinStrategy?: JoinStrategy,\n cache?: InternalExternalMessageConversionCache<T>,\n) => {\n const callbackResults = messages.map((message) => {\n let result = cache?.callbackCache.get(message);\n if (\n !result ||\n result.metadata !== metadata ||\n result.callback !== callback\n ) {\n result = {\n ...convertExternalMessageCallback(message, callback, metadata),\n metadata,\n callback,\n };\n cache?.callbackCache.set(message, result);\n }\n return result;\n });\n const chunks = chunkExternalMessages(callbackResults, joinStrategy).map(\n (message) => {\n const key = message.outputs[0];\n if (!key || !cache) return message;\n\n const cached = cache.chunkCache.get(key);\n if (cached && shallowArrayEqual(cached.outputs, message.outputs)) {\n return cached;\n }\n cache.chunkCache.set(key, message);\n return message;\n },\n );\n const result = cache\n ? cache.converterCache.convertMessages(chunks, (cached, message, idx) =>\n convertExternalMessageChunk(\n message,\n idx,\n chunks.length,\n isRunning,\n metadata.error,\n {\n message: cached,\n generatedFallbackMessages: cache.generatedFallbackMessages,\n },\n metadata.cancelledMessageIds,\n ),\n )\n : chunks.map((message, idx) =>\n convertExternalMessageChunk(\n message,\n idx,\n chunks.length,\n isRunning,\n metadata.error,\n undefined,\n metadata.cancelledMessageIds,\n ),\n );\n return completeExternalMessageConversion(result, metadata.error);\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-repository.d.ts","names":[],"sources":["../../../src/runtime/utils/message-repository.ts"],"mappings":";;;KAOY;EACV,SAAS;EACT;EACA,YAAY;;KAGF;EACV;EACA,UAAU;IACR,SAAS;IACT;IACA,YAAY;;;cAIH;EAEC,YAAA,mBAAS,wBAClB;EAkBM,sBAAA;IACL,SAAS;IACT;OACC;IACS;QACX;;cAgEQ;UACH;UACA;UACA;UAKA;UAgBA;
|
|
1
|
+
{"version":3,"file":"message-repository.d.ts","names":[],"sources":["../../../src/runtime/utils/message-repository.ts"],"mappings":";;;KAOY;EACV,SAAS;EACT;EACA,YAAY;;KAGF;EACV;EACA,UAAU;IACR,SAAS;IACT;IACA,YAAY;;;cAIH;EAEC,YAAA,mBAAS,wBAClB;EAkBM,sBAAA;IACL,SAAS;IACT;OACC;IACS;QACX;;cAgEQ;UACH;UACA;UACA;UAKA;UAgBA;UAUA;UAgEA;MAQJ;MAIA;EAUJ,YAAY,2BAAe;EAuB3B,mBAAmB,yBAAyB,SAAS;EAiCrD,WAAW;;;;;EAcX,cAAc,mBAAmB;EAsCjC,YAAY;;;;;;;;;UAmBJ;EA+BR,eAAe;EAiBf,UAAU;EAuCV;EAUA,UAAU;EAgCV,SAAS,QAAQ,YAAY"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { generateId } from "../../utils/id.js";
|
|
2
2
|
import { fromThreadMessageLike } from "./thread-message-like.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getRepositoryContentAutoStatus } from "./auto-status.js";
|
|
4
4
|
//#region src/runtime/utils/message-repository.ts
|
|
5
5
|
const ExportedMessageRepository = {
|
|
6
6
|
fromArray: (messages) => {
|
|
7
|
-
const conv = messages.map((m) => fromThreadMessageLike(m, generateId(),
|
|
7
|
+
const conv = messages.map((m) => fromThreadMessageLike(m, generateId(), getRepositoryContentAutoStatus(m.content)));
|
|
8
8
|
return { messages: conv.map((m, idx) => ({
|
|
9
9
|
parentId: idx > 0 ? conv[idx - 1].id : null,
|
|
10
10
|
message: m
|
|
@@ -17,7 +17,7 @@ const ExportedMessageRepository = {
|
|
|
17
17
|
if (!message.id) throw new Error("ExportedMessageRepository.fromBranchableArray: Each message must have an 'id' field set.");
|
|
18
18
|
return {
|
|
19
19
|
parentId,
|
|
20
|
-
message: fromThreadMessageLike(message, message.id,
|
|
20
|
+
message: fromThreadMessageLike(message, message.id, getRepositoryContentAutoStatus(message.content))
|
|
21
21
|
};
|
|
22
22
|
})
|
|
23
23
|
};
|
|
@@ -66,6 +66,9 @@ var MessageRepository = class {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
selectPathTo(message) {
|
|
70
|
+
for (let current = message; current; current = current.prev) (current.prev ?? this.root).next = current;
|
|
71
|
+
}
|
|
69
72
|
performOp(newParent, child, operation) {
|
|
70
73
|
const parentOrRoot = child.prev ?? this.root;
|
|
71
74
|
const newParentOrRoot = newParent ?? this.root;
|
|
@@ -84,8 +87,12 @@ var MessageRepository = class {
|
|
|
84
87
|
}
|
|
85
88
|
if (operation !== "cut") {
|
|
86
89
|
newParentOrRoot.children = [...newParentOrRoot.children, child.current.id];
|
|
87
|
-
if (findHead(child) === this.head || newParentOrRoot.next === null) newParentOrRoot.next = child;
|
|
88
90
|
child.prev = newParent;
|
|
91
|
+
if (findHead(child) === this.head) this.selectPathTo(child);
|
|
92
|
+
else if (newParentOrRoot.next === null) {
|
|
93
|
+
newParentOrRoot.next = child;
|
|
94
|
+
if (this.head === newParentOrRoot) this.head = findHead(child);
|
|
95
|
+
}
|
|
89
96
|
const newLevel = newParent ? newParent.level + 1 : 0;
|
|
90
97
|
this.updateLevels(child, newLevel);
|
|
91
98
|
}
|
|
@@ -186,8 +193,7 @@ var MessageRepository = class {
|
|
|
186
193
|
const message = this.messages.get(messageId);
|
|
187
194
|
if (!message) throw new Error("MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui.");
|
|
188
195
|
const previousHead = this.head;
|
|
189
|
-
|
|
190
|
-
prevOrRoot.next = message;
|
|
196
|
+
this.selectPathTo(message);
|
|
191
197
|
this.head = findHead(message);
|
|
192
198
|
this.evictOffBranchOptimisticMessages(previousHead, this.head);
|
|
193
199
|
this._messages.dirty();
|
|
@@ -214,8 +220,7 @@ var MessageRepository = class {
|
|
|
214
220
|
message.next = null;
|
|
215
221
|
}
|
|
216
222
|
this.head = message;
|
|
217
|
-
|
|
218
|
-
else this.root.next = current;
|
|
223
|
+
this.selectPathTo(message);
|
|
219
224
|
this.evictOffBranchOptimisticMessages(previousHead, this.head);
|
|
220
225
|
this._messages.dirty();
|
|
221
226
|
}
|
|
@@ -230,7 +235,11 @@ var MessageRepository = class {
|
|
|
230
235
|
}
|
|
231
236
|
export() {
|
|
232
237
|
const exportItems = [];
|
|
233
|
-
|
|
238
|
+
const pending = [...this.root.children].reverse();
|
|
239
|
+
while (pending.length > 0) {
|
|
240
|
+
const message = this.messages.get(pending.pop());
|
|
241
|
+
if (!message) continue;
|
|
242
|
+
for (let i = message.children.length - 1; i >= 0; i--) pending.push(message.children[i]);
|
|
234
243
|
if (message.current.metadata?.isOptimistic) continue;
|
|
235
244
|
let prev = message.prev;
|
|
236
245
|
while (prev && prev.current.metadata?.isOptimistic) prev = prev.prev;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-repository.js","names":["ThreadMessage","RunConfig","generateId","ThreadMessageLike","getContentAutoStatus","fromThreadMessageLike","ExportedMessageRepositoryItem","message","parentId","runConfig","ExportedMessageRepository","headId","messages","Array","fromArray","conv","map","m","content","idx","id","fromBranchableArray","items","options","undefined","Error","RepositoryParent","children","next","RepositoryMessage","prev","current","level","findHead","CachedValue","_value","T","func","constructor","value","dirty","MessageRepository","Map","head","root","updateLevels","newLevel","pending","length","pop","childId","childMessage","get","push","performOp","newParent","child","operation","parentOrRoot","newParentOrRoot","filter","fallbackId","at","fallback","_messages","canonicalHeadId","metadata","isOptimistic","getMessages","headMessage","addOrUpdateMessage","existingItem","newItem","set","getMessage","messageId","index","deleteMessage","replacementId","replacement","delete","getBranches","evictOffBranchOptimisticMessages","previousHead","currentHead","onHeadBranch","Set","add","stale","has","switchToBranch","prevOrRoot","resetHead","clear","descendantId","export","exportItems","import"],"sources":["../../../src/runtime/utils/message-repository.ts"],"sourcesContent":["import type { ThreadMessage } from \"../../types/message\";\nimport type { RunConfig } from \"../../types/message\";\nimport { generateId } from \"../../utils/id\";\nimport type { ThreadMessageLike } from \"./thread-message-like\";\nimport { getContentAutoStatus } from \"./auto-status\";\nimport { fromThreadMessageLike } from \"./thread-message-like\";\n\nexport type ExportedMessageRepositoryItem = {\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n};\n\nexport type ExportedMessageRepository = {\n headId?: string | null;\n messages: Array<{\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n }>;\n};\n\nexport const ExportedMessageRepository = {\n fromArray: (\n messages: readonly ThreadMessageLike[],\n ): ExportedMessageRepository => {\n const conv = messages.map((m) =>\n fromThreadMessageLike(\n m,\n generateId(),\n getContentAutoStatus(m.content, false, false),\n ),\n );\n\n return {\n messages: conv.map((m, idx) => ({\n parentId: idx > 0 ? conv[idx - 1]!.id : null,\n message: m,\n })),\n };\n },\n\n fromBranchableArray: (\n items: readonly {\n message: ThreadMessageLike;\n parentId: string | null;\n }[],\n options?: { headId?: string | null },\n ): ExportedMessageRepository => {\n return {\n ...(options?.headId !== undefined\n ? { headId: options.headId }\n : undefined),\n messages: items.map(({ message, parentId }) => {\n if (!message.id) {\n throw new Error(\n \"ExportedMessageRepository.fromBranchableArray: Each message must have an 'id' field set.\",\n );\n }\n return {\n parentId,\n message: fromThreadMessageLike(\n message,\n message.id,\n getContentAutoStatus(message.content, false, false),\n ),\n };\n }),\n };\n },\n};\n\ntype RepositoryParent = {\n children: string[];\n next: RepositoryMessage | null;\n};\n\ntype RepositoryMessage = RepositoryParent & {\n prev: RepositoryMessage | null;\n current: ThreadMessage;\n level: number;\n};\n\nconst findHead = (\n message: RepositoryMessage | RepositoryParent,\n): RepositoryMessage | null => {\n let current = message;\n while (current.next) current = current.next;\n return \"current\" in current ? current : null;\n};\n\nclass CachedValue<T> {\n private _value: T | null = null;\n\n private func: () => T;\n\n constructor(func: () => T) {\n this.func = func;\n }\n\n get value() {\n if (this._value === null) {\n this._value = this.func();\n }\n return this._value;\n }\n\n dirty() {\n this._value = null;\n }\n}\n\nexport class MessageRepository {\n private messages = new Map<string, RepositoryMessage>();\n private head: RepositoryMessage | null = null;\n private root: RepositoryParent = {\n children: [],\n next: null,\n };\n\n private updateLevels(message: RepositoryMessage, newLevel: number) {\n const pending = [{ message, level: newLevel }];\n\n while (pending.length > 0) {\n const current = pending.pop()!;\n current.message.level = current.level;\n\n for (const childId of current.message.children) {\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n pending.push({ message: childMessage, level: current.level + 1 });\n }\n }\n }\n }\n\n private performOp(\n newParent: RepositoryMessage | null,\n child: RepositoryMessage,\n operation: \"cut\" | \"link\" | \"relink\",\n ) {\n const parentOrRoot = child.prev ?? this.root;\n const newParentOrRoot = newParent ?? this.root;\n\n if (operation === \"relink\" && parentOrRoot === newParentOrRoot) return;\n\n // `link` receives a fresh ID from `addOrUpdateMessage`; only `relink` can introduce a cycle.\n if (operation === \"relink\") {\n for (\n let current: RepositoryMessage | null = newParent;\n current;\n current = current.prev\n ) {\n if (current.current.id === child.current.id) {\n throw new Error(\n \"MessageRepository(performOp/relink): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui.\",\n );\n }\n }\n }\n\n if (operation !== \"link\") {\n parentOrRoot.children = parentOrRoot.children.filter(\n (m) => m !== child.current.id,\n );\n\n if (parentOrRoot.next === child) {\n const fallbackId = parentOrRoot.children.at(-1);\n const fallback = fallbackId ? this.messages.get(fallbackId) : null;\n if (fallback === undefined) {\n throw new Error(\n \"MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n parentOrRoot.next = fallback;\n }\n }\n\n if (operation !== \"cut\") {\n newParentOrRoot.children = [\n ...newParentOrRoot.children,\n child.current.id,\n ];\n\n if (findHead(child) === this.head || newParentOrRoot.next === null) {\n newParentOrRoot.next = child;\n }\n\n child.prev = newParent;\n\n const newLevel = newParent ? newParent.level + 1 : 0;\n this.updateLevels(child, newLevel);\n }\n }\n\n private _messages = new CachedValue<readonly ThreadMessage[]>(() => {\n const messages = new Array<ThreadMessage>((this.head?.level ?? -1) + 1);\n for (let current = this.head; current; current = current.prev) {\n messages[current.level] = current.current;\n }\n return messages;\n });\n\n get headId() {\n return this.head?.current.id ?? null;\n }\n\n get canonicalHeadId() {\n // Optimistic messages are ephemeral, so persisted callers need the nearest\n // non-optimistic ancestor rather than the raw head.\n let head = this.head;\n while (head?.current.metadata?.isOptimistic) {\n head = head.prev;\n }\n return head?.current.id ?? null;\n }\n\n getMessages(headId?: string) {\n if (headId === undefined || headId === this.head?.current.id) {\n return this._messages.value;\n }\n\n const headMessage = this.messages.get(headId);\n if (!headMessage) {\n throw new Error(\n \"MessageRepository(getMessages): Head message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n\n const messages = new Array<ThreadMessage>(headMessage.level + 1);\n for (\n let current: RepositoryMessage | null = headMessage;\n current;\n current = current.prev\n ) {\n messages[current.level] = current.current;\n }\n return messages;\n }\n\n addOrUpdateMessage(parentId: string | null, message: ThreadMessage) {\n const existingItem = this.messages.get(message.id);\n const prev = parentId ? this.messages.get(parentId) : null;\n if (prev === undefined)\n throw new Error(\n \"MessageRepository(addOrUpdateMessage): Parent message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n if (existingItem) {\n existingItem.current = message;\n this.performOp(prev, existingItem, \"relink\");\n this._messages.dirty();\n return;\n }\n\n const newItem: RepositoryMessage = {\n prev,\n current: message,\n next: null,\n children: [],\n level: prev ? prev.level + 1 : 0,\n };\n\n this.messages.set(message.id, newItem);\n this.performOp(prev, newItem, \"link\");\n\n if (this.head === prev) {\n this.head = newItem;\n }\n\n this._messages.dirty();\n }\n\n getMessage(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(updateMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n return {\n parentId: message.prev?.current.id ?? null,\n message: message.current,\n index: message.level,\n };\n }\n\n deleteMessage(messageId: string, replacementId?: string | null | undefined) {\n const message = this.messages.get(messageId);\n\n if (!message)\n throw new Error(\n \"MessageRepository(deleteMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const replacement =\n replacementId === undefined\n ? message.prev\n : replacementId === null\n ? null\n : this.messages.get(replacementId);\n if (replacement === undefined)\n throw new Error(\n \"MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui.\",\n );\n\n for (const child of message.children) {\n const childMessage = this.messages.get(child);\n if (!childMessage)\n throw new Error(\n \"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui.\",\n );\n this.performOp(replacement, childMessage, \"relink\");\n }\n\n this.performOp(null, message, \"cut\");\n this.messages.delete(messageId);\n\n if (this.head === message) {\n this.head = findHead(replacement ?? this.root);\n }\n\n this._messages.dirty();\n }\n\n getBranches(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(getBranches): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const { children } = message.prev ?? this.root;\n return children;\n }\n\n /**\n * Evicts optimistic messages (`metadata.isOptimistic`) the head just moved\n * away from. Since eviction runs on every head move, the only optimistic\n * messages in the repository live on the branch the head previously pointed\n * at — so we walk just that branch rather than the whole repository. Keeps a\n * client→server id swap from leaving a phantom sibling, and drops off-branch\n * placeholders.\n */\n private evictOffBranchOptimisticMessages(\n previousHead: RepositoryMessage | null,\n currentHead: RepositoryMessage | null,\n ) {\n if (!previousHead) return;\n\n const onHeadBranch = new Set<string>();\n for (let current = currentHead; current; current = current.prev) {\n onHeadBranch.add(current.current.id);\n }\n\n const stale: string[] = [];\n for (\n let current: RepositoryMessage | null = previousHead;\n current;\n current = current.prev\n ) {\n // Stop at the first node shared with the current head branch: every\n // ancestor above it is shared too, so nothing further can be off-branch.\n if (onHeadBranch.has(current.current.id)) break;\n if (current.current.metadata?.isOptimistic) {\n stale.push(current.current.id);\n }\n }\n\n for (const id of stale) {\n // A prior deletion may have already removed this node.\n if (this.messages.has(id)) this.deleteMessage(id);\n }\n }\n\n switchToBranch(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const previousHead = this.head;\n const prevOrRoot = message.prev ?? this.root;\n prevOrRoot.next = message;\n\n this.head = findHead(message);\n\n this.evictOffBranchOptimisticMessages(previousHead, this.head);\n\n this._messages.dirty();\n }\n\n resetHead(messageId: string | null) {\n if (messageId === null) {\n this.clear();\n return;\n }\n\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const previousHead = this.head;\n\n if (message.children.length > 0) {\n const pending = [...message.children];\n while (pending.length > 0) {\n const childId = pending.pop()!;\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n for (const descendantId of childMessage.children) {\n pending.push(descendantId);\n }\n this.messages.delete(childId);\n }\n }\n\n message.children = [];\n message.next = null;\n }\n\n this.head = message;\n for (\n let current: RepositoryMessage | null = message;\n current;\n current = current.prev\n ) {\n if (current.prev) {\n current.prev.next = current;\n } else {\n this.root.next = current;\n }\n }\n\n this.evictOffBranchOptimisticMessages(previousHead, this.head);\n\n this._messages.dirty();\n }\n\n clear(): void {\n this.messages.clear();\n this.head = null;\n this.root = {\n children: [],\n next: null,\n };\n this._messages.dirty();\n }\n\n export(): ExportedMessageRepository {\n const exportItems: ExportedMessageRepository[\"messages\"] = [];\n\n // Optimistic messages are ephemeral and never persisted. A persisted child\n // of an optimistic node is re-parented onto its nearest persisted ancestor\n // so the exported tree never references a skipped id.\n for (const [, message] of this.messages) {\n if (message.current.metadata?.isOptimistic) continue;\n let prev = message.prev;\n while (prev && prev.current.metadata?.isOptimistic) {\n prev = prev.prev;\n }\n exportItems.push({\n message: message.current,\n parentId: prev?.current.id ?? null,\n });\n }\n\n return {\n headId: this.canonicalHeadId,\n messages: exportItems,\n };\n }\n\n import({ headId, messages }: ExportedMessageRepository) {\n for (const { message, parentId } of messages) {\n this.addOrUpdateMessage(parentId, message);\n }\n\n this.resetHead(headId ?? messages.at(-1)?.message.id ?? null);\n }\n}\n"],"mappings":";;;;AAsBA,MAAaU,4BAA4B;CACvCI,YACEF,aAC8B;EAC9B,MAAMG,OAAOH,SAASI,KAAKC,MACzBZ,sBACEY,GACAf,WAAW,GACXE,qBAAqBa,EAAEC,SAAS,OAAO,KAAK,CAC9C,CACF;EAEA,OAAO,EACLN,UAAUG,KAAKC,KAAKC,GAAGE,SAAS;GAC9BX,UAAUW,MAAM,IAAIJ,KAAKI,MAAM,EAAE,CAAEC,KAAK;GACxCb,SAASU;EACX,EAAE,EACJ;CACF;CAEAI,sBACEC,OAIAC,YAC8B;EAC9B,OAAO;GACL,GAAIA,SAASZ,WAAWa,KAAAA,IACpB,EAAEb,QAAQY,QAAQZ,OAAO,IACzBa,KAAAA;GACJZ,UAAUU,MAAMN,KAAK,EAAET,SAASC,eAAe;IAC7C,IAAI,CAACD,QAAQa,IACX,MAAM,IAAIK,MACR,0FACF;IAEF,OAAO;KACLjB;KACAD,SAASF,sBACPE,SACAA,QAAQa,IACRhB,qBAAqBG,QAAQW,SAAS,OAAO,KAAK,CACpD;IACF;GACF,CAAC;EACH;CACF;AACF;AAaA,MAAMe,YACJ1B,YAC6B;CAC7B,IAAIwB,UAAUxB;CACd,OAAOwB,QAAQH,MAAMG,UAAUA,QAAQH;CACvC,OAAO,aAAaG,UAAUA,UAAU;AAC1C;AAEA,IAAMG,cAAN,MAAqB;CACnB,SAA2B;CAE3B;CAEAI,YAAYD,MAAe;EACzB,KAAKA,OAAOA;CACd;CAEA,IAAIE,QAAQ;EACV,IAAI,KAAKJ,WAAW,MAClB,KAAKA,SAAS,KAAKE,KAAK;EAE1B,OAAO,KAAKF;CACd;CAEAK,QAAQ;EACN,KAAKL,SAAS;CAChB;AACF;AAEA,IAAaM,oBAAb,MAA+B;CAC7B,2BAAmB,IAAIC,IAA+B;CACtD,OAAyC;CACzC,OAAiC;EAC/Bf,UAAU,CAAA;EACVC,MAAM;CACR;CAEA,aAAqBrB,SAA4BuC,UAAkB;EACjE,MAAMC,UAAU,CAAC;GAAExC;GAASyB,OAAOc;EAAS,CAAC;EAE7C,OAAOC,QAAQC,SAAS,GAAG;GACzB,MAAMjB,UAAUgB,QAAQE,IAAI;GAC5BlB,QAAQxB,QAAQyB,QAAQD,QAAQC;GAEhC,KAAK,MAAMkB,WAAWnB,QAAQxB,QAAQoB,UAAU;IAC9C,MAAMwB,eAAe,KAAKvC,SAASwC,IAAIF,OAAO;IAC9C,IAAIC,cACFJ,QAAQM,KAAK;KAAE9C,SAAS4C;KAAcnB,OAAOD,QAAQC,QAAQ;IAAE,CAAC;GAEpE;EACF;CACF;CAEA,UACEuB,WACAC,OACAC,WACA;EACA,MAAMC,eAAeF,MAAM1B,QAAQ,KAAKc;EACxC,MAAMe,kBAAkBJ,aAAa,KAAKX;EAE1C,IAAIa,cAAc,YAAYC,iBAAiBC,iBAAiB;EAGhE,IAAIF,cAAc,UAEd;QAAA,IAAI1B,UAAoCwB,WACxCxB,SACAA,UAAUA,QAAQD,MAElB,IAAIC,QAAQA,QAAQX,OAAOoC,MAAMzB,QAAQX,IACvC,MAAM,IAAIK,MACR,sNACF;EAAA;EAKN,IAAIgC,cAAc,QAAQ;GACxBC,aAAa/B,WAAW+B,aAAa/B,SAASiC,QAC3C3C,MAAMA,MAAMuC,MAAMzB,QAAQX,EAC7B;GAEA,IAAIsC,aAAa9B,SAAS4B,OAAO;IAC/B,MAAMK,aAAaH,aAAa/B,SAASmC,GAAG,EAAE;IAC9C,MAAMC,WAAWF,aAAa,KAAKjD,SAASwC,IAAIS,UAAU,IAAI;IAC9D,IAAIE,aAAavC,KAAAA,GACf,MAAM,IAAIC,MACR,uHACF;IAEFiC,aAAa9B,OAAOmC;GACtB;EACF;EAEA,IAAIN,cAAc,OAAO;GACvBE,gBAAgBhC,WAAW,CACzB,GAAGgC,gBAAgBhC,UACnB6B,MAAMzB,QAAQX,EAAE;GAGlB,IAAIa,SAASuB,KAAK,MAAM,KAAKb,QAAQgB,gBAAgB/B,SAAS,MAC5D+B,gBAAgB/B,OAAO4B;GAGzBA,MAAM1B,OAAOyB;GAEb,MAAMT,WAAWS,YAAYA,UAAUvB,QAAQ,IAAI;GACnD,KAAKa,aAAaW,OAAOV,QAAQ;EACnC;CACF;CAEA,YAAoB,IAAIZ,kBAA4C;EAClE,MAAMtB,WAAW,IAAIC,OAAsB,KAAK8B,MAAMX,SAAS,MAAM,CAAC;EACtE,KAAK,IAAID,UAAU,KAAKY,MAAMZ,SAASA,UAAUA,QAAQD,MACvDlB,SAASmB,QAAQC,SAASD,QAAQA;EAEpC,OAAOnB;CACT,CAAC;CAED,IAAID,SAAS;EACX,OAAO,KAAKgC,MAAMZ,QAAQX,MAAM;CAClC;CAEA,IAAI6C,kBAAkB;EAGpB,IAAItB,OAAO,KAAKA;EAChB,OAAOA,MAAMZ,QAAQmC,UAAUC,cAC7BxB,OAAOA,KAAKb;EAEd,OAAOa,MAAMZ,QAAQX,MAAM;CAC7B;CAEAgD,YAAYzD,QAAiB;EAC3B,IAAIA,WAAWa,KAAAA,KAAab,WAAW,KAAKgC,MAAMZ,QAAQX,IACxD,OAAO,KAAK4C,UAAUzB;EAGxB,MAAM8B,cAAc,KAAKzD,SAASwC,IAAIzC,MAAM;EAC5C,IAAI,CAAC0D,aACH,MAAM,IAAI5C,MACR,yGACF;EAGF,MAAMb,WAAW,IAAIC,MAAqBwD,YAAYrC,QAAQ,CAAC;EAC/D,KACE,IAAID,UAAoCsC,aACxCtC,SACAA,UAAUA,QAAQD,MAElBlB,SAASmB,QAAQC,SAASD,QAAQA;EAEpC,OAAOnB;CACT;CAEA0D,mBAAmB9D,UAAyBD,SAAwB;EAClE,MAAMgE,eAAe,KAAK3D,SAASwC,IAAI7C,QAAQa,EAAE;EACjD,MAAMU,OAAOtB,WAAW,KAAKI,SAASwC,IAAI5C,QAAQ,IAAI;EACtD,IAAIsB,SAASN,KAAAA,GACX,MAAM,IAAIC,MACR,kHACF;EAEF,IAAI8C,cAAc;GAChBA,aAAaxC,UAAUxB;GACvB,KAAK+C,UAAUxB,MAAMyC,cAAc,QAAQ;GAC3C,KAAKP,UAAUxB,MAAM;GACrB;EACF;EAEA,MAAMgC,UAA6B;GACjC1C;GACAC,SAASxB;GACTqB,MAAM;GACND,UAAU,CAAA;GACVK,OAAOF,OAAOA,KAAKE,QAAQ,IAAI;EACjC;EAEA,KAAKpB,SAAS6D,IAAIlE,QAAQa,IAAIoD,OAAO;EACrC,KAAKlB,UAAUxB,MAAM0C,SAAS,MAAM;EAEpC,IAAI,KAAK7B,SAASb,MAChB,KAAKa,OAAO6B;EAGd,KAAKR,UAAUxB,MAAM;CACvB;CAEAkC,WAAWC,WAAmB;EAC5B,MAAMpE,UAAU,KAAKK,SAASwC,IAAIuB,SAAS;EAC3C,IAAI,CAACpE,SACH,MAAM,IAAIkB,MACR,sGACF;EAEF,OAAO;GACLjB,UAAUD,QAAQuB,MAAMC,QAAQX,MAAM;GACtCb,SAASA,QAAQwB;GACjB6C,OAAOrE,QAAQyB;EACjB;CACF;CAEA6C,cAAcF,WAAmBG,eAA2C;EAC1E,MAAMvE,UAAU,KAAKK,SAASwC,IAAIuB,SAAS;EAE3C,IAAI,CAACpE,SACH,MAAM,IAAIkB,MACR,sGACF;EAEF,MAAMsD,cACJD,kBAAkBtD,KAAAA,IACdjB,QAAQuB,OACRgD,kBAAkB,OAChB,OACA,KAAKlE,SAASwC,IAAI0B,aAAa;EACvC,IAAIC,gBAAgBvD,KAAAA,GAClB,MAAM,IAAIC,MACR,0GACF;EAEF,KAAK,MAAM+B,SAASjD,QAAQoB,UAAU;GACpC,MAAMwB,eAAe,KAAKvC,SAASwC,IAAII,KAAK;GAC5C,IAAI,CAACL,cACH,MAAM,IAAI1B,MACR,4GACF;GACF,KAAK6B,UAAUyB,aAAa5B,cAAc,QAAQ;EACpD;EAEA,KAAKG,UAAU,MAAM/C,SAAS,KAAK;EACnC,KAAKK,SAASoE,OAAOL,SAAS;EAE9B,IAAI,KAAKhC,SAASpC,SAChB,KAAKoC,OAAOV,SAAS8C,eAAe,KAAKnC,IAAI;EAG/C,KAAKoB,UAAUxB,MAAM;CACvB;CAEAyC,YAAYN,WAAmB;EAC7B,MAAMpE,UAAU,KAAKK,SAASwC,IAAIuB,SAAS;EAC3C,IAAI,CAACpE,SACH,MAAM,IAAIkB,MACR,oGACF;EAEF,MAAM,EAAEE,aAAapB,QAAQuB,QAAQ,KAAKc;EAC1C,OAAOjB;CACT;;;;;;;;;CAUA,iCACEwD,cACAC,aACA;EACA,IAAI,CAACD,cAAc;EAEnB,MAAME,+BAAe,IAAIC,IAAY;EACrC,KAAK,IAAIvD,UAAUqD,aAAarD,SAASA,UAAUA,QAAQD,MACzDuD,aAAaE,IAAIxD,QAAQA,QAAQX,EAAE;EAGrC,MAAMoE,QAAkB,CAAA;EACxB,KACE,IAAIzD,UAAoCoD,cACxCpD,SACAA,UAAUA,QAAQD,MAClB;GAGA,IAAIuD,aAAaI,IAAI1D,QAAQA,QAAQX,EAAE,GAAG;GAC1C,IAAIW,QAAQA,QAAQmC,UAAUC,cAC5BqB,MAAMnC,KAAKtB,QAAQA,QAAQX,EAAE;EAEjC;EAEA,KAAK,MAAMA,MAAMoE,OAEf,IAAI,KAAK5E,SAAS6E,IAAIrE,EAAE,GAAG,KAAKyD,cAAczD,EAAE;CAEpD;CAEAsE,eAAef,WAAmB;EAChC,MAAMpE,UAAU,KAAKK,SAASwC,IAAIuB,SAAS;EAC3C,IAAI,CAACpE,SACH,MAAM,IAAIkB,MACR,sGACF;EAEF,MAAM0D,eAAe,KAAKxC;EAC1B,MAAMgD,aAAapF,QAAQuB,QAAQ,KAAKc;EACxC+C,WAAW/D,OAAOrB;EAElB,KAAKoC,OAAOV,SAAS1B,OAAO;EAE5B,KAAK2E,iCAAiCC,cAAc,KAAKxC,IAAI;EAE7D,KAAKqB,UAAUxB,MAAM;CACvB;CAEAoD,UAAUjB,WAA0B;EAClC,IAAIA,cAAc,MAAM;GACtB,KAAKkB,MAAM;GACX;EACF;EAEA,MAAMtF,UAAU,KAAKK,SAASwC,IAAIuB,SAAS;EAC3C,IAAI,CAACpE,SACH,MAAM,IAAIkB,MACR,iGACF;EAEF,MAAM0D,eAAe,KAAKxC;EAE1B,IAAIpC,QAAQoB,SAASqB,SAAS,GAAG;GAC/B,MAAMD,UAAU,CAAC,GAAGxC,QAAQoB,QAAQ;GACpC,OAAOoB,QAAQC,SAAS,GAAG;IACzB,MAAME,UAAUH,QAAQE,IAAI;IAC5B,MAAME,eAAe,KAAKvC,SAASwC,IAAIF,OAAO;IAC9C,IAAIC,cAAc;KAChB,KAAK,MAAM2C,gBAAgB3C,aAAaxB,UACtCoB,QAAQM,KAAKyC,YAAY;KAE3B,KAAKlF,SAASoE,OAAO9B,OAAO;IAC9B;GACF;GAEA3C,QAAQoB,WAAW,CAAA;GACnBpB,QAAQqB,OAAO;EACjB;EAEA,KAAKe,OAAOpC;EACZ,KACE,IAAIwB,UAAoCxB,SACxCwB,SACAA,UAAUA,QAAQD,MAElB,IAAIC,QAAQD,MACVC,QAAQD,KAAKF,OAAOG;OAEpB,KAAKa,KAAKhB,OAAOG;EAIrB,KAAKmD,iCAAiCC,cAAc,KAAKxC,IAAI;EAE7D,KAAKqB,UAAUxB,MAAM;CACvB;CAEAqD,QAAc;EACZ,KAAKjF,SAASiF,MAAM;EACpB,KAAKlD,OAAO;EACZ,KAAKC,OAAO;GACVjB,UAAU,CAAA;GACVC,MAAM;EACR;EACA,KAAKoC,UAAUxB,MAAM;CACvB;CAEAuD,SAAoC;EAClC,MAAMC,cAAqD,CAAA;EAK3D,KAAK,MAAM,GAAGzF,YAAY,KAAKK,UAAU;GACvC,IAAIL,QAAQwB,QAAQmC,UAAUC,cAAc;GAC5C,IAAIrC,OAAOvB,QAAQuB;GACnB,OAAOA,QAAQA,KAAKC,QAAQmC,UAAUC,cACpCrC,OAAOA,KAAKA;GAEdkE,YAAY3C,KAAK;IACf9C,SAASA,QAAQwB;IACjBvB,UAAUsB,MAAMC,QAAQX,MAAM;GAChC,CAAC;EACH;EAEA,OAAO;GACLT,QAAQ,KAAKsD;GACbrD,UAAUoF;EACZ;CACF;CAEAC,OAAO,EAAEtF,QAAQC,YAAuC;EACtD,KAAK,MAAM,EAAEL,SAASC,cAAcI,UAClC,KAAK0D,mBAAmB9D,UAAUD,OAAO;EAG3C,KAAKqF,UAAUjF,UAAUC,SAASkD,GAAG,EAAE,CAAC,EAAEvD,QAAQa,MAAM,IAAI;CAC9D;AACF"}
|
|
1
|
+
{"version":3,"file":"message-repository.js","names":["ThreadMessage","RunConfig","generateId","ThreadMessageLike","getRepositoryContentAutoStatus","fromThreadMessageLike","ExportedMessageRepositoryItem","message","parentId","runConfig","ExportedMessageRepository","headId","messages","Array","fromArray","conv","map","m","content","idx","id","fromBranchableArray","items","options","undefined","Error","RepositoryParent","children","next","RepositoryMessage","prev","current","level","findHead","CachedValue","_value","T","func","constructor","value","dirty","MessageRepository","Map","head","root","updateLevels","newLevel","pending","length","pop","childId","childMessage","get","push","selectPathTo","performOp","newParent","child","operation","parentOrRoot","newParentOrRoot","filter","fallbackId","at","fallback","_messages","canonicalHeadId","metadata","isOptimistic","getMessages","headMessage","addOrUpdateMessage","existingItem","newItem","set","getMessage","messageId","index","deleteMessage","replacementId","replacement","delete","getBranches","evictOffBranchOptimisticMessages","previousHead","currentHead","onHeadBranch","Set","add","stale","has","switchToBranch","resetHead","clear","descendantId","export","exportItems","reverse","i","import"],"sources":["../../../src/runtime/utils/message-repository.ts"],"sourcesContent":["import type { ThreadMessage } from \"../../types/message\";\nimport type { RunConfig } from \"../../types/message\";\nimport { generateId } from \"../../utils/id\";\nimport type { ThreadMessageLike } from \"./thread-message-like\";\nimport { getRepositoryContentAutoStatus } from \"./auto-status\";\nimport { fromThreadMessageLike } from \"./thread-message-like\";\n\nexport type ExportedMessageRepositoryItem = {\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n};\n\nexport type ExportedMessageRepository = {\n headId?: string | null;\n messages: Array<{\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n }>;\n};\n\nexport const ExportedMessageRepository = {\n fromArray: (\n messages: readonly ThreadMessageLike[],\n ): ExportedMessageRepository => {\n const conv = messages.map((m) =>\n fromThreadMessageLike(\n m,\n generateId(),\n getRepositoryContentAutoStatus(m.content),\n ),\n );\n\n return {\n messages: conv.map((m, idx) => ({\n parentId: idx > 0 ? conv[idx - 1]!.id : null,\n message: m,\n })),\n };\n },\n\n fromBranchableArray: (\n items: readonly {\n message: ThreadMessageLike;\n parentId: string | null;\n }[],\n options?: { headId?: string | null },\n ): ExportedMessageRepository => {\n return {\n ...(options?.headId !== undefined\n ? { headId: options.headId }\n : undefined),\n messages: items.map(({ message, parentId }) => {\n if (!message.id) {\n throw new Error(\n \"ExportedMessageRepository.fromBranchableArray: Each message must have an 'id' field set.\",\n );\n }\n return {\n parentId,\n message: fromThreadMessageLike(\n message,\n message.id,\n getRepositoryContentAutoStatus(message.content),\n ),\n };\n }),\n };\n },\n};\n\ntype RepositoryParent = {\n children: string[];\n next: RepositoryMessage | null;\n};\n\ntype RepositoryMessage = RepositoryParent & {\n prev: RepositoryMessage | null;\n current: ThreadMessage;\n level: number;\n};\n\nconst findHead = (\n message: RepositoryMessage | RepositoryParent,\n): RepositoryMessage | null => {\n let current = message;\n while (current.next) current = current.next;\n return \"current\" in current ? current : null;\n};\n\nclass CachedValue<T> {\n private _value: T | null = null;\n\n private func: () => T;\n\n constructor(func: () => T) {\n this.func = func;\n }\n\n get value() {\n if (this._value === null) {\n this._value = this.func();\n }\n return this._value;\n }\n\n dirty() {\n this._value = null;\n }\n}\n\nexport class MessageRepository {\n private messages = new Map<string, RepositoryMessage>();\n private head: RepositoryMessage | null = null;\n private root: RepositoryParent = {\n children: [],\n next: null,\n };\n\n private updateLevels(message: RepositoryMessage, newLevel: number) {\n const pending = [{ message, level: newLevel }];\n\n while (pending.length > 0) {\n const current = pending.pop()!;\n current.message.level = current.level;\n\n for (const childId of current.message.children) {\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n pending.push({ message: childMessage, level: current.level + 1 });\n }\n }\n }\n }\n\n private selectPathTo(message: RepositoryMessage) {\n for (\n let current: RepositoryMessage | null = message;\n current;\n current = current.prev\n ) {\n (current.prev ?? this.root).next = current;\n }\n }\n\n private performOp(\n newParent: RepositoryMessage | null,\n child: RepositoryMessage,\n operation: \"cut\" | \"link\" | \"relink\",\n ) {\n const parentOrRoot = child.prev ?? this.root;\n const newParentOrRoot = newParent ?? this.root;\n\n if (operation === \"relink\" && parentOrRoot === newParentOrRoot) return;\n\n // `link` receives a fresh ID from `addOrUpdateMessage`; only `relink` can introduce a cycle.\n if (operation === \"relink\") {\n for (\n let current: RepositoryMessage | null = newParent;\n current;\n current = current.prev\n ) {\n if (current.current.id === child.current.id) {\n throw new Error(\n \"MessageRepository(performOp/relink): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui.\",\n );\n }\n }\n }\n\n if (operation !== \"link\") {\n parentOrRoot.children = parentOrRoot.children.filter(\n (m) => m !== child.current.id,\n );\n\n if (parentOrRoot.next === child) {\n const fallbackId = parentOrRoot.children.at(-1);\n const fallback = fallbackId ? this.messages.get(fallbackId) : null;\n if (fallback === undefined) {\n throw new Error(\n \"MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n parentOrRoot.next = fallback;\n }\n }\n\n if (operation !== \"cut\") {\n newParentOrRoot.children = [\n ...newParentOrRoot.children,\n child.current.id,\n ];\n\n child.prev = newParent;\n\n if (findHead(child) === this.head) {\n this.selectPathTo(child);\n } else if (newParentOrRoot.next === null) {\n newParentOrRoot.next = child;\n if (this.head === newParentOrRoot) {\n this.head = findHead(child);\n }\n }\n\n const newLevel = newParent ? newParent.level + 1 : 0;\n this.updateLevels(child, newLevel);\n }\n }\n\n private _messages = new CachedValue<readonly ThreadMessage[]>(() => {\n const messages = new Array<ThreadMessage>((this.head?.level ?? -1) + 1);\n for (let current = this.head; current; current = current.prev) {\n messages[current.level] = current.current;\n }\n return messages;\n });\n\n get headId() {\n return this.head?.current.id ?? null;\n }\n\n get canonicalHeadId() {\n // Optimistic messages are ephemeral, so persisted callers need the nearest\n // non-optimistic ancestor rather than the raw head.\n let head = this.head;\n while (head?.current.metadata?.isOptimistic) {\n head = head.prev;\n }\n return head?.current.id ?? null;\n }\n\n getMessages(headId?: string) {\n if (headId === undefined || headId === this.head?.current.id) {\n return this._messages.value;\n }\n\n const headMessage = this.messages.get(headId);\n if (!headMessage) {\n throw new Error(\n \"MessageRepository(getMessages): Head message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n\n const messages = new Array<ThreadMessage>(headMessage.level + 1);\n for (\n let current: RepositoryMessage | null = headMessage;\n current;\n current = current.prev\n ) {\n messages[current.level] = current.current;\n }\n return messages;\n }\n\n addOrUpdateMessage(parentId: string | null, message: ThreadMessage) {\n const existingItem = this.messages.get(message.id);\n const prev = parentId ? this.messages.get(parentId) : null;\n if (prev === undefined)\n throw new Error(\n \"MessageRepository(addOrUpdateMessage): Parent message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n if (existingItem) {\n existingItem.current = message;\n this.performOp(prev, existingItem, \"relink\");\n this._messages.dirty();\n return;\n }\n\n const newItem: RepositoryMessage = {\n prev,\n current: message,\n next: null,\n children: [],\n level: prev ? prev.level + 1 : 0,\n };\n\n this.messages.set(message.id, newItem);\n this.performOp(prev, newItem, \"link\");\n\n if (this.head === prev) {\n this.head = newItem;\n }\n\n this._messages.dirty();\n }\n\n getMessage(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(updateMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n return {\n parentId: message.prev?.current.id ?? null,\n message: message.current,\n index: message.level,\n };\n }\n\n deleteMessage(messageId: string, replacementId?: string | null | undefined) {\n const message = this.messages.get(messageId);\n\n if (!message)\n throw new Error(\n \"MessageRepository(deleteMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const replacement =\n replacementId === undefined\n ? message.prev\n : replacementId === null\n ? null\n : this.messages.get(replacementId);\n if (replacement === undefined)\n throw new Error(\n \"MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui.\",\n );\n\n for (const child of message.children) {\n const childMessage = this.messages.get(child);\n if (!childMessage)\n throw new Error(\n \"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui.\",\n );\n this.performOp(replacement, childMessage, \"relink\");\n }\n\n this.performOp(null, message, \"cut\");\n this.messages.delete(messageId);\n\n if (this.head === message) {\n this.head = findHead(replacement ?? this.root);\n }\n\n this._messages.dirty();\n }\n\n getBranches(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(getBranches): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const { children } = message.prev ?? this.root;\n return children;\n }\n\n /**\n * Evicts optimistic messages (`metadata.isOptimistic`) the head just moved\n * away from. Since eviction runs on every head move, the only optimistic\n * messages in the repository live on the branch the head previously pointed\n * at — so we walk just that branch rather than the whole repository. Keeps a\n * client→server id swap from leaving a phantom sibling, and drops off-branch\n * placeholders.\n */\n private evictOffBranchOptimisticMessages(\n previousHead: RepositoryMessage | null,\n currentHead: RepositoryMessage | null,\n ) {\n if (!previousHead) return;\n\n const onHeadBranch = new Set<string>();\n for (let current = currentHead; current; current = current.prev) {\n onHeadBranch.add(current.current.id);\n }\n\n const stale: string[] = [];\n for (\n let current: RepositoryMessage | null = previousHead;\n current;\n current = current.prev\n ) {\n // Stop at the first node shared with the current head branch: every\n // ancestor above it is shared too, so nothing further can be off-branch.\n if (onHeadBranch.has(current.current.id)) break;\n if (current.current.metadata?.isOptimistic) {\n stale.push(current.current.id);\n }\n }\n\n for (const id of stale) {\n // A prior deletion may have already removed this node.\n if (this.messages.has(id)) this.deleteMessage(id);\n }\n }\n\n switchToBranch(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const previousHead = this.head;\n this.selectPathTo(message);\n\n this.head = findHead(message);\n\n this.evictOffBranchOptimisticMessages(previousHead, this.head);\n\n this._messages.dirty();\n }\n\n resetHead(messageId: string | null) {\n if (messageId === null) {\n this.clear();\n return;\n }\n\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const previousHead = this.head;\n\n if (message.children.length > 0) {\n const pending = [...message.children];\n while (pending.length > 0) {\n const childId = pending.pop()!;\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n for (const descendantId of childMessage.children) {\n pending.push(descendantId);\n }\n this.messages.delete(childId);\n }\n }\n\n message.children = [];\n message.next = null;\n }\n\n this.head = message;\n this.selectPathTo(message);\n\n this.evictOffBranchOptimisticMessages(previousHead, this.head);\n\n this._messages.dirty();\n }\n\n clear(): void {\n this.messages.clear();\n this.head = null;\n this.root = {\n children: [],\n next: null,\n };\n this._messages.dirty();\n }\n\n export(): ExportedMessageRepository {\n const exportItems: ExportedMessageRepository[\"messages\"] = [];\n\n // Optimistic messages are ephemeral and never persisted. A persisted child\n // of an optimistic node is re-parented onto its nearest persisted ancestor\n // so the exported tree never references a skipped id.\n // Import and external-state conversion require parents before children, so\n // the tree is walked in pre-order rather than iterated in insertion order.\n const pending = [...this.root.children].reverse();\n while (pending.length > 0) {\n const message = this.messages.get(pending.pop()!);\n if (!message) continue;\n for (let i = message.children.length - 1; i >= 0; i--) {\n pending.push(message.children[i]!);\n }\n if (message.current.metadata?.isOptimistic) continue;\n let prev = message.prev;\n while (prev && prev.current.metadata?.isOptimistic) {\n prev = prev.prev;\n }\n exportItems.push({\n message: message.current,\n parentId: prev?.current.id ?? null,\n });\n }\n\n return {\n headId: this.canonicalHeadId,\n messages: exportItems,\n };\n }\n\n import({ headId, messages }: ExportedMessageRepository) {\n for (const { message, parentId } of messages) {\n this.addOrUpdateMessage(parentId, message);\n }\n\n this.resetHead(headId ?? messages.at(-1)?.message.id ?? null);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DataMessagePart, FileMessagePart, GenerativeUIMessagePart, ImageMessagePart, MessageStatus, MessageTiming, PartProviderMetadata, ReasoningMessagePart, SourceMessagePart, TextMessagePart, ThreadMessage, ThreadStep, ThreadUserMessagePart, ToolCallMessagePart, ToolCallMessagePartMcpMetadata, ToolCallTiming, Unstable_AudioMessagePart } from "../../types/message.js";
|
|
1
|
+
import { DataMessagePart, FileMessagePart, GenerativeUIMessagePart, ImageMessagePart, MessageModality, MessageStatus, MessageTiming, PartProviderMetadata, ReasoningMessagePart, SourceMessagePart, TextMessagePart, ThreadMessage, ThreadStep, ThreadUserMessagePart, ToolCallMessagePart, ToolCallMessagePartMcpMetadata, ToolCallTiming, Unstable_AudioMessagePart } from "../../types/message.js";
|
|
2
2
|
import { CompleteAttachment } from "../../types/attachment.js";
|
|
3
3
|
import { ReadonlyJSONObject, ReadonlyJSONValue } from "assistant-stream/utils";
|
|
4
4
|
//#region src/runtime/utils/thread-message-like.d.ts
|
|
@@ -44,6 +44,7 @@ type ThreadMessageLike = {
|
|
|
44
44
|
readonly type: "positive" | "negative";
|
|
45
45
|
};
|
|
46
46
|
readonly isOptimistic?: boolean | undefined;
|
|
47
|
+
readonly modality?: MessageModality | undefined;
|
|
47
48
|
readonly custom?: Record<string, unknown> | undefined;
|
|
48
49
|
} | undefined;
|
|
49
50
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-message-like.d.ts","names":[],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"thread-message-like.d.ts","names":[],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"mappings":";;;;KAmCK;WACM;WACA;;KAGC;WACD;WACA,4BAGD,kBACA,uBACA,oBACA,mBACA,kBACA,kBACA,0BACA,4BACA;aAEW;aACA;aACA;aACA,OAAO;aACP;aACA;aACA;aACA;aACA;aACA,oBAAoB;aACpB;MAAc;MAAe;;aAC7B,SAAS;aACT,MAAM;aACN,mBAAmB;aACnB,WAAW,YAAY;;WAGjC;WACA,YAAY;WACZ,SAAS;WACT,wBACK,KAAK;aACJ,mBAAmB,wBAAwB;;WAGjD;aAEM,iBAAiB;aACjB,gCACI;aAEJ,yBAAyB;aACzB,iBAAiB;aACjB,SAAS;aACT;eAA+B;;aAC/B;aACA,WAAW;aACX,SAAS;;;;;;cAgBb,wBACX,MAAM,mBACN,oBACA,gBAAgB,kBACf"}
|
|
@@ -61,7 +61,7 @@ const fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
|
|
|
61
61
|
const { parentId, messages, ...basePart } = part;
|
|
62
62
|
const commonProps = {
|
|
63
63
|
...basePart,
|
|
64
|
-
toolCallId: part.toolCallId
|
|
64
|
+
toolCallId: part.toolCallId || `tool-${generateId()}`,
|
|
65
65
|
...parentId !== void 0 && { parentId },
|
|
66
66
|
...messages !== void 0 && { messages }
|
|
67
67
|
};
|
|
@@ -92,7 +92,8 @@ const fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
|
|
|
92
92
|
steps: metadata?.steps ?? [],
|
|
93
93
|
...metadata?.timing && { timing: metadata.timing },
|
|
94
94
|
...metadata?.submittedFeedback && { submittedFeedback: metadata.submittedFeedback },
|
|
95
|
-
...metadata?.isOptimistic && { isOptimistic: true }
|
|
95
|
+
...metadata?.isOptimistic && { isOptimistic: true },
|
|
96
|
+
...metadata?.modality && { modality: metadata.modality }
|
|
96
97
|
}
|
|
97
98
|
};
|
|
98
99
|
case "user": return {
|
|
@@ -121,7 +122,8 @@ const fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
|
|
|
121
122
|
})),
|
|
122
123
|
metadata: {
|
|
123
124
|
custom: metadata?.custom ?? {},
|
|
124
|
-
...metadata?.isOptimistic && { isOptimistic: true }
|
|
125
|
+
...metadata?.isOptimistic && { isOptimistic: true },
|
|
126
|
+
...metadata?.modality && { modality: metadata.modality }
|
|
125
127
|
}
|
|
126
128
|
};
|
|
127
129
|
case "system":
|