@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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.js","names":["ModelContextProvider","ModelContext","Unsubscribe","Tool","notifySubscribers","notifyStateSubscribers","generateId","FrameMessage","FRAME_MESSAGE_CHANNEL","SerializedModelContext","SerializedTool","getDefaultTargetOrigin","window","location","origin","deserializeTool","serializedTool","parameters","description","disabled","undefined","type","deserializeModelContext","serialized","system","tools","Object","fromEntries","entries","map","name","tool","getAbortReason","signal","AbortSignal","reason","error","Error","AssistantFrameHost","_context","_subscribers","Set","_pendingRequests","Map","resolve","value","reject","_iframeWindow","Window","_targetOrigin","_disposed","constructor","iframeWindow","targetOrigin","handleMessage","bind","addEventListener","requestContext","event","MessageEvent","source","data","channel","message","updateContext","context","pending","get","id","result","delete","serializedContext","execute","args","abortSignal","callTool","toolName","Promise","sendRequest","T","timeout","timeoutMessage","aborted","timeoutId","ReturnType","setTimeout","onAbort","cancelToolCall","cleanup","clearTimeout","removeEventListener","set","once","postMessage","getModelContext","subscribe","callback","add","dispose","clear"],"sources":["../../../src/model-context/frame/host.ts"],"sourcesContent":["import type { ModelContextProvider, ModelContext } from \"../types\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { Tool } from \"assistant-stream\";\nimport { notifySubscribers as notifyStateSubscribers } from \"../../subscribable/subscribable\";\nimport { generateId } from \"../../utils/id\";\nimport {\n type FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n type SerializedModelContext,\n type SerializedTool,\n} from \"./types\";\n\nconst getDefaultTargetOrigin = () => window.location.origin;\n\n/**\n * Deserializes tools from JSON Schema format back to Tool objects\n */\nconst deserializeTool = (serializedTool: SerializedTool): Tool<any, any> =>\n ({\n parameters: serializedTool.parameters,\n ...(serializedTool.description && {\n description: serializedTool.description,\n }),\n ...(serializedTool.disabled !== undefined && {\n disabled: serializedTool.disabled,\n }),\n ...(serializedTool.type && { type: serializedTool.type }),\n }) as Tool<any, any>;\n\n/**\n * Deserializes a ModelContext from transmission format\n */\nconst deserializeModelContext = (\n serialized: SerializedModelContext,\n): ModelContext => ({\n ...(serialized.system !== undefined && { system: serialized.system }),\n ...(serialized.tools && {\n tools: Object.fromEntries(\n Object.entries(serialized.tools).map(([name, tool]) => [\n name,\n deserializeTool(tool),\n ]),\n ),\n }),\n});\n\nconst getAbortReason = (signal: AbortSignal): unknown => {\n if (signal.reason !== undefined) return signal.reason;\n const error = new Error(\"Tool call was aborted\");\n error.name = \"AbortError\";\n return error;\n};\n\nexport class AssistantFrameHost implements ModelContextProvider {\n private _context: ModelContext = {};\n private _subscribers = new Set<() => void>();\n private _pendingRequests = new Map<\n string,\n {\n resolve: (value: any) => void;\n reject: (error: any) => void;\n }\n >();\n private _iframeWindow: Window;\n private _targetOrigin: string;\n private _disposed = false;\n\n constructor(\n iframeWindow: Window,\n targetOrigin: string = getDefaultTargetOrigin(),\n ) {\n this._iframeWindow = iframeWindow;\n this._targetOrigin = targetOrigin;\n\n this.handleMessage = this.handleMessage.bind(this);\n window.addEventListener(\"message\", this.handleMessage);\n\n this.requestContext();\n }\n\n private handleMessage(event: MessageEvent) {\n if (this._targetOrigin !== \"*\" && event.origin !== this._targetOrigin)\n return;\n if (event.source !== this._iframeWindow) return;\n if (event.data?.channel !== FRAME_MESSAGE_CHANNEL) return;\n\n const message = event.data.message as FrameMessage;\n\n switch (message.type) {\n case \"model-context-update\": {\n this.updateContext(message.context);\n break;\n }\n\n case \"tool-result\": {\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n if (typeof message.error === \"string\") {\n pending.reject(new Error(message.error));\n } else {\n pending.resolve(message.result);\n }\n this._pendingRequests.delete(message.id);\n }\n break;\n }\n }\n }\n\n private updateContext(serializedContext: SerializedModelContext) {\n const context = deserializeModelContext(serializedContext);\n this._context = {\n ...context,\n tools:\n context.tools &&\n Object.fromEntries(\n Object.entries(context.tools).map(([name, tool]) => [\n name,\n {\n ...tool,\n execute: (args: any, context: { abortSignal: AbortSignal }) =>\n this.callTool(name, args, context.abortSignal),\n } as Tool<any, any>,\n ]),\n ),\n };\n this.notifySubscribers();\n }\n\n private callTool(\n toolName: string,\n args: any,\n abortSignal: AbortSignal,\n ): Promise<any> {\n return this.sendRequest(\n {\n type: \"tool-call\",\n id: `tool-${generateId()}`,\n toolName,\n args,\n },\n 30000,\n `Tool call \"${toolName}\" timed out`,\n abortSignal,\n );\n }\n\n private sendRequest<T extends FrameMessage & { id: string }>(\n message: T,\n timeout = 30000,\n timeoutMessage = \"Request timed out\",\n abortSignal?: AbortSignal,\n ): Promise<any> {\n if (this._disposed) {\n return Promise.reject(new Error(\"AssistantFrameHost has been disposed\"));\n }\n if (abortSignal?.aborted) {\n return Promise.reject(getAbortReason(abortSignal));\n }\n\n return new Promise((resolve, reject) => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const onAbort = () => {\n if (!abortSignal) return;\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n this.cancelToolCall(message.id);\n pending.reject(getAbortReason(abortSignal));\n this._pendingRequests.delete(message.id);\n }\n };\n const cleanup = () => {\n if (timeoutId !== undefined) clearTimeout(timeoutId);\n abortSignal?.removeEventListener(\"abort\", onAbort);\n };\n\n this._pendingRequests.set(message.id, {\n resolve: (value: any) => {\n cleanup();\n resolve(value);\n },\n reject: (error: any) => {\n cleanup();\n reject(error);\n },\n });\n\n timeoutId = setTimeout(() => {\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n this.cancelToolCall(message.id);\n pending.reject(new Error(timeoutMessage));\n this._pendingRequests.delete(message.id);\n }\n }, timeout);\n abortSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n this._iframeWindow.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message },\n this._targetOrigin,\n );\n });\n }\n\n private cancelToolCall(id: string) {\n this._iframeWindow.postMessage(\n {\n channel: FRAME_MESSAGE_CHANNEL,\n message: { type: \"tool-cancel\", id } satisfies FrameMessage,\n },\n this._targetOrigin,\n );\n }\n\n private requestContext() {\n this._iframeWindow.postMessage(\n {\n channel: FRAME_MESSAGE_CHANNEL,\n message: {\n type: \"model-context-request\",\n } as FrameMessage,\n },\n this._targetOrigin,\n );\n }\n\n private notifySubscribers() {\n notifyStateSubscribers(this._subscribers);\n }\n\n getModelContext(): ModelContext {\n return this._context;\n }\n\n subscribe(callback: () => void): Unsubscribe {\n this._subscribers.add(callback);\n return () => this._subscribers.delete(callback);\n }\n\n dispose() {\n this._disposed = true;\n window.removeEventListener(\"message\", this.handleMessage);\n this._subscribers.clear();\n const error = new Error(\"AssistantFrameHost has been disposed\");\n for (const [id, pending] of this._pendingRequests) {\n this.cancelToolCall(id);\n pending.reject(error);\n }\n this._pendingRequests.clear();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"host.js","names":["ModelContextProvider","ModelContext","Unsubscribe","Tool","notifySubscribers","notifyStateSubscribers","generateId","FrameMessage","FRAME_MESSAGE_CHANNEL","SerializedModelContext","SerializedTool","getDefaultTargetOrigin","window","location","origin","logCancellationFailure","error","console","deserializeTool","serializedTool","parameters","description","disabled","undefined","type","deserializeModelContext","serialized","system","tools","Object","fromEntries","entries","map","name","tool","getAbortReason","signal","AbortSignal","reason","Error","AssistantFrameHost","_context","_subscribers","Set","_pendingRequests","Map","resolve","value","reject","_iframeWindow","Window","_targetOrigin","_disposed","constructor","iframeWindow","targetOrigin","handleMessage","bind","requestContext","addEventListener","event","MessageEvent","source","data","channel","message","updateContext","context","pending","get","id","result","delete","serializedContext","execute","args","abortSignal","callTool","toolName","Promise","sendRequest","T","timeout","timeoutMessage","aborted","timeoutId","ReturnType","setTimeout","onAbort","cancelToolCall","cleanup","clearTimeout","removeEventListener","set","once","postMessage","onError","getModelContext","subscribe","callback","add","dispose","clear","cancellationFailed","cancellationError"],"sources":["../../../src/model-context/frame/host.ts"],"sourcesContent":["import type { ModelContextProvider, ModelContext } from \"../types\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { Tool } from \"assistant-stream\";\nimport { notifySubscribers as notifyStateSubscribers } from \"../../subscribable/subscribable\";\nimport { generateId } from \"../../utils/id\";\nimport {\n type FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n type SerializedModelContext,\n type SerializedTool,\n} from \"./types\";\n\nconst getDefaultTargetOrigin = () => window.location.origin;\n\nconst logCancellationFailure = (error: unknown) => {\n console.error(\n \"[assistant-ui] AssistantFrameHost tool cancellation could not be sent.\",\n error,\n );\n};\n\n/**\n * Deserializes tools from JSON Schema format back to Tool objects\n */\nconst deserializeTool = (serializedTool: SerializedTool): Tool<any, any> =>\n ({\n parameters: serializedTool.parameters,\n ...(serializedTool.description && {\n description: serializedTool.description,\n }),\n ...(serializedTool.disabled !== undefined && {\n disabled: serializedTool.disabled,\n }),\n ...(serializedTool.type && { type: serializedTool.type }),\n }) as Tool<any, any>;\n\n/**\n * Deserializes a ModelContext from transmission format\n */\nconst deserializeModelContext = (\n serialized: SerializedModelContext,\n): ModelContext => ({\n ...(serialized.system !== undefined && { system: serialized.system }),\n ...(serialized.tools && {\n tools: Object.fromEntries(\n Object.entries(serialized.tools).map(([name, tool]) => [\n name,\n deserializeTool(tool),\n ]),\n ),\n }),\n});\n\nconst getAbortReason = (signal: AbortSignal): unknown => {\n if (signal.reason !== undefined) return signal.reason;\n const error = new Error(\"Tool call was aborted\");\n error.name = \"AbortError\";\n return error;\n};\n\nexport class AssistantFrameHost implements ModelContextProvider {\n private _context: ModelContext = {};\n private _subscribers = new Set<() => void>();\n private _pendingRequests = new Map<\n string,\n {\n resolve: (value: any) => void;\n reject: (error: any) => void;\n }\n >();\n private _iframeWindow: Window;\n private _targetOrigin: string;\n private _disposed = false;\n\n constructor(\n iframeWindow: Window,\n targetOrigin: string = getDefaultTargetOrigin(),\n ) {\n this._iframeWindow = iframeWindow;\n this._targetOrigin = targetOrigin;\n\n this.handleMessage = this.handleMessage.bind(this);\n // A posted message cannot be delivered before this constructor returns, so\n // requesting first means a failed request leaves no listener to clean up.\n this.requestContext();\n window.addEventListener(\"message\", this.handleMessage);\n }\n\n private handleMessage(event: MessageEvent) {\n if (this._targetOrigin !== \"*\" && event.origin !== this._targetOrigin)\n return;\n if (event.source !== this._iframeWindow) return;\n if (event.data?.channel !== FRAME_MESSAGE_CHANNEL) return;\n\n const message = event.data.message as FrameMessage;\n\n switch (message.type) {\n case \"model-context-update\": {\n this.updateContext(message.context);\n break;\n }\n\n case \"tool-result\": {\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n if (typeof message.error === \"string\") {\n pending.reject(new Error(message.error));\n } else {\n pending.resolve(message.result);\n }\n this._pendingRequests.delete(message.id);\n }\n break;\n }\n }\n }\n\n private updateContext(serializedContext: SerializedModelContext) {\n const context = deserializeModelContext(serializedContext);\n this._context = {\n ...context,\n tools:\n context.tools &&\n Object.fromEntries(\n Object.entries(context.tools).map(([name, tool]) => [\n name,\n {\n ...tool,\n execute: (args: any, context: { abortSignal: AbortSignal }) =>\n this.callTool(name, args, context.abortSignal),\n } as Tool<any, any>,\n ]),\n ),\n };\n this.notifySubscribers();\n }\n\n private callTool(\n toolName: string,\n args: any,\n abortSignal: AbortSignal,\n ): Promise<any> {\n return this.sendRequest(\n {\n type: \"tool-call\",\n id: `tool-${generateId()}`,\n toolName,\n args,\n },\n 30000,\n `Tool call \"${toolName}\" timed out`,\n abortSignal,\n );\n }\n\n private sendRequest<T extends FrameMessage & { id: string }>(\n message: T,\n timeout = 30000,\n timeoutMessage = \"Request timed out\",\n abortSignal?: AbortSignal,\n ): Promise<any> {\n if (this._disposed) {\n return Promise.reject(new Error(\"AssistantFrameHost has been disposed\"));\n }\n if (abortSignal?.aborted) {\n return Promise.reject(getAbortReason(abortSignal));\n }\n\n return new Promise((resolve, reject) => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const onAbort = () => {\n if (!abortSignal) return;\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n this.cancelToolCall(message.id);\n pending.reject(getAbortReason(abortSignal));\n this._pendingRequests.delete(message.id);\n }\n };\n const cleanup = () => {\n if (timeoutId !== undefined) clearTimeout(timeoutId);\n abortSignal?.removeEventListener(\"abort\", onAbort);\n };\n\n this._pendingRequests.set(message.id, {\n resolve: (value: any) => {\n cleanup();\n resolve(value);\n },\n reject: (error: any) => {\n cleanup();\n reject(error);\n },\n });\n\n timeoutId = setTimeout(() => {\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n this.cancelToolCall(message.id);\n pending.reject(new Error(timeoutMessage));\n this._pendingRequests.delete(message.id);\n }\n }, timeout);\n abortSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n this._iframeWindow.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message },\n this._targetOrigin,\n );\n } catch (error) {\n const pending = this._pendingRequests.get(message.id);\n this._pendingRequests.delete(message.id);\n pending?.reject(error);\n }\n });\n }\n\n private cancelToolCall(\n id: string,\n onError: (error: unknown) => void = logCancellationFailure,\n ) {\n try {\n this._iframeWindow.postMessage(\n {\n channel: FRAME_MESSAGE_CHANNEL,\n message: { type: \"tool-cancel\", id } satisfies FrameMessage,\n },\n this._targetOrigin,\n );\n } catch (error) {\n onError(error);\n }\n }\n\n private requestContext() {\n this._iframeWindow.postMessage(\n {\n channel: FRAME_MESSAGE_CHANNEL,\n message: {\n type: \"model-context-request\",\n } as FrameMessage,\n },\n this._targetOrigin,\n );\n }\n\n private notifySubscribers() {\n notifyStateSubscribers(this._subscribers);\n }\n\n getModelContext(): ModelContext {\n return this._context;\n }\n\n subscribe(callback: () => void): Unsubscribe {\n this._subscribers.add(callback);\n return () => this._subscribers.delete(callback);\n }\n\n dispose() {\n this._disposed = true;\n window.removeEventListener(\"message\", this.handleMessage);\n this._subscribers.clear();\n const error = new Error(\"AssistantFrameHost has been disposed\");\n let cancellationFailed = false;\n let cancellationError: unknown;\n\n for (const [id, pending] of this._pendingRequests) {\n this._pendingRequests.delete(id);\n this.cancelToolCall(id, (error) => {\n if (!cancellationFailed) {\n cancellationFailed = true;\n cancellationError = error;\n } else {\n logCancellationFailure(error);\n }\n });\n pending.reject(error);\n }\n\n if (cancellationFailed) throw cancellationError;\n }\n}\n"],"mappings":"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"}
|
|
@@ -9,6 +9,8 @@ declare class AssistantFrameProvider {
|
|
|
9
9
|
private _targetOrigin;
|
|
10
10
|
private _strictRegistrations;
|
|
11
11
|
private _wildcardRegistrations;
|
|
12
|
+
private _startupTimer;
|
|
13
|
+
private _disposed;
|
|
12
14
|
private constructor();
|
|
13
15
|
private static getInstance;
|
|
14
16
|
private reconcileTargetOrigin;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","names":[],"sources":["../../../src/model-context/frame/provider.ts"],"mappings":";;;cAiCa;iBACI;UAEP;UACA;UACA;UAQA;UACA;UACA;UAED;
|
|
1
|
+
{"version":3,"file":"provider.d.ts","names":[],"sources":["../../../src/model-context/frame/provider.ts"],"mappings":";;;cAiCa;iBACI;UAEP;UACA;UACA;UAQA;UACA;UACA;UACA;UACA;UAED;iBAWQ;UAWP;UAsBA;UA+BM;UA8DN;UAOA;UA+BA;UAOA;UAIA;UAaA;UAkBA;UAeA;SAiCD,wBACL,UAAU,sBACV,wBACC;SA+EI"}
|
|
@@ -20,11 +20,16 @@ var AssistantFrameProvider = class AssistantFrameProvider {
|
|
|
20
20
|
_targetOrigin;
|
|
21
21
|
_strictRegistrations = 0;
|
|
22
22
|
_wildcardRegistrations = 0;
|
|
23
|
+
_startupTimer;
|
|
24
|
+
_disposed = false;
|
|
23
25
|
constructor(targetOrigin = getDefaultTargetOrigin()) {
|
|
24
26
|
this._targetOrigin = targetOrigin;
|
|
25
27
|
this.handleMessage = this.handleMessage.bind(this);
|
|
26
28
|
window.addEventListener("message", this.handleMessage);
|
|
27
|
-
setTimeout(() =>
|
|
29
|
+
this._startupTimer = setTimeout(() => {
|
|
30
|
+
this._startupTimer = void 0;
|
|
31
|
+
this.broadcastUpdate();
|
|
32
|
+
}, 0);
|
|
28
33
|
}
|
|
29
34
|
static getInstance(targetOrigin) {
|
|
30
35
|
if (!AssistantFrameProvider._instance) AssistantFrameProvider._instance = new AssistantFrameProvider(targetOrigin);
|
|
@@ -57,7 +62,9 @@ var AssistantFrameProvider = class AssistantFrameProvider {
|
|
|
57
62
|
});
|
|
58
63
|
break;
|
|
59
64
|
case "tool-call":
|
|
60
|
-
this.handleToolCall(message, event)
|
|
65
|
+
this.handleToolCall(message, event).catch((error) => {
|
|
66
|
+
console.error("[assistant-ui] AssistantFrame tool call failed.", error);
|
|
67
|
+
});
|
|
61
68
|
break;
|
|
62
69
|
case "tool-cancel": this.cancelToolCall(message.id);
|
|
63
70
|
}
|
|
@@ -89,11 +96,21 @@ var AssistantFrameProvider = class AssistantFrameProvider {
|
|
|
89
96
|
}
|
|
90
97
|
if (this._activeToolCalls.get(message.id) !== activeCall) return;
|
|
91
98
|
this._activeToolCalls.delete(message.id);
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
try {
|
|
100
|
+
this.sendMessage(event, {
|
|
101
|
+
type: "tool-result",
|
|
102
|
+
id: message.id,
|
|
103
|
+
...error !== void 0 ? { error } : { result }
|
|
104
|
+
});
|
|
105
|
+
} catch (sendError) {
|
|
106
|
+
if (error !== void 0) throw sendError;
|
|
107
|
+
console.error("[assistant-ui] AssistantFrame tool result could not be sent.", sendError);
|
|
108
|
+
this.sendMessage(event, {
|
|
109
|
+
type: "tool-result",
|
|
110
|
+
id: message.id,
|
|
111
|
+
error: "Tool result could not be sent across the frame boundary"
|
|
112
|
+
});
|
|
113
|
+
}
|
|
97
114
|
}
|
|
98
115
|
cancelToolCall(id) {
|
|
99
116
|
const activeCall = this._activeToolCalls.get(id);
|
|
@@ -154,6 +171,7 @@ var AssistantFrameProvider = class AssistantFrameProvider {
|
|
|
154
171
|
}), {});
|
|
155
172
|
}
|
|
156
173
|
broadcastUpdate() {
|
|
174
|
+
if (this._disposed) return;
|
|
157
175
|
if (window.parent && window.parent !== window) {
|
|
158
176
|
const updateMessage = {
|
|
159
177
|
type: "model-context-update",
|
|
@@ -239,6 +257,11 @@ var AssistantFrameProvider = class AssistantFrameProvider {
|
|
|
239
257
|
static dispose() {
|
|
240
258
|
if (AssistantFrameProvider._instance) {
|
|
241
259
|
const instance = AssistantFrameProvider._instance;
|
|
260
|
+
instance._disposed = true;
|
|
261
|
+
if (instance._startupTimer !== void 0) {
|
|
262
|
+
clearTimeout(instance._startupTimer);
|
|
263
|
+
instance._startupTimer = void 0;
|
|
264
|
+
}
|
|
242
265
|
window.removeEventListener("message", instance.handleMessage);
|
|
243
266
|
let cleanupFailed = false;
|
|
244
267
|
let cleanupError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","names":["ModelContextProvider","ModelContext","Unsubscribe","Tool","toJSONSchema","FrameMessage","FRAME_MESSAGE_CHANNEL","SerializedModelContext","SerializedTool","serializeTool","tool","description","parameters","undefined","disabled","type","serializeModelContext","context","system","tools","Object","fromEntries","entries","map","name","getDefaultTargetOrigin","window","location","origin","AssistantFrameProvider","_instance","_providers","Map","_providerUnsubscribes","_activeToolCalls","abortController","AbortController","event","MessageEvent","provider","_targetOrigin","_strictRegistrations","_wildcardRegistrations","constructor","targetOrigin","handleMessage","bind","addEventListener","setTimeout","broadcastUpdate","getInstance","reconcileTargetOrigin","size","Error","source","parent","data","channel","message","sendMessage","getModelContext","handleToolCall","cancelToolCall","id","Extract","resolvedTool","getTool","toolName","get","abort","activeCall","set","result","error","execute","args","toolCallId","abortSignal","signal","human","e","String","delete","cancelToolCallsForProvider","matchingCalls","Array","from","filter","sendFailed","sendError","console","postMessage","getProviders","Set","values","resolved","contexts","reduce","merged","updateMessage","removeProvider","unsubscribe","removedProvider","includes","addModelContextProvider","instance","Symbol","subscribe","cancelError","unsubscribeError","broadcastError","released","cleanupFailed","cleanupError","runCleanup","cleanup","dispose","removeEventListener","forEach","clear"],"sources":["../../../src/model-context/frame/provider.ts"],"sourcesContent":["import type { ModelContextProvider, ModelContext } from \"../types\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport { type Tool, toJSONSchema } from \"assistant-stream\";\nimport {\n type FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n type SerializedModelContext,\n type SerializedTool,\n} from \"./types\";\n\nconst serializeTool = (tool: Tool<any, any>): SerializedTool => ({\n ...(tool.description && { description: tool.description }),\n parameters: tool.parameters ? toJSONSchema(tool.parameters) : undefined,\n ...(tool.disabled !== undefined && { disabled: tool.disabled }),\n ...(tool.type && { type: tool.type }),\n});\n\nconst serializeModelContext = (\n context: ModelContext,\n): SerializedModelContext => ({\n ...(context.system !== undefined && { system: context.system }),\n ...(context.tools && {\n tools: Object.fromEntries(\n Object.entries(context.tools).map(([name, tool]) => [\n name,\n serializeTool(tool),\n ]),\n ),\n }),\n});\n\nconst getDefaultTargetOrigin = () => window.location.origin;\n\nexport class AssistantFrameProvider {\n private static _instance: AssistantFrameProvider | null = null;\n\n private _providers = new Map<symbol, ModelContextProvider>();\n private _providerUnsubscribes = new Map<symbol, Unsubscribe | undefined>();\n private _activeToolCalls = new Map<\n string,\n {\n abortController: AbortController;\n event: MessageEvent;\n provider: ModelContextProvider | undefined;\n }\n >();\n private _targetOrigin: string;\n private _strictRegistrations = 0;\n private _wildcardRegistrations = 0;\n\n private constructor(targetOrigin: string = getDefaultTargetOrigin()) {\n this._targetOrigin = targetOrigin;\n this.handleMessage = this.handleMessage.bind(this);\n window.addEventListener(\"message\", this.handleMessage);\n\n setTimeout(() => this.broadcastUpdate(), 0);\n }\n\n private static getInstance(targetOrigin?: string): AssistantFrameProvider {\n if (!AssistantFrameProvider._instance) {\n AssistantFrameProvider._instance = new AssistantFrameProvider(\n targetOrigin,\n );\n } else {\n AssistantFrameProvider._instance.reconcileTargetOrigin(targetOrigin);\n }\n return AssistantFrameProvider._instance;\n }\n\n private reconcileTargetOrigin(\n targetOrigin: string = getDefaultTargetOrigin(),\n ) {\n if (targetOrigin === this._targetOrigin) return;\n\n if (this._providers.size === 0) {\n this._targetOrigin = targetOrigin;\n return;\n }\n\n if (targetOrigin === \"*\") return;\n\n if (this._targetOrigin === \"*\") {\n this._targetOrigin = targetOrigin;\n return;\n }\n\n throw new Error(\n `AssistantFrameProvider cannot register conflicting target origins: \"${this._targetOrigin}\" and \"${targetOrigin}\"`,\n );\n }\n\n private handleMessage(event: MessageEvent) {\n if (this._targetOrigin !== \"*\" && event.origin !== this._targetOrigin)\n return;\n if (event.source !== window.parent) return;\n if (event.data?.channel !== FRAME_MESSAGE_CHANNEL) return;\n\n const message = event.data.message as FrameMessage;\n\n switch (message.type) {\n case \"model-context-request\":\n this.sendMessage(event, {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n });\n break;\n\n case \"tool-call\":\n this.handleToolCall(message, event);\n break;\n\n case \"tool-cancel\":\n this.cancelToolCall(message.id);\n break;\n }\n }\n\n private async handleToolCall(\n message: Extract<FrameMessage, { type: \"tool-call\" }>,\n event: MessageEvent,\n ) {\n const resolvedTool = this.getTool(message.toolName);\n const tool = resolvedTool?.tool;\n const abortController = new AbortController();\n this._activeToolCalls.get(message.id)?.abortController.abort();\n const activeCall = {\n abortController,\n event,\n provider: resolvedTool?.provider,\n };\n this._activeToolCalls.set(message.id, activeCall);\n\n let result: any;\n let error: string | undefined;\n\n if (!tool) {\n error = `Tool \"${message.toolName}\" not found`;\n } else {\n try {\n result = tool.execute\n ? await tool.execute(message.args, {\n toolCallId: message.id,\n abortSignal: abortController.signal,\n human: async () => {\n throw new Error(\n \"Tool human input is not supported in frame context\",\n );\n },\n })\n : undefined;\n } catch (e) {\n error = e instanceof Error ? e.message : String(e);\n }\n }\n\n if (this._activeToolCalls.get(message.id) !== activeCall) return;\n this._activeToolCalls.delete(message.id);\n\n this.sendMessage(event, {\n type: \"tool-result\",\n id: message.id,\n ...(error !== undefined ? { error } : { result }),\n });\n }\n\n private cancelToolCall(id: string) {\n const activeCall = this._activeToolCalls.get(id);\n if (!activeCall) return;\n this._activeToolCalls.delete(id);\n activeCall.abortController.abort();\n }\n\n private cancelToolCallsForProvider(provider: ModelContextProvider) {\n const matchingCalls = Array.from(this._activeToolCalls).filter(\n ([, activeCall]) => activeCall.provider === provider,\n );\n for (const [id, activeCall] of matchingCalls) {\n this._activeToolCalls.delete(id);\n activeCall.abortController.abort();\n }\n\n let sendFailed = false;\n let sendError: unknown;\n for (const [id, activeCall] of matchingCalls) {\n try {\n this.sendMessage(activeCall.event, {\n type: \"tool-result\",\n id,\n error: \"AssistantFrame tool provider has been removed\",\n });\n } catch (error) {\n if (sendFailed) {\n console.error(error);\n } else {\n sendFailed = true;\n sendError = error;\n }\n }\n }\n\n if (sendFailed) throw sendError;\n }\n\n private sendMessage(event: MessageEvent, message: FrameMessage) {\n event.source?.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message },\n { targetOrigin: event.origin },\n );\n }\n\n private getProviders() {\n return Array.from(new Set(this._providers.values()));\n }\n\n private getTool(toolName: string) {\n let resolved:\n | { provider: ModelContextProvider; tool: Tool<any, any> }\n | undefined;\n\n for (const provider of this.getProviders()) {\n const tool = provider.getModelContext().tools?.[toolName];\n if (tool) resolved = { provider, tool };\n }\n\n return resolved;\n }\n\n private getModelContext(): ModelContext {\n const contexts = this.getProviders().map((provider) =>\n provider.getModelContext(),\n );\n\n return contexts.reduce(\n (merged, context) => ({\n system: context.system\n ? merged.system\n ? `${merged.system}\\n\\n${context.system}`\n : context.system\n : merged.system,\n tools: { ...(merged.tools || {}), ...(context.tools || {}) },\n }),\n {} as ModelContext,\n );\n }\n\n private broadcastUpdate() {\n if (window.parent && window.parent !== window) {\n const updateMessage: FrameMessage = {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n };\n\n window.parent.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message: updateMessage },\n this._targetOrigin,\n );\n }\n }\n\n private removeProvider(\n id: symbol,\n origin: string,\n ): {\n unsubscribe: Unsubscribe | undefined;\n removedProvider: ModelContextProvider | undefined;\n } {\n const provider = this._providers.get(id);\n this._providers.delete(id);\n const unsubscribe = this._providerUnsubscribes.get(id);\n this._providerUnsubscribes.delete(id);\n if (origin === \"*\") {\n this._wildcardRegistrations -= 1;\n if (\n this._wildcardRegistrations === 0 &&\n this._strictRegistrations === 0\n ) {\n this._targetOrigin = getDefaultTargetOrigin();\n }\n } else {\n this._strictRegistrations -= 1;\n if (this._strictRegistrations === 0) {\n this._targetOrigin =\n this._wildcardRegistrations > 0 ? \"*\" : getDefaultTargetOrigin();\n }\n }\n const removedProvider =\n provider && !this.getProviders().includes(provider)\n ? provider\n : undefined;\n return { unsubscribe, removedProvider };\n }\n\n static addModelContextProvider(\n provider: ModelContextProvider,\n targetOrigin?: string,\n ): Unsubscribe {\n const origin = targetOrigin ?? getDefaultTargetOrigin();\n const instance = AssistantFrameProvider.getInstance(origin);\n const id = Symbol();\n instance._providers.set(id, provider);\n if (origin === \"*\") {\n instance._wildcardRegistrations += 1;\n } else {\n instance._strictRegistrations += 1;\n }\n\n try {\n const unsubscribe = provider.subscribe?.(() =>\n instance.broadcastUpdate(),\n );\n if (unsubscribe) {\n instance._providerUnsubscribes.set(id, unsubscribe);\n }\n\n instance.broadcastUpdate();\n } catch (error) {\n const { unsubscribe, removedProvider } = instance.removeProvider(\n id,\n origin,\n );\n // Rollback failures must not replace the registration error.\n try {\n if (removedProvider) {\n instance.cancelToolCallsForProvider(removedProvider);\n }\n } catch (cancelError) {\n console.error(cancelError);\n }\n try {\n unsubscribe?.();\n } catch (unsubscribeError) {\n console.error(unsubscribeError);\n }\n try {\n instance.broadcastUpdate();\n } catch (broadcastError) {\n console.error(broadcastError);\n }\n throw error;\n }\n\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const { unsubscribe, removedProvider } = instance.removeProvider(\n id,\n origin,\n );\n let cleanupFailed = false;\n let cleanupError: unknown;\n const runCleanup = (cleanup: () => void) => {\n try {\n cleanup();\n } catch (error) {\n if (cleanupFailed) {\n console.error(error);\n } else {\n cleanupFailed = true;\n cleanupError = error;\n }\n }\n };\n\n if (removedProvider) {\n runCleanup(() => instance.cancelToolCallsForProvider(removedProvider));\n }\n if (unsubscribe) runCleanup(unsubscribe);\n runCleanup(() => instance.broadcastUpdate());\n\n if (cleanupFailed) throw cleanupError;\n };\n }\n\n static dispose() {\n if (AssistantFrameProvider._instance) {\n const instance = AssistantFrameProvider._instance;\n window.removeEventListener(\"message\", instance.handleMessage);\n\n let cleanupFailed = false;\n let cleanupError: unknown;\n const runCleanup = (cleanup: () => void) => {\n try {\n cleanup();\n } catch (error) {\n if (cleanupFailed) {\n console.error(error);\n } else {\n cleanupFailed = true;\n cleanupError = error;\n }\n }\n };\n\n instance._providerUnsubscribes.forEach((unsubscribe) => {\n if (unsubscribe) runCleanup(unsubscribe);\n });\n instance._providerUnsubscribes.clear();\n instance._providers.clear();\n instance._activeToolCalls.forEach(({ abortController, event }, id) => {\n runCleanup(() => {\n abortController.abort();\n instance.sendMessage(event, {\n type: \"tool-result\",\n id,\n error: \"AssistantFrameProvider has been disposed\",\n });\n });\n });\n instance._activeToolCalls.clear();\n\n AssistantFrameProvider._instance = null;\n if (cleanupFailed) throw cleanupError;\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"provider.js","names":["ModelContextProvider","ModelContext","Unsubscribe","Tool","toJSONSchema","FrameMessage","FRAME_MESSAGE_CHANNEL","SerializedModelContext","SerializedTool","serializeTool","tool","description","parameters","undefined","disabled","type","serializeModelContext","context","system","tools","Object","fromEntries","entries","map","name","getDefaultTargetOrigin","window","location","origin","AssistantFrameProvider","_instance","_providers","Map","_providerUnsubscribes","_activeToolCalls","abortController","AbortController","event","MessageEvent","provider","_targetOrigin","_strictRegistrations","_wildcardRegistrations","_startupTimer","ReturnType","setTimeout","_disposed","constructor","targetOrigin","handleMessage","bind","addEventListener","broadcastUpdate","getInstance","reconcileTargetOrigin","size","Error","source","parent","data","channel","message","sendMessage","getModelContext","handleToolCall","catch","error","console","cancelToolCall","id","Extract","resolvedTool","getTool","toolName","get","abort","activeCall","set","result","execute","args","toolCallId","abortSignal","signal","human","e","String","delete","sendError","cancelToolCallsForProvider","matchingCalls","Array","from","filter","sendFailed","postMessage","getProviders","Set","values","resolved","contexts","reduce","merged","updateMessage","removeProvider","unsubscribe","removedProvider","includes","addModelContextProvider","instance","Symbol","subscribe","cancelError","unsubscribeError","broadcastError","released","cleanupFailed","cleanupError","runCleanup","cleanup","dispose","clearTimeout","removeEventListener","forEach","clear"],"sources":["../../../src/model-context/frame/provider.ts"],"sourcesContent":["import type { ModelContextProvider, ModelContext } from \"../types\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport { type Tool, toJSONSchema } from \"assistant-stream\";\nimport {\n type FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n type SerializedModelContext,\n type SerializedTool,\n} from \"./types\";\n\nconst serializeTool = (tool: Tool<any, any>): SerializedTool => ({\n ...(tool.description && { description: tool.description }),\n parameters: tool.parameters ? toJSONSchema(tool.parameters) : undefined,\n ...(tool.disabled !== undefined && { disabled: tool.disabled }),\n ...(tool.type && { type: tool.type }),\n});\n\nconst serializeModelContext = (\n context: ModelContext,\n): SerializedModelContext => ({\n ...(context.system !== undefined && { system: context.system }),\n ...(context.tools && {\n tools: Object.fromEntries(\n Object.entries(context.tools).map(([name, tool]) => [\n name,\n serializeTool(tool),\n ]),\n ),\n }),\n});\n\nconst getDefaultTargetOrigin = () => window.location.origin;\n\nexport class AssistantFrameProvider {\n private static _instance: AssistantFrameProvider | null = null;\n\n private _providers = new Map<symbol, ModelContextProvider>();\n private _providerUnsubscribes = new Map<symbol, Unsubscribe | undefined>();\n private _activeToolCalls = new Map<\n string,\n {\n abortController: AbortController;\n event: MessageEvent;\n provider: ModelContextProvider | undefined;\n }\n >();\n private _targetOrigin: string;\n private _strictRegistrations = 0;\n private _wildcardRegistrations = 0;\n private _startupTimer: ReturnType<typeof setTimeout> | undefined;\n private _disposed = false;\n\n private constructor(targetOrigin: string = getDefaultTargetOrigin()) {\n this._targetOrigin = targetOrigin;\n this.handleMessage = this.handleMessage.bind(this);\n window.addEventListener(\"message\", this.handleMessage);\n\n this._startupTimer = setTimeout(() => {\n this._startupTimer = undefined;\n this.broadcastUpdate();\n }, 0);\n }\n\n private static getInstance(targetOrigin?: string): AssistantFrameProvider {\n if (!AssistantFrameProvider._instance) {\n AssistantFrameProvider._instance = new AssistantFrameProvider(\n targetOrigin,\n );\n } else {\n AssistantFrameProvider._instance.reconcileTargetOrigin(targetOrigin);\n }\n return AssistantFrameProvider._instance;\n }\n\n private reconcileTargetOrigin(\n targetOrigin: string = getDefaultTargetOrigin(),\n ) {\n if (targetOrigin === this._targetOrigin) return;\n\n if (this._providers.size === 0) {\n this._targetOrigin = targetOrigin;\n return;\n }\n\n if (targetOrigin === \"*\") return;\n\n if (this._targetOrigin === \"*\") {\n this._targetOrigin = targetOrigin;\n return;\n }\n\n throw new Error(\n `AssistantFrameProvider cannot register conflicting target origins: \"${this._targetOrigin}\" and \"${targetOrigin}\"`,\n );\n }\n\n private handleMessage(event: MessageEvent) {\n if (this._targetOrigin !== \"*\" && event.origin !== this._targetOrigin)\n return;\n if (event.source !== window.parent) return;\n if (event.data?.channel !== FRAME_MESSAGE_CHANNEL) return;\n\n const message = event.data.message as FrameMessage;\n\n switch (message.type) {\n case \"model-context-request\":\n this.sendMessage(event, {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n });\n break;\n\n case \"tool-call\":\n void this.handleToolCall(message, event).catch((error: unknown) => {\n console.error(\n \"[assistant-ui] AssistantFrame tool call failed.\",\n error,\n );\n });\n break;\n\n case \"tool-cancel\":\n this.cancelToolCall(message.id);\n break;\n }\n }\n\n private async handleToolCall(\n message: Extract<FrameMessage, { type: \"tool-call\" }>,\n event: MessageEvent,\n ) {\n const resolvedTool = this.getTool(message.toolName);\n const tool = resolvedTool?.tool;\n const abortController = new AbortController();\n this._activeToolCalls.get(message.id)?.abortController.abort();\n const activeCall = {\n abortController,\n event,\n provider: resolvedTool?.provider,\n };\n this._activeToolCalls.set(message.id, activeCall);\n\n let result: any;\n let error: string | undefined;\n\n if (!tool) {\n error = `Tool \"${message.toolName}\" not found`;\n } else {\n try {\n result = tool.execute\n ? await tool.execute(message.args, {\n toolCallId: message.id,\n abortSignal: abortController.signal,\n human: async () => {\n throw new Error(\n \"Tool human input is not supported in frame context\",\n );\n },\n })\n : undefined;\n } catch (e) {\n error = e instanceof Error ? e.message : String(e);\n }\n }\n\n if (this._activeToolCalls.get(message.id) !== activeCall) return;\n this._activeToolCalls.delete(message.id);\n\n try {\n this.sendMessage(event, {\n type: \"tool-result\",\n id: message.id,\n ...(error !== undefined ? { error } : { result }),\n });\n } catch (sendError) {\n if (error !== undefined) throw sendError;\n\n console.error(\n \"[assistant-ui] AssistantFrame tool result could not be sent.\",\n sendError,\n );\n this.sendMessage(event, {\n type: \"tool-result\",\n id: message.id,\n error: \"Tool result could not be sent across the frame boundary\",\n });\n }\n }\n\n private cancelToolCall(id: string) {\n const activeCall = this._activeToolCalls.get(id);\n if (!activeCall) return;\n this._activeToolCalls.delete(id);\n activeCall.abortController.abort();\n }\n\n private cancelToolCallsForProvider(provider: ModelContextProvider) {\n const matchingCalls = Array.from(this._activeToolCalls).filter(\n ([, activeCall]) => activeCall.provider === provider,\n );\n for (const [id, activeCall] of matchingCalls) {\n this._activeToolCalls.delete(id);\n activeCall.abortController.abort();\n }\n\n let sendFailed = false;\n let sendError: unknown;\n for (const [id, activeCall] of matchingCalls) {\n try {\n this.sendMessage(activeCall.event, {\n type: \"tool-result\",\n id,\n error: \"AssistantFrame tool provider has been removed\",\n });\n } catch (error) {\n if (sendFailed) {\n console.error(error);\n } else {\n sendFailed = true;\n sendError = error;\n }\n }\n }\n\n if (sendFailed) throw sendError;\n }\n\n private sendMessage(event: MessageEvent, message: FrameMessage) {\n event.source?.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message },\n { targetOrigin: event.origin },\n );\n }\n\n private getProviders() {\n return Array.from(new Set(this._providers.values()));\n }\n\n private getTool(toolName: string) {\n let resolved:\n | { provider: ModelContextProvider; tool: Tool<any, any> }\n | undefined;\n\n for (const provider of this.getProviders()) {\n const tool = provider.getModelContext().tools?.[toolName];\n if (tool) resolved = { provider, tool };\n }\n\n return resolved;\n }\n\n private getModelContext(): ModelContext {\n const contexts = this.getProviders().map((provider) =>\n provider.getModelContext(),\n );\n\n return contexts.reduce(\n (merged, context) => ({\n system: context.system\n ? merged.system\n ? `${merged.system}\\n\\n${context.system}`\n : context.system\n : merged.system,\n tools: { ...(merged.tools || {}), ...(context.tools || {}) },\n }),\n {} as ModelContext,\n );\n }\n\n private broadcastUpdate() {\n if (this._disposed) return;\n if (window.parent && window.parent !== window) {\n const updateMessage: FrameMessage = {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n };\n\n window.parent.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message: updateMessage },\n this._targetOrigin,\n );\n }\n }\n\n private removeProvider(\n id: symbol,\n origin: string,\n ): {\n unsubscribe: Unsubscribe | undefined;\n removedProvider: ModelContextProvider | undefined;\n } {\n const provider = this._providers.get(id);\n this._providers.delete(id);\n const unsubscribe = this._providerUnsubscribes.get(id);\n this._providerUnsubscribes.delete(id);\n if (origin === \"*\") {\n this._wildcardRegistrations -= 1;\n if (\n this._wildcardRegistrations === 0 &&\n this._strictRegistrations === 0\n ) {\n this._targetOrigin = getDefaultTargetOrigin();\n }\n } else {\n this._strictRegistrations -= 1;\n if (this._strictRegistrations === 0) {\n this._targetOrigin =\n this._wildcardRegistrations > 0 ? \"*\" : getDefaultTargetOrigin();\n }\n }\n const removedProvider =\n provider && !this.getProviders().includes(provider)\n ? provider\n : undefined;\n return { unsubscribe, removedProvider };\n }\n\n static addModelContextProvider(\n provider: ModelContextProvider,\n targetOrigin?: string,\n ): Unsubscribe {\n const origin = targetOrigin ?? getDefaultTargetOrigin();\n const instance = AssistantFrameProvider.getInstance(origin);\n const id = Symbol();\n instance._providers.set(id, provider);\n if (origin === \"*\") {\n instance._wildcardRegistrations += 1;\n } else {\n instance._strictRegistrations += 1;\n }\n\n try {\n const unsubscribe = provider.subscribe?.(() =>\n instance.broadcastUpdate(),\n );\n if (unsubscribe) {\n instance._providerUnsubscribes.set(id, unsubscribe);\n }\n\n instance.broadcastUpdate();\n } catch (error) {\n const { unsubscribe, removedProvider } = instance.removeProvider(\n id,\n origin,\n );\n // Rollback failures must not replace the registration error.\n try {\n if (removedProvider) {\n instance.cancelToolCallsForProvider(removedProvider);\n }\n } catch (cancelError) {\n console.error(cancelError);\n }\n try {\n unsubscribe?.();\n } catch (unsubscribeError) {\n console.error(unsubscribeError);\n }\n try {\n instance.broadcastUpdate();\n } catch (broadcastError) {\n console.error(broadcastError);\n }\n throw error;\n }\n\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const { unsubscribe, removedProvider } = instance.removeProvider(\n id,\n origin,\n );\n let cleanupFailed = false;\n let cleanupError: unknown;\n const runCleanup = (cleanup: () => void) => {\n try {\n cleanup();\n } catch (error) {\n if (cleanupFailed) {\n console.error(error);\n } else {\n cleanupFailed = true;\n cleanupError = error;\n }\n }\n };\n\n if (removedProvider) {\n runCleanup(() => instance.cancelToolCallsForProvider(removedProvider));\n }\n if (unsubscribe) runCleanup(unsubscribe);\n runCleanup(() => instance.broadcastUpdate());\n\n if (cleanupFailed) throw cleanupError;\n };\n }\n\n static dispose() {\n if (AssistantFrameProvider._instance) {\n const instance = AssistantFrameProvider._instance;\n instance._disposed = true;\n if (instance._startupTimer !== undefined) {\n clearTimeout(instance._startupTimer);\n instance._startupTimer = undefined;\n }\n window.removeEventListener(\"message\", instance.handleMessage);\n\n let cleanupFailed = false;\n let cleanupError: unknown;\n const runCleanup = (cleanup: () => void) => {\n try {\n cleanup();\n } catch (error) {\n if (cleanupFailed) {\n console.error(error);\n } else {\n cleanupFailed = true;\n cleanupError = error;\n }\n }\n };\n\n instance._providerUnsubscribes.forEach((unsubscribe) => {\n if (unsubscribe) runCleanup(unsubscribe);\n });\n instance._providerUnsubscribes.clear();\n instance._providers.clear();\n instance._activeToolCalls.forEach(({ abortController, event }, id) => {\n runCleanup(() => {\n abortController.abort();\n instance.sendMessage(event, {\n type: \"tool-result\",\n id,\n error: \"AssistantFrameProvider has been disposed\",\n });\n });\n });\n instance._activeToolCalls.clear();\n\n AssistantFrameProvider._instance = null;\n if (cleanupFailed) throw cleanupError;\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactable-composer-metadata.d.ts","names":[],"sources":["../../src/model-context/interactable-composer-metadata.ts"],"mappings":";;;;;KAOY;EACV;EACA;EACA;;;;;;EAMA;;;;;;;KAQG;EACH;EACA;EACA;;;;;;;;;;;iBAYc,kCAAkC;EAChD;IACE;;;;;;iBAgBY,oCACd,OAAO;;iBASO,qBAAqB;;;;;;
|
|
1
|
+
{"version":3,"file":"interactable-composer-metadata.d.ts","names":[],"sources":["../../src/model-context/interactable-composer-metadata.ts"],"mappings":";;;;;KAOY;EACV;EACA;EACA;;;;;;EAMA;;;;;;;KAQG;EACH;EACA;EACA;;;;;;;;;;;iBAYc,kCAAkC;EAChD;IACE;;;;;;iBAgBY,oCACd,OAAO;;iBASO,qBAAqB;;;;;;iBAgErB,8BACd,eACA,kBACA;EAEM;;;;;;EAMA,aAAa;EACb,gBAAgB;;;;;;KAgGZ;;EAEV;EACA;;EAEA;;;;;;;;;;;;;;;;;;iBA0Bc,iCACd,mBAAmB,0BACnB,YACA,eACC;;;;;iBAwEa,oBACd,mBAAmB,0BACnB,YACA;EACG;;;;;;;;;iBAaW,iCACd,MAAM,qCACN,mBAAmB,2BAClB"}
|
|
@@ -47,15 +47,22 @@ function applyArrayUpdate(prev, update, mintId) {
|
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
const patches = update.update;
|
|
50
|
-
if (Array.isArray(patches) && patches.length > 0)
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
if (Array.isArray(patches) && patches.length > 0) {
|
|
51
|
+
const patchesById = /* @__PURE__ */ new Map();
|
|
52
|
+
for (const candidate of patches) {
|
|
53
|
+
const id = getArrayItemId(candidate);
|
|
54
|
+
if (id !== void 0 && !Number.isNaN(id) && !patchesById.has(id)) patchesById.set(id, candidate);
|
|
55
|
+
}
|
|
56
|
+
next = next.map((item) => {
|
|
57
|
+
const id = getArrayItemId(item);
|
|
58
|
+
if (id === void 0 || !isRecord(item)) return item;
|
|
59
|
+
const patch = patchesById.get(id);
|
|
60
|
+
return patch ? {
|
|
61
|
+
...item,
|
|
62
|
+
...patch
|
|
63
|
+
} : item;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
59
66
|
if (Array.isArray(update.add) && update.add.length > 0) {
|
|
60
67
|
const added = mintId ? update.add.map((item) => {
|
|
61
68
|
if (!isRecord(item) || item.id !== void 0) return item;
|
|
@@ -77,13 +84,15 @@ function applyArrayUpdate(prev, update, mintId) {
|
|
|
77
84
|
function shallowMergeInteractableState(prev, partial, options) {
|
|
78
85
|
if (!isRecord(prev) || !isRecord(partial)) return partial;
|
|
79
86
|
const baseline = isRecord(options?.arrayBaseline) ? options.arrayBaseline : prev;
|
|
80
|
-
const next =
|
|
87
|
+
const next = Object.entries(prev);
|
|
81
88
|
for (const [key, value] of Object.entries(partial)) {
|
|
82
89
|
const baseValue = baseline[key];
|
|
83
|
-
if (Array.isArray(baseValue) && isRecord(value))
|
|
84
|
-
|
|
90
|
+
if (Array.isArray(baseValue) && isRecord(value)) {
|
|
91
|
+
const mintId = options?.idFactory && (options.idKeyedFields === void 0 || options.idKeyedFields.has(key)) ? () => options.idFactory?.(key) : void 0;
|
|
92
|
+
next.push([key, applyArrayUpdate(baseValue, value, mintId)]);
|
|
93
|
+
} else next.push([key, value]);
|
|
85
94
|
}
|
|
86
|
-
return next;
|
|
95
|
+
return Object.fromEntries(next);
|
|
87
96
|
}
|
|
88
97
|
/**
|
|
89
98
|
* The top-level fields of `next` that differ from `known`, for stamping a
|
|
@@ -94,12 +103,12 @@ function shallowMergeInteractableState(prev, partial, options) {
|
|
|
94
103
|
*/
|
|
95
104
|
function shallowDiffInteractableState(known, next) {
|
|
96
105
|
if (!isRecord(known) || !isRecord(next)) return void 0;
|
|
97
|
-
for (const key of Object.keys(known)) if (!(key
|
|
98
|
-
const diff =
|
|
99
|
-
for (const [key, value] of Object.entries(next)) if (!(key
|
|
100
|
-
const changed =
|
|
106
|
+
for (const key of Object.keys(known)) if (!Object.hasOwn(next, key)) return void 0;
|
|
107
|
+
const diff = [];
|
|
108
|
+
for (const [key, value] of Object.entries(next)) if (!Object.hasOwn(known, key) || !isJSONValueEqual(known[key], value)) diff.push([key, value]);
|
|
109
|
+
const changed = diff.length;
|
|
101
110
|
if (changed === 0 || changed === Object.keys(next).length) return void 0;
|
|
102
|
-
return diff;
|
|
111
|
+
return Object.fromEntries(diff);
|
|
103
112
|
}
|
|
104
113
|
const asToolCallPart = (part) => {
|
|
105
114
|
if (!part || typeof part !== "object") return void 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactable-composer-metadata.js","names":["isJSONValueEqual","isJSONValue","isRecord","Unstable_InteractableSnapshotEntry","id","name","state","partial","SnapshotCarrierMessage","role","metadata","content","unstable_getInteractableSnapshots","message","undefined","custom","Record","items","interactables","Array","isArray","unstable_formatInteractableSnapshot","entry","JSON","stringify","interactableToolName","replace","getArrayItemId","item","applyArrayUpdate","prev","update","mintId","next","set","clear","remove","length","ids","Set","filter","has","patches","map","patch","find","candidate","add","added","shallowMergeInteractableState","options","arrayBaseline","idFactory","field","idKeyedFields","ReadonlySet","baseline","key","value","Object","entries","baseValue","shallowDiffInteractableState","known","keys","diff","changed","ToolCallLikePart","type","toolCallId","toolName","args","result","asToolCallPart","part","p","updateCallTargets","success","argsId","createAddedItemIdFactory","addedItemIds","idsByField","Map","stringIds","size","get","shift","Unstable_InteractableVersion","origin","versionsCache","WeakMap","unstable_getInteractableVersions","messages","byName","byId","cached","versions","current","msg","it","push","_id","findModelKnownState","last","gateInteractableComposerMetadata","meta","rest","gated","pending","process","env","NODE_ENV","console","warn"],"sources":["../../src/model-context/interactable-composer-metadata.ts"],"sourcesContent":["import { isJSONValueEqual } from \"../utils/json/is-json-equal\";\nimport { isJSONValue, isRecord } from \"../utils/json/is-json\";\n\n/**\n * Unstable / Experimental — the interactables API is still evolving and may change in any release.\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport type Unstable_InteractableSnapshotEntry = {\n id: string;\n name: string;\n state: unknown;\n /**\n * When true, `state` carries only the top-level fields that changed since\n * the model's last known state; omitted fields are unchanged. The first\n * snapshot of an instance is always full.\n */\n partial?: boolean | undefined;\n};\n\n/**\n * Minimal message shape needed to read snapshots and `update_*` tool calls out\n * of history. Structurally compatible with both `ThreadMessage` and the AI\n * SDK's `UIMessage`.\n */\ntype SnapshotCarrierMessage = {\n role: string;\n metadata?: unknown;\n content?: readonly unknown[] | undefined;\n};\n\n/**\n * Reads the interactable snapshots stamped on a message's\n * `metadata.custom.interactables`, or `undefined` if none. This is the read\n * half of the snapshot channel — integrations use it to surface interactable\n * state to the model (see `unstable_injectInteractableContext` in\n * `@assistant-ui/ai-sdk` for the AI SDK implementation).\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_getInteractableSnapshots(message: {\n metadata?: unknown;\n}): Unstable_InteractableSnapshotEntry[] | undefined {\n const metadata = message.metadata;\n if (!metadata || typeof metadata !== \"object\") return undefined;\n const custom = (metadata as Record<string, unknown>).custom;\n if (!custom || typeof custom !== \"object\") return undefined;\n const items = (custom as Record<string, unknown>).interactables;\n return Array.isArray(items)\n ? (items as Unstable_InteractableSnapshotEntry[])\n : undefined;\n}\n\n/**\n * Canonical model-facing wording for one snapshot entry.\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_formatInteractableSnapshot(\n entry: Unstable_InteractableSnapshotEntry,\n): string {\n if (entry.partial) {\n return `[State of \"${entry.name}\" (id: ${JSON.stringify(entry.id)}) changed — updated fields: ${JSON.stringify(entry.state)}; fields not listed are unchanged]`;\n }\n return `[Current state of \"${entry.name}\" (id: ${JSON.stringify(entry.id)}): ${JSON.stringify(entry.state)}]`;\n}\n\n/** The model-facing tool name for an interactable `name`. One tool per name. */\nexport function interactableToolName(name: string): string {\n return `update_${name.replace(/[^a-zA-Z0-9_-]/g, \"_\")}`;\n}\n\nconst getArrayItemId = (item: unknown): string | number | undefined => {\n if (!isRecord(item)) return undefined;\n const id = item.id;\n return typeof id === \"string\" || typeof id === \"number\" ? id : undefined;\n};\n\nfunction applyArrayUpdate(\n prev: unknown[],\n update: Record<string, unknown>,\n mintId?: () => string | undefined,\n) {\n let next = Array.isArray(update.set) ? [...update.set] : [...prev];\n\n if (update.clear === true) next = [];\n\n if (Array.isArray(update.remove) && update.remove.length > 0) {\n const ids = new Set(update.remove);\n next = next.filter((item) => {\n const id = getArrayItemId(item);\n return id !== undefined ? !ids.has(id) : !ids.has(item);\n });\n }\n\n const patches = update.update;\n if (Array.isArray(patches) && patches.length > 0) {\n next = next.map((item) => {\n const id = getArrayItemId(item);\n if (id === undefined || !isRecord(item)) return item;\n const patch = patches.find(\n (candidate) => isRecord(candidate) && candidate.id === id,\n );\n return patch ? { ...item, ...patch } : item;\n });\n }\n\n if (Array.isArray(update.add) && update.add.length > 0) {\n const added = mintId\n ? update.add.map((item) => {\n if (!isRecord(item) || item.id !== undefined) return item;\n const id = mintId();\n return id === undefined ? item : { ...item, id };\n })\n : update.add;\n next = [...next, ...added];\n }\n\n return next;\n}\n\n/**\n * The merge `update_*` tools apply: top-level keys replace, rest preserved.\n * Array fields also accept operation objects (`add`, `update`, `remove`,\n * `clear`, `set`) so collection edits do not need a companion manage_* tool.\n */\nexport function shallowMergeInteractableState(\n prev: unknown,\n partial: unknown,\n options?:\n | {\n arrayBaseline?: unknown;\n /**\n * Supplies ids for added items in id-keyed array fields. The live\n * execute path mints fresh ids; history folds replay ids previously\n * returned by execute.\n */\n idFactory?: (field: string) => string | undefined;\n idKeyedFields?: ReadonlySet<string>;\n }\n | undefined,\n): unknown {\n if (!isRecord(prev) || !isRecord(partial)) return partial;\n const baseline = isRecord(options?.arrayBaseline)\n ? options.arrayBaseline\n : prev;\n const next = { ...prev };\n for (const [key, value] of Object.entries(partial)) {\n const baseValue = baseline[key];\n if (Array.isArray(baseValue) && isRecord(value)) {\n const mintId =\n options?.idFactory &&\n (options.idKeyedFields === undefined || options.idKeyedFields.has(key))\n ? () => options.idFactory?.(key)\n : undefined;\n next[key] = applyArrayUpdate(baseValue, value, mintId);\n } else {\n next[key] = value;\n }\n }\n return next;\n}\n\n/**\n * The top-level fields of `next` that differ from `known`, for stamping a\n * partial snapshot. Returns `undefined` when a partial stamp has no benefit:\n * the change is not expressible as a shallow merge (non-object states, or a\n * top-level key was removed), or every field changed anyway — the caller\n * falls back to a full snapshot.\n */\nfunction shallowDiffInteractableState(\n known: unknown,\n next: unknown,\n): Record<string, unknown> | undefined {\n if (!isRecord(known) || !isRecord(next)) return undefined;\n for (const key of Object.keys(known)) {\n if (!(key in next)) return undefined;\n }\n const diff: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(next)) {\n if (!(key in known) || !isJSONValueEqual(known[key], value)) {\n diff[key] = value;\n }\n }\n const changed = Object.keys(diff).length;\n if (changed === 0 || changed === Object.keys(next).length) return undefined;\n return diff;\n}\n\ntype ToolCallLikePart = {\n type?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n result?: unknown;\n};\n\nconst asToolCallPart = (part: unknown): ToolCallLikePart | undefined => {\n if (!part || typeof part !== \"object\") return undefined;\n const p = part as ToolCallLikePart;\n return p.type === \"tool-call\" ? p : undefined;\n};\n\n/** Whether an accepted `update_*` call addressed instance `id`. */\nconst updateCallTargets = (p: ToolCallLikePart, id: string): boolean => {\n if (!p.args || typeof p.args !== \"object\") return false;\n const result = isRecord(p.result) ? p.result : undefined;\n if (result?.success === false) return false;\n if (typeof result?.id === \"string\") return result.id === id;\n const argsId = (p.args as Record<string, unknown>).id;\n return argsId === id || argsId === undefined;\n};\n\nconst createAddedItemIdFactory = (result: unknown) => {\n const value = isRecord(result) ? result.addedItemIds : undefined;\n if (!isRecord(value)) return undefined;\n\n const idsByField = new Map<string, string[]>();\n for (const [field, ids] of Object.entries(value)) {\n if (!Array.isArray(ids)) continue;\n const stringIds = ids.filter(\n (item): item is string => typeof item === \"string\",\n );\n if (stringIds.length > 0) idsByField.set(field, stringIds);\n }\n if (idsByField.size === 0) return undefined;\n\n return (field: string) => idsByField.get(field)?.shift();\n};\n\n/**\n * Unstable / Experimental — the interactables API is still evolving and may change in any release.\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport type Unstable_InteractableVersion = {\n /** The full state as of this version. */\n state: unknown;\n origin: \"create\" | \"update\" | \"user-edit\";\n /** For create/update versions, the tool call that produced this version. */\n toolCallId?: string | undefined;\n};\n\n// Without this, every mounted anchor re-folds the whole thread on each streaming\n// token, since the repository hands out a new messages array per token.\nconst versionsCache = new WeakMap<\n readonly SnapshotCarrierMessage[],\n Map<string, Map<string, Unstable_InteractableVersion[]>>\n>();\n\n/**\n * Every version of interactable `id` recorded in the thread, oldest first,\n * folded chronologically:\n *\n * - the tool call whose `toolCallId` equals `id` seeds the baseline with its\n * args (`origin: \"create\"`) — the `id: toolCallId` convention for\n * tool-created interactables,\n * - a snapshot stamped on a user message is a `\"user-edit\"` version (a full\n * snapshot replaces the state; a partial one shallow-merges),\n * - each accepted `update_*` call shallow-merges an `\"update\"` version.\n *\n * The last entry is the state the model knows. Partial snapshots and update\n * calls with no baseline to merge into are skipped.\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_getInteractableVersions(\n messages: readonly SnapshotCarrierMessage[],\n id: string,\n name: string,\n): Unstable_InteractableVersion[] {\n let byName = versionsCache.get(messages);\n if (!byName) {\n byName = new Map();\n versionsCache.set(messages, byName);\n }\n let byId = byName.get(name);\n if (!byId) {\n byId = new Map();\n byName.set(name, byId);\n }\n const cached = byId.get(id);\n if (cached) return cached;\n\n const toolName = interactableToolName(name);\n const versions: Unstable_InteractableVersion[] = [];\n const current = () => versions[versions.length - 1];\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n const entry = unstable_getInteractableSnapshots(msg)?.find(\n (it) => it.id === id,\n );\n if (!entry) continue;\n if (entry.partial) {\n const prev = current();\n if (prev) {\n versions.push({\n state: shallowMergeInteractableState(prev.state, entry.state),\n origin: \"user-edit\",\n });\n }\n } else {\n versions.push({ state: entry.state, origin: \"user-edit\" });\n }\n continue;\n }\n\n if (msg.role !== \"assistant\") continue;\n for (const part of msg.content ?? []) {\n const p = asToolCallPart(part);\n if (!p) continue;\n if (p.toolCallId === id && p.toolName === name) {\n if (p.args && typeof p.args === \"object\") {\n versions.push({ state: p.args, origin: \"create\", toolCallId: id });\n }\n } else if (p.toolName === toolName && updateCallTargets(p, id)) {\n const prev = current();\n if (prev) {\n const { id: _id, ...partial } = p.args as Record<string, unknown>;\n const idFactory = createAddedItemIdFactory(p.result);\n versions.push({\n state: idFactory\n ? shallowMergeInteractableState(prev.state, partial, {\n idFactory,\n })\n : shallowMergeInteractableState(prev.state, partial),\n origin: \"update\",\n toolCallId: p.toolCallId,\n });\n }\n }\n }\n }\n byId.set(id, versions);\n return versions;\n}\n\n/**\n * The state the model knows for interactable `id` — its latest recorded\n * version, or `undefined` when no baseline exists yet.\n */\nexport function findModelKnownState(\n messages: readonly SnapshotCarrierMessage[],\n id: string,\n name: string,\n): { state: unknown } | undefined {\n const versions = unstable_getInteractableVersions(messages, id, name);\n const last = versions[versions.length - 1];\n return last ? { state: last.state } : undefined;\n}\n\n/**\n * Snapshot gate. Stamps an interactable only when the model doesn't already\n * know its state (no baseline yet, or the live state differs from the folded\n * thread record). A change that fits a shallow merge is stamped as a partial\n * snapshot carrying just the changed fields; otherwise the full state is\n * stamped. Other metadata keys pass through untouched.\n */\nexport function gateInteractableComposerMetadata(\n meta: Record<string, unknown> | undefined,\n messages: readonly SnapshotCarrierMessage[],\n): Record<string, unknown> | undefined {\n if (!meta) return undefined;\n const { interactables, ...rest } = meta as {\n interactables?: Unstable_InteractableSnapshotEntry[];\n } & Record<string, unknown>;\n\n const gated: Record<string, unknown> = { ...rest };\n if (Array.isArray(interactables)) {\n const pending: Unstable_InteractableSnapshotEntry[] = [];\n for (const it of interactables) {\n if (process.env.NODE_ENV !== \"production\" && !isJSONValue(it.state)) {\n console.warn(\n `[Interactables] state for \"${it.name}\" (${it.id}) is not JSON-equatable ` +\n `(an undefined, NaN, Infinity, function, or symbol value?). It will be ` +\n `re-snapshotted on every send, recreating per-message growth. Use plain ` +\n `JSON values.`,\n );\n }\n const known = findModelKnownState(messages, it.id, it.name);\n if (!known) {\n pending.push({ id: it.id, name: it.name, state: it.state });\n continue;\n }\n if (isJSONValueEqual(it.state, known.state)) continue;\n const diff = shallowDiffInteractableState(known.state, it.state);\n pending.push(\n diff\n ? { id: it.id, name: it.name, state: diff, partial: true }\n : { id: it.id, name: it.name, state: it.state },\n );\n }\n if (pending.length) gated.interactables = pending;\n }\n return Object.keys(gated).length ? gated : undefined;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"interactable-composer-metadata.js","names":["isJSONValueEqual","isJSONValue","isRecord","Unstable_InteractableSnapshotEntry","id","name","state","partial","SnapshotCarrierMessage","role","metadata","content","unstable_getInteractableSnapshots","message","undefined","custom","Record","items","interactables","Array","isArray","unstable_formatInteractableSnapshot","entry","JSON","stringify","interactableToolName","replace","getArrayItemId","item","applyArrayUpdate","prev","update","mintId","next","set","clear","remove","length","ids","Set","filter","has","patches","patchesById","Map","candidate","Number","isNaN","map","patch","get","add","added","shallowMergeInteractableState","options","arrayBaseline","idFactory","field","idKeyedFields","ReadonlySet","baseline","Object","entries","key","value","baseValue","push","fromEntries","shallowDiffInteractableState","known","keys","hasOwn","diff","changed","ToolCallLikePart","type","toolCallId","toolName","args","result","asToolCallPart","part","p","updateCallTargets","success","argsId","createAddedItemIdFactory","addedItemIds","idsByField","stringIds","size","shift","Unstable_InteractableVersion","origin","versionsCache","WeakMap","unstable_getInteractableVersions","messages","byName","byId","cached","versions","current","msg","find","it","_id","findModelKnownState","last","gateInteractableComposerMetadata","meta","rest","gated","pending","process","env","NODE_ENV","console","warn"],"sources":["../../src/model-context/interactable-composer-metadata.ts"],"sourcesContent":["import { isJSONValueEqual } from \"../utils/json/is-json-equal\";\nimport { isJSONValue, isRecord } from \"../utils/json/is-json\";\n\n/**\n * Unstable / Experimental — the interactables API is still evolving and may change in any release.\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport type Unstable_InteractableSnapshotEntry = {\n id: string;\n name: string;\n state: unknown;\n /**\n * When true, `state` carries only the top-level fields that changed since\n * the model's last known state; omitted fields are unchanged. The first\n * snapshot of an instance is always full.\n */\n partial?: boolean | undefined;\n};\n\n/**\n * Minimal message shape needed to read snapshots and `update_*` tool calls out\n * of history. Structurally compatible with both `ThreadMessage` and the AI\n * SDK's `UIMessage`.\n */\ntype SnapshotCarrierMessage = {\n role: string;\n metadata?: unknown;\n content?: readonly unknown[] | undefined;\n};\n\n/**\n * Reads the interactable snapshots stamped on a message's\n * `metadata.custom.interactables`, or `undefined` if none. This is the read\n * half of the snapshot channel — integrations use it to surface interactable\n * state to the model (see `unstable_injectInteractableContext` in\n * `@assistant-ui/ai-sdk` for the AI SDK implementation).\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_getInteractableSnapshots(message: {\n metadata?: unknown;\n}): Unstable_InteractableSnapshotEntry[] | undefined {\n const metadata = message.metadata;\n if (!metadata || typeof metadata !== \"object\") return undefined;\n const custom = (metadata as Record<string, unknown>).custom;\n if (!custom || typeof custom !== \"object\") return undefined;\n const items = (custom as Record<string, unknown>).interactables;\n return Array.isArray(items)\n ? (items as Unstable_InteractableSnapshotEntry[])\n : undefined;\n}\n\n/**\n * Canonical model-facing wording for one snapshot entry.\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_formatInteractableSnapshot(\n entry: Unstable_InteractableSnapshotEntry,\n): string {\n if (entry.partial) {\n return `[State of \"${entry.name}\" (id: ${JSON.stringify(entry.id)}) changed — updated fields: ${JSON.stringify(entry.state)}; fields not listed are unchanged]`;\n }\n return `[Current state of \"${entry.name}\" (id: ${JSON.stringify(entry.id)}): ${JSON.stringify(entry.state)}]`;\n}\n\n/** The model-facing tool name for an interactable `name`. One tool per name. */\nexport function interactableToolName(name: string): string {\n return `update_${name.replace(/[^a-zA-Z0-9_-]/g, \"_\")}`;\n}\n\nconst getArrayItemId = (item: unknown): string | number | undefined => {\n if (!isRecord(item)) return undefined;\n const id = item.id;\n return typeof id === \"string\" || typeof id === \"number\" ? id : undefined;\n};\n\nfunction applyArrayUpdate(\n prev: unknown[],\n update: Record<string, unknown>,\n mintId?: () => string | undefined,\n) {\n let next = Array.isArray(update.set) ? [...update.set] : [...prev];\n\n if (update.clear === true) next = [];\n\n if (Array.isArray(update.remove) && update.remove.length > 0) {\n const ids = new Set(update.remove);\n next = next.filter((item) => {\n const id = getArrayItemId(item);\n return id !== undefined ? !ids.has(id) : !ids.has(item);\n });\n }\n\n const patches = update.update;\n if (Array.isArray(patches) && patches.length > 0) {\n const patchesById = new Map<string | number, Record<string, unknown>>();\n for (const candidate of patches) {\n const id = getArrayItemId(candidate);\n if (id !== undefined && !Number.isNaN(id) && !patchesById.has(id)) {\n patchesById.set(id, candidate as Record<string, unknown>);\n }\n }\n\n next = next.map((item) => {\n const id = getArrayItemId(item);\n if (id === undefined || !isRecord(item)) return item;\n const patch = patchesById.get(id);\n return patch ? { ...item, ...patch } : item;\n });\n }\n\n if (Array.isArray(update.add) && update.add.length > 0) {\n const added = mintId\n ? update.add.map((item) => {\n if (!isRecord(item) || item.id !== undefined) return item;\n const id = mintId();\n return id === undefined ? item : { ...item, id };\n })\n : update.add;\n next = [...next, ...added];\n }\n\n return next;\n}\n\n/**\n * The merge `update_*` tools apply: top-level keys replace, rest preserved.\n * Array fields also accept operation objects (`add`, `update`, `remove`,\n * `clear`, `set`) so collection edits do not need a companion manage_* tool.\n */\nexport function shallowMergeInteractableState(\n prev: unknown,\n partial: unknown,\n options?:\n | {\n arrayBaseline?: unknown;\n /**\n * Supplies ids for added items in id-keyed array fields. The live\n * execute path mints fresh ids; history folds replay ids previously\n * returned by execute.\n */\n idFactory?: (field: string) => string | undefined;\n idKeyedFields?: ReadonlySet<string>;\n }\n | undefined,\n): unknown {\n if (!isRecord(prev) || !isRecord(partial)) return partial;\n const baseline = isRecord(options?.arrayBaseline)\n ? options.arrayBaseline\n : prev;\n const next = Object.entries(prev);\n for (const [key, value] of Object.entries(partial)) {\n const baseValue = baseline[key];\n if (Array.isArray(baseValue) && isRecord(value)) {\n const mintId =\n options?.idFactory &&\n (options.idKeyedFields === undefined || options.idKeyedFields.has(key))\n ? () => options.idFactory?.(key)\n : undefined;\n next.push([key, applyArrayUpdate(baseValue, value, mintId)]);\n } else {\n next.push([key, value]);\n }\n }\n return Object.fromEntries(next);\n}\n\n/**\n * The top-level fields of `next` that differ from `known`, for stamping a\n * partial snapshot. Returns `undefined` when a partial stamp has no benefit:\n * the change is not expressible as a shallow merge (non-object states, or a\n * top-level key was removed), or every field changed anyway — the caller\n * falls back to a full snapshot.\n */\nfunction shallowDiffInteractableState(\n known: unknown,\n next: unknown,\n): Record<string, unknown> | undefined {\n if (!isRecord(known) || !isRecord(next)) return undefined;\n for (const key of Object.keys(known)) {\n if (!Object.hasOwn(next, key)) return undefined;\n }\n const diff: [string, unknown][] = [];\n for (const [key, value] of Object.entries(next)) {\n if (!Object.hasOwn(known, key) || !isJSONValueEqual(known[key], value)) {\n diff.push([key, value]);\n }\n }\n const changed = diff.length;\n if (changed === 0 || changed === Object.keys(next).length) return undefined;\n return Object.fromEntries(diff);\n}\n\ntype ToolCallLikePart = {\n type?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n result?: unknown;\n};\n\nconst asToolCallPart = (part: unknown): ToolCallLikePart | undefined => {\n if (!part || typeof part !== \"object\") return undefined;\n const p = part as ToolCallLikePart;\n return p.type === \"tool-call\" ? p : undefined;\n};\n\n/** Whether an accepted `update_*` call addressed instance `id`. */\nconst updateCallTargets = (p: ToolCallLikePart, id: string): boolean => {\n if (!p.args || typeof p.args !== \"object\") return false;\n const result = isRecord(p.result) ? p.result : undefined;\n if (result?.success === false) return false;\n if (typeof result?.id === \"string\") return result.id === id;\n const argsId = (p.args as Record<string, unknown>).id;\n return argsId === id || argsId === undefined;\n};\n\nconst createAddedItemIdFactory = (result: unknown) => {\n const value = isRecord(result) ? result.addedItemIds : undefined;\n if (!isRecord(value)) return undefined;\n\n const idsByField = new Map<string, string[]>();\n for (const [field, ids] of Object.entries(value)) {\n if (!Array.isArray(ids)) continue;\n const stringIds = ids.filter(\n (item): item is string => typeof item === \"string\",\n );\n if (stringIds.length > 0) idsByField.set(field, stringIds);\n }\n if (idsByField.size === 0) return undefined;\n\n return (field: string) => idsByField.get(field)?.shift();\n};\n\n/**\n * Unstable / Experimental — the interactables API is still evolving and may change in any release.\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport type Unstable_InteractableVersion = {\n /** The full state as of this version. */\n state: unknown;\n origin: \"create\" | \"update\" | \"user-edit\";\n /** For create/update versions, the tool call that produced this version. */\n toolCallId?: string | undefined;\n};\n\n// Without this, every mounted anchor re-folds the whole thread on each streaming\n// token, since the repository hands out a new messages array per token.\nconst versionsCache = new WeakMap<\n readonly SnapshotCarrierMessage[],\n Map<string, Map<string, Unstable_InteractableVersion[]>>\n>();\n\n/**\n * Every version of interactable `id` recorded in the thread, oldest first,\n * folded chronologically:\n *\n * - the tool call whose `toolCallId` equals `id` seeds the baseline with its\n * args (`origin: \"create\"`) — the `id: toolCallId` convention for\n * tool-created interactables,\n * - a snapshot stamped on a user message is a `\"user-edit\"` version (a full\n * snapshot replaces the state; a partial one shallow-merges),\n * - each accepted `update_*` call shallow-merges an `\"update\"` version.\n *\n * The last entry is the state the model knows. Partial snapshots and update\n * calls with no baseline to merge into are skipped.\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_getInteractableVersions(\n messages: readonly SnapshotCarrierMessage[],\n id: string,\n name: string,\n): Unstable_InteractableVersion[] {\n let byName = versionsCache.get(messages);\n if (!byName) {\n byName = new Map();\n versionsCache.set(messages, byName);\n }\n let byId = byName.get(name);\n if (!byId) {\n byId = new Map();\n byName.set(name, byId);\n }\n const cached = byId.get(id);\n if (cached) return cached;\n\n const toolName = interactableToolName(name);\n const versions: Unstable_InteractableVersion[] = [];\n const current = () => versions[versions.length - 1];\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n const entry = unstable_getInteractableSnapshots(msg)?.find(\n (it) => it.id === id,\n );\n if (!entry) continue;\n if (entry.partial) {\n const prev = current();\n if (prev) {\n versions.push({\n state: shallowMergeInteractableState(prev.state, entry.state),\n origin: \"user-edit\",\n });\n }\n } else {\n versions.push({ state: entry.state, origin: \"user-edit\" });\n }\n continue;\n }\n\n if (msg.role !== \"assistant\") continue;\n for (const part of msg.content ?? []) {\n const p = asToolCallPart(part);\n if (!p) continue;\n if (p.toolCallId === id && p.toolName === name) {\n if (p.args && typeof p.args === \"object\") {\n versions.push({ state: p.args, origin: \"create\", toolCallId: id });\n }\n } else if (p.toolName === toolName && updateCallTargets(p, id)) {\n const prev = current();\n if (prev) {\n const { id: _id, ...partial } = p.args as Record<string, unknown>;\n const idFactory = createAddedItemIdFactory(p.result);\n versions.push({\n state: idFactory\n ? shallowMergeInteractableState(prev.state, partial, {\n idFactory,\n })\n : shallowMergeInteractableState(prev.state, partial),\n origin: \"update\",\n toolCallId: p.toolCallId,\n });\n }\n }\n }\n }\n byId.set(id, versions);\n return versions;\n}\n\n/**\n * The state the model knows for interactable `id` — its latest recorded\n * version, or `undefined` when no baseline exists yet.\n */\nexport function findModelKnownState(\n messages: readonly SnapshotCarrierMessage[],\n id: string,\n name: string,\n): { state: unknown } | undefined {\n const versions = unstable_getInteractableVersions(messages, id, name);\n const last = versions[versions.length - 1];\n return last ? { state: last.state } : undefined;\n}\n\n/**\n * Snapshot gate. Stamps an interactable only when the model doesn't already\n * know its state (no baseline yet, or the live state differs from the folded\n * thread record). A change that fits a shallow merge is stamped as a partial\n * snapshot carrying just the changed fields; otherwise the full state is\n * stamped. Other metadata keys pass through untouched.\n */\nexport function gateInteractableComposerMetadata(\n meta: Record<string, unknown> | undefined,\n messages: readonly SnapshotCarrierMessage[],\n): Record<string, unknown> | undefined {\n if (!meta) return undefined;\n const { interactables, ...rest } = meta as {\n interactables?: Unstable_InteractableSnapshotEntry[];\n } & Record<string, unknown>;\n\n const gated: Record<string, unknown> = { ...rest };\n if (Array.isArray(interactables)) {\n const pending: Unstable_InteractableSnapshotEntry[] = [];\n for (const it of interactables) {\n if (process.env.NODE_ENV !== \"production\" && !isJSONValue(it.state)) {\n console.warn(\n `[Interactables] state for \"${it.name}\" (${it.id}) is not JSON-equatable ` +\n `(an undefined, NaN, Infinity, function, or symbol value?). It will be ` +\n `re-snapshotted on every send, recreating per-message growth. Use plain ` +\n `JSON values.`,\n );\n }\n const known = findModelKnownState(messages, it.id, it.name);\n if (!known) {\n pending.push({ id: it.id, name: it.name, state: it.state });\n continue;\n }\n if (isJSONValueEqual(it.state, known.state)) continue;\n const diff = shallowDiffInteractableState(known.state, it.state);\n pending.push(\n diff\n ? { id: it.id, name: it.name, state: diff, partial: true }\n : { id: it.id, name: it.name, state: it.state },\n );\n }\n if (pending.length) gated.interactables = pending;\n }\n return Object.keys(gated).length ? gated : undefined;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","names":[],"sources":["../../src/model-context/registry.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","names":[],"sources":["../../src/model-context/registry.ts"],"mappings":";;;;cAiBa,gCAAgC;UACnC;UACA;UACA;UACA;;EAQR,mBAAmB;EA+CnB,UAAU,uBAAuB;UAKzB;EAIR,QAAQ,cAAc,yBAAyB,SAC7C,MAAM,mBAAmB,OAAO,WAC/B,+BAA+B,OAAO;EAoBzC,eACE,iBAAiB,8BAChB;EAiCH,YACE,UAAU,uBACT"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nullProtoRecord } from "../utils/record.js";
|
|
1
2
|
import { notifySubscribers } from "../subscribable/subscribable.js";
|
|
2
3
|
import { CompositeContextProvider } from "../utils/composite-context-provider.js";
|
|
3
4
|
//#region src/model-context/registry.ts
|
|
@@ -14,7 +15,7 @@ var ModelContextRegistry = class {
|
|
|
14
15
|
getModelContext() {
|
|
15
16
|
const instructions = Array.from(this._instructions.values()).filter(Boolean);
|
|
16
17
|
const system = instructions.length > 0 ? instructions.join("\n\n") : void 0;
|
|
17
|
-
const tools =
|
|
18
|
+
const tools = nullProtoRecord();
|
|
18
19
|
for (const toolProps of this._tools.values()) {
|
|
19
20
|
const { toolName, render, ...tool } = toolProps;
|
|
20
21
|
tools[toolName] = tool;
|
|
@@ -25,10 +26,7 @@ var ModelContextRegistry = class {
|
|
|
25
26
|
tools: Object.keys(tools).length > 0 ? tools : void 0
|
|
26
27
|
};
|
|
27
28
|
if (providerContexts.system) context.system = context.system ? `${context.system}\n\n${providerContexts.system}` : providerContexts.system;
|
|
28
|
-
if (providerContexts.tools) context.tools =
|
|
29
|
-
...context.tools || {},
|
|
30
|
-
...providerContexts.tools
|
|
31
|
-
};
|
|
29
|
+
if (providerContexts.tools) context.tools = nullProtoRecord(context.tools, providerContexts.tools);
|
|
32
30
|
if (providerContexts.callSettings) context.callSettings = providerContexts.callSettings;
|
|
33
31
|
if (providerContexts.config) context.config = providerContexts.config;
|
|
34
32
|
if (providerContexts.unstable_composerMetadata) context.unstable_composerMetadata = providerContexts.unstable_composerMetadata;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","names":["Tool","ModelContext","ModelContextProvider","AssistantToolProps","AssistantInstructionsConfig","notifySubscribers","notifyStateSubscribers","CompositeContextProvider","Unsubscribe","ModelContextRegistryToolHandle","ModelContextRegistryInstructionHandle","ModelContextRegistryProviderHandle","ModelContextRegistry","_tools","Map","_instructions","_contextProviders","_subscribers","Set","constructor","subscribe","getModelContext","instructions","Array","from","values","filter","Boolean","system","length","join","undefined","tools","
|
|
1
|
+
{"version":3,"file":"registry.js","names":["Tool","ModelContext","ModelContextProvider","AssistantToolProps","AssistantInstructionsConfig","notifySubscribers","notifyStateSubscribers","CompositeContextProvider","Unsubscribe","ModelContextRegistryToolHandle","ModelContextRegistryInstructionHandle","ModelContextRegistryProviderHandle","nullProtoRecord","ModelContextRegistry","_tools","Map","_instructions","_contextProviders","_subscribers","Set","constructor","subscribe","getModelContext","instructions","Array","from","values","filter","Boolean","system","length","join","undefined","tools","toolProps","toolName","render","tool","providerContexts","context","Object","keys","callSettings","config","unstable_composerMetadata","callback","add","delete","addTool","Record","TArgs","TResult","id","Symbol","set","update","newTool","has","remove","addInstruction","instruction","disabled","newConfig","newInstruction","newDisabled","addProvider","provider","unregister","registerModelContextProvider"],"sources":["../../src/model-context/registry.ts"],"sourcesContent":["import type { Tool } from \"assistant-stream\";\nimport {\n type ModelContext,\n type ModelContextProvider,\n type AssistantToolProps,\n type AssistantInstructionsConfig,\n} from \"./types\";\nimport { notifySubscribers as notifyStateSubscribers } from \"../subscribable/subscribable\";\nimport { CompositeContextProvider } from \"../utils/composite-context-provider\";\nimport type { Unsubscribe } from \"../types/unsubscribe\";\nimport type {\n ModelContextRegistryToolHandle,\n ModelContextRegistryInstructionHandle,\n ModelContextRegistryProviderHandle,\n} from \"./registry-handles\";\nimport { nullProtoRecord } from \"../utils/record\";\n\nexport class ModelContextRegistry implements ModelContextProvider {\n private _tools = new Map<symbol, AssistantToolProps<any, any>>();\n private _instructions = new Map<symbol, string>();\n private _contextProviders = new CompositeContextProvider();\n private _subscribers = new Set<() => void>();\n\n constructor() {\n this._contextProviders.subscribe(() => {\n this.notifySubscribers();\n });\n }\n\n getModelContext(): ModelContext {\n const instructions = Array.from(this._instructions.values()).filter(\n Boolean,\n );\n\n const system =\n instructions.length > 0 ? instructions.join(\"\\n\\n\") : undefined;\n\n const tools = nullProtoRecord<Tool<any, any>>();\n for (const toolProps of this._tools.values()) {\n const { toolName, render, ...tool } = toolProps;\n tools[toolName] = tool;\n }\n\n const providerContexts = this._contextProviders.getModelContext();\n\n const context: ModelContext = {\n system,\n tools: Object.keys(tools).length > 0 ? tools : undefined,\n };\n\n if (providerContexts.system) {\n context.system = context.system\n ? `${context.system}\\n\\n${providerContexts.system}`\n : providerContexts.system;\n }\n\n if (providerContexts.tools) {\n context.tools = nullProtoRecord(context.tools, providerContexts.tools);\n }\n\n if (providerContexts.callSettings) {\n context.callSettings = providerContexts.callSettings;\n }\n\n if (providerContexts.config) {\n context.config = providerContexts.config;\n }\n\n if (providerContexts.unstable_composerMetadata) {\n context.unstable_composerMetadata =\n providerContexts.unstable_composerMetadata;\n }\n\n return context;\n }\n\n subscribe(callback: () => void): Unsubscribe {\n this._subscribers.add(callback);\n return () => this._subscribers.delete(callback);\n }\n\n private notifySubscribers(): void {\n notifyStateSubscribers(this._subscribers);\n }\n\n addTool<TArgs extends Record<string, unknown>, TResult>(\n tool: AssistantToolProps<TArgs, TResult>,\n ): ModelContextRegistryToolHandle<TArgs, TResult> {\n const id = Symbol();\n\n this._tools.set(id, tool);\n this.notifySubscribers();\n\n return {\n update: (newTool: AssistantToolProps<TArgs, TResult>) => {\n if (this._tools.has(id)) {\n this._tools.set(id, newTool);\n this.notifySubscribers();\n }\n },\n remove: () => {\n this._tools.delete(id);\n this.notifySubscribers();\n },\n };\n }\n\n addInstruction(\n config: string | AssistantInstructionsConfig,\n ): ModelContextRegistryInstructionHandle {\n const id = Symbol();\n\n const instruction =\n typeof config === \"string\" ? config : config.instruction;\n const disabled = typeof config === \"object\" ? config.disabled : false;\n\n if (!disabled) {\n this._instructions.set(id, instruction);\n this.notifySubscribers();\n }\n\n return {\n update: (newConfig: string | AssistantInstructionsConfig) => {\n const newInstruction =\n typeof newConfig === \"string\" ? newConfig : newConfig.instruction;\n const newDisabled =\n typeof newConfig === \"object\" ? newConfig.disabled : false;\n\n if (newDisabled) {\n this._instructions.delete(id);\n } else {\n this._instructions.set(id, newInstruction);\n }\n this.notifySubscribers();\n },\n remove: () => {\n this._instructions.delete(id);\n this.notifySubscribers();\n },\n };\n }\n\n addProvider(\n provider: ModelContextProvider,\n ): ModelContextRegistryProviderHandle {\n const unregister =\n this._contextProviders.registerModelContextProvider(provider);\n\n return {\n remove: unregister,\n };\n }\n}\n"],"mappings":";;;;AAiBA,IAAaa,uBAAb,MAAkE;CAChE,yBAAiB,IAAIE,IAA0C;CAC/D,gCAAwB,IAAIA,IAAoB;CAChD,oBAA4B,IAAIR,yBAAyB;CACzD,+BAAuB,IAAIY,IAAgB;CAE3CC,cAAc;EACZ,KAAKH,kBAAkBI,gBAAgB;GACrC,KAAKhB,kBAAkB;EACzB,CAAC;CACH;CAEAiB,kBAAgC;EAC9B,MAAMC,eAAeC,MAAMC,KAAK,KAAKT,cAAcU,OAAO,CAAC,CAAC,CAACC,OAC3DC,OACF;EAEA,MAAMC,SACJN,aAAaO,SAAS,IAAIP,aAAaQ,KAAK,MAAM,IAAIC,KAAAA;EAExD,MAAMC,QAAQrB,gBAAgC;EAC9C,KAAK,MAAMsB,aAAa,KAAKpB,OAAOY,OAAO,GAAG;GAC5C,MAAM,EAAES,UAAUC,QAAQ,GAAGC,SAASH;GACtCD,MAAME,YAAYE;EACpB;EAEA,MAAMC,mBAAmB,KAAKrB,kBAAkBK,gBAAgB;EAEhE,MAAMiB,UAAwB;GAC5BV;GACAI,OAAOO,OAAOC,KAAKR,KAAK,CAAC,CAACH,SAAS,IAAIG,QAAQD,KAAAA;EACjD;EAEA,IAAIM,iBAAiBT,QACnBU,QAAQV,SAASU,QAAQV,SACrB,GAAGU,QAAQV,OAAM,MAAOS,iBAAiBT,WACzCS,iBAAiBT;EAGvB,IAAIS,iBAAiBL,OACnBM,QAAQN,QAAQrB,gBAAgB2B,QAAQN,OAAOK,iBAAiBL,KAAK;EAGvE,IAAIK,iBAAiBI,cACnBH,QAAQG,eAAeJ,iBAAiBI;EAG1C,IAAIJ,iBAAiBK,QACnBJ,QAAQI,SAASL,iBAAiBK;EAGpC,IAAIL,iBAAiBM,2BACnBL,QAAQK,4BACNN,iBAAiBM;EAGrB,OAAOL;CACT;CAEAlB,UAAUwB,UAAmC;EAC3C,KAAK3B,aAAa4B,IAAID,QAAQ;EAC9B,aAAa,KAAK3B,aAAa6B,OAAOF,QAAQ;CAChD;CAEA,oBAAkC;EAChCvC,kBAAuB,KAAKY,YAAY;CAC1C;CAEA8B,QACEX,MACgD;EAChD,MAAMe,KAAKC,OAAO;EAElB,KAAKvC,OAAOwC,IAAIF,IAAIf,IAAI;EACxB,KAAKhC,kBAAkB;EAEvB,OAAO;GACLkD,SAASC,YAAgD;IACvD,IAAI,KAAK1C,OAAO2C,IAAIL,EAAE,GAAG;KACvB,KAAKtC,OAAOwC,IAAIF,IAAII,OAAO;KAC3B,KAAKnD,kBAAkB;IACzB;GACF;GACAqD,cAAc;IACZ,KAAK5C,OAAOiC,OAAOK,EAAE;IACrB,KAAK/C,kBAAkB;GACzB;EACF;CACF;CAEAsD,eACEhB,QACuC;EACvC,MAAMS,KAAKC,OAAO;EAElB,MAAMO,cACJ,OAAOjB,WAAW,WAAWA,SAASA,OAAOiB;EAG/C,IAAI,EAFa,OAAOjB,WAAW,WAAWA,OAAOkB,WAAW,QAEjD;GACb,KAAK7C,cAAcsC,IAAIF,IAAIQ,WAAW;GACtC,KAAKvD,kBAAkB;EACzB;EAEA,OAAO;GACLkD,SAASO,cAAoD;IAC3D,MAAMC,iBACJ,OAAOD,cAAc,WAAWA,YAAYA,UAAUF;IAIxD,IAFE,OAAOE,cAAc,WAAWA,UAAUD,WAAW,OAGrD,KAAK7C,cAAc+B,OAAOK,EAAE;SAE5B,KAAKpC,cAAcsC,IAAIF,IAAIW,cAAc;IAE3C,KAAK1D,kBAAkB;GACzB;GACAqD,cAAc;IACZ,KAAK1C,cAAc+B,OAAOK,EAAE;IAC5B,KAAK/C,kBAAkB;GACzB;EACF;CACF;CAEA4D,YACEC,UACoC;EAIpC,OAAO,EACLR,QAHA,KAAKzC,kBAAkBmD,6BAA6BF,QAG5CC,EACV;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/model-context/types.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/model-context/types.ts"],"mappings":";;;KAIY;EACV;EACA;EACA;EACA;EACA;EACA;EACA,UAAU;;KAGA;EACV;EACA;EACA;EACA;;KAGU;EACV;EACA;EACA,QAAQ,eAAe;EACvB,eAAe;EACf,SAAS;;;;;;EAMT,4BAA4B;;KAGlB;EACV,uBAAuB;EACvB,aAAa,yBAAyB;;KAG5B,mBACV,cAAc,yBACd,WACE,KAAK,OAAO;EACd;EACA;;KAGU;EACV;EACA;;KAGU;EACV;EACA;;cASW,qBACX,WAAW,IAAI,0BACd"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nullProtoRecord } from "../utils/record.js";
|
|
1
2
|
//#region src/model-context/types.ts
|
|
2
3
|
const stripOverwrite = (tool) => {
|
|
3
4
|
if (!tool.overwrite) return tool;
|
|
@@ -6,7 +7,7 @@ const stripOverwrite = (tool) => {
|
|
|
6
7
|
};
|
|
7
8
|
const mergeModelContexts = (configSet) => {
|
|
8
9
|
const configs = Array.from(configSet).map((c) => c.getModelContext()).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
9
|
-
const toolPriorities =
|
|
10
|
+
const toolPriorities = nullProtoRecord();
|
|
10
11
|
return configs.reduce((acc, config) => {
|
|
11
12
|
const priority = config.priority ?? 0;
|
|
12
13
|
if (config.system) {
|
|
@@ -14,7 +15,7 @@ const mergeModelContexts = (configSet) => {
|
|
|
14
15
|
else acc.system = config.system;
|
|
15
16
|
}
|
|
16
17
|
if (config.tools) for (const [name, tool] of Object.entries(config.tools)) {
|
|
17
|
-
const existing = acc.tools
|
|
18
|
+
const existing = acc.tools !== void 0 && Object.hasOwn(acc.tools, name) ? acc.tools[name] : void 0;
|
|
18
19
|
if (existing && existing !== tool) {
|
|
19
20
|
const existingPriority = toolPriorities[name];
|
|
20
21
|
if (existingPriority === priority) {
|
|
@@ -31,9 +32,9 @@ const mergeModelContexts = (configSet) => {
|
|
|
31
32
|
toolPriorities[name] = Math.max(existingPriority, priority);
|
|
32
33
|
continue;
|
|
33
34
|
}
|
|
34
|
-
if (!acc.tools) acc.tools =
|
|
35
|
+
if (!acc.tools) acc.tools = nullProtoRecord();
|
|
35
36
|
acc.tools[name] = stripOverwrite(tool);
|
|
36
|
-
toolPriorities[name]
|
|
37
|
+
if (!Object.hasOwn(toolPriorities, name)) toolPriorities[name] = priority;
|
|
37
38
|
}
|
|
38
39
|
if (config.config) acc.config = {
|
|
39
40
|
...acc.config,
|