@assistant-ui/core 0.2.22 → 0.2.23
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/thread-history.d.ts +8 -0
- package/dist/adapters/thread-history.d.ts.map +1 -1
- package/dist/internal.d.ts +3 -2
- package/dist/internal.js +3 -2
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +36 -21
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/types.d.ts.map +1 -1
- package/dist/model-context/types.js +13 -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 +1 -0
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/interactable-model-context.js +1 -0
- package/dist/react/client/interactable-model-context.js.map +1 -1
- package/dist/react/interactables-legacy/useInteractableState.js +1 -0
- package/dist/react/interactables-legacy/useInteractableState.js.map +1 -1
- package/dist/react/model-context/useInteractableState.js +1 -0
- package/dist/react/model-context/useInteractableState.js.map +1 -1
- package/dist/react/model-context/useInteractableVersions.js +1 -0
- package/dist/react/model-context/useInteractableVersions.js.map +1 -1
- package/dist/react/model-context/useToolArgsStatus.js +1 -0
- package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.js +1 -0
- package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.js +1 -0
- package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarFeedback.js +1 -0
- package/dist/react/primitive-hooks/useActionBarFeedback.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.js +1 -0
- package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarSpeak.js +1 -0
- package/dist/react/primitive-hooks/useActionBarSpeak.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarStopSpeaking.js +1 -0
- package/dist/react/primitive-hooks/useActionBarStopSpeaking.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.js +1 -0
- package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js +1 -0
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerAddAttachment.js +1 -0
- package/dist/react/primitive-hooks/useComposerAddAttachment.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.js +1 -0
- package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerDictate.js +1 -0
- package/dist/react/primitive-hooks/useComposerDictate.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.js +1 -0
- package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useEditComposerCancel.js +1 -0
- package/dist/react/primitive-hooks/useEditComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useEditComposerSend.js +1 -0
- package/dist/react/primitive-hooks/useEditComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useMessageBranching.js +1 -0
- package/dist/react/primitive-hooks/useMessageBranching.js.map +1 -1
- package/dist/react/primitive-hooks/useMessageReload.js +1 -0
- package/dist/react/primitive-hooks/useMessageReload.js.map +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.js +1 -0
- package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemArchive.js +1 -0
- package/dist/react/primitive-hooks/useThreadListItemArchive.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemDelete.js +1 -0
- package/dist/react/primitive-hooks/useThreadListItemDelete.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemTrigger.js +1 -0
- package/dist/react/primitive-hooks/useThreadListItemTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemUnarchive.js +1 -0
- package/dist/react/primitive-hooks/useThreadListItemUnarchive.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.js +1 -0
- package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListNew.js +1 -0
- package/dist/react/primitive-hooks/useThreadListNew.js.map +1 -1
- package/dist/react/providers/TextMessagePartProvider.js +1 -0
- package/dist/react/providers/TextMessagePartProvider.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +6 -4
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +31 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +11 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +12 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js +2 -1
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +75 -73
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/external-message-converter.js +1 -1
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreSharedOptions.js +1 -0
- package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
- package/dist/react/runtimes/useLocalRuntime.d.ts +0 -1
- package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
- package/dist/runtime/api/assistant-runtime.d.ts +1 -1
- package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
- package/dist/runtime/api/assistant-runtime.js +1 -1
- package/dist/runtime/api/assistant-runtime.js.map +1 -1
- package/dist/runtime/api/attachment-runtime.d.ts +1 -1
- package/dist/runtime/api/attachment-runtime.d.ts.map +1 -1
- package/dist/runtime/api/attachment-runtime.js +1 -1
- package/dist/runtime/api/attachment-runtime.js.map +1 -1
- package/dist/runtime/api/composer-runtime.d.ts +2 -2
- package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.js +2 -2
- package/dist/runtime/api/composer-runtime.js.map +1 -1
- package/dist/runtime/api/message-part-runtime.d.ts +4 -4
- package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-part-runtime.js +3 -3
- package/dist/runtime/api/message-part-runtime.js.map +1 -1
- package/dist/runtime/api/message-runtime.d.ts +1 -1
- package/dist/runtime/api/message-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-runtime.js +2 -2
- package/dist/runtime/api/message-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.d.ts +1 -1
- 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 +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +1 -1
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts +2 -2
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.js +2 -2
- package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +4 -2
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +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 +1 -1
- 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 +12 -0
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/internal.d.ts +2 -1
- package/dist/runtimes/internal.js +2 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +44 -13
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +32 -27
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +2 -0
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/no-op-composer-client.js +1 -0
- package/dist/store/clients/no-op-composer-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js +1 -0
- 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 +17 -15
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scopes/thread.d.ts +1 -0
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/dist/subscribable/subscribable.d.ts +3 -3
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/subscribable/subscribable.js +3 -3
- package/dist/subscribable/subscribable.js.map +1 -1
- package/package.json +7 -7
- package/src/adapters/thread-history.ts +8 -0
- package/src/internal.ts +1 -1
- package/src/model-context/frame/host.test.ts +47 -0
- package/src/model-context/frame/host.ts +46 -19
- package/src/model-context/types.ts +16 -6
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +15 -5
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +20 -6
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +34 -0
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +26 -5
- package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +5 -1
- package/src/react/runtimes/cloud/auiV0.ts +14 -0
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +90 -88
- package/src/react/runtimes/external-message-converter.test.ts +346 -0
- package/src/react/runtimes/external-message-converter.ts +1 -1
- package/src/react/runtimes/useLocalRuntime.test.tsx +43 -0
- package/src/runtime/api/assistant-runtime.ts +4 -1
- package/src/runtime/api/attachment-runtime.ts +8 -2
- package/src/runtime/api/composer-runtime.ts +9 -5
- package/src/runtime/api/message-part-runtime.ts +10 -3
- package/src/runtime/api/message-runtime.ts +7 -2
- package/src/runtime/api/thread-list-item-runtime.ts +7 -2
- package/src/runtime/api/thread-list-runtime.ts +10 -2
- package/src/runtime/base/base-thread-runtime-core.ts +5 -1
- package/src/runtime/base/default-edit-composer-runtime-core.ts +14 -2
- package/src/runtime/base/default-thread-composer-runtime-core.ts +11 -1
- package/src/runtime/utils/message-repository.ts +19 -13
- package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +15 -0
- package/src/runtimes/internal.ts +3 -0
- package/src/runtimes/local/local-thread-runtime-core.test.ts +596 -0
- package/src/runtimes/local/local-thread-runtime-core.ts +85 -21
- package/src/runtimes/local/should-continue.test.ts +122 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +9 -10
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +38 -32
- package/src/store/clients/model-context-client.test.ts +21 -1
- package/src/store/runtime-clients/thread-runtime-client.ts +2 -1
- package/src/store/scopes/thread.ts +1 -0
- package/src/subscribable/subscribable.ts +16 -8
- package/src/tests/MessageRepository.test.ts +12 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-position.test.ts +121 -0
- package/src/tests/auiV0Encode.test.ts +74 -0
- package/src/tests/base-composer-runtime-core.test.ts +422 -0
- package/src/tests/external-store-thread-list-runtime-core.test.ts +6 -6
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +575 -0
- package/src/tests/external-store-thread-runtime-core.test.ts +55 -1
- package/src/tests/OptimisticState-delete-crash.test.ts +0 -208
|
@@ -42,6 +42,14 @@ type ThreadHistoryAdapter = {
|
|
|
42
42
|
}>;
|
|
43
43
|
resume?(options: ChatModelRunOptions): AsyncGenerator<ChatModelRunResult, void, unknown>;
|
|
44
44
|
append(item: ExportedMessageRepositoryItem): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Rewrites a previously appended message in place, keyed by its message id.
|
|
47
|
+
* Adapters that implement this let a runtime persist a run paused for tool
|
|
48
|
+
* approval and finalize the same message once the run resumes. An update may
|
|
49
|
+
* arrive for an id whose earlier write failed; treat it as an upsert keyed
|
|
50
|
+
* on the message id rather than assuming the entry exists.
|
|
51
|
+
*/
|
|
52
|
+
update?(item: ExportedMessageRepositoryItem): Promise<void>;
|
|
45
53
|
delete?(items: ExportedMessageRepositoryItem[]): Promise<void>;
|
|
46
54
|
/** Required when used with `useAISDKRuntime` / `useChatRuntime`. */
|
|
47
55
|
withFormat?<TMessage, TStorageFormat extends Record<string, unknown>>(formatAdapter: MessageFormatAdapter<TMessage, TStorageFormat>): GenericThreadHistoryAdapter<TMessage>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-history.d.ts","names":[],"sources":["../../src/adapters/thread-history.ts"],"mappings":";;;;UAUiB,oBAAoB;EACnC;EACA;EACA;EACA,SAAS;;UAGM,kBAAkB;EACjC;EACA,SAAS;;UAGM,wBAAwB;EACvC;EACA,UAAU,kBAAkB;;UAGb,qBACf,UACA,uBAAuB;EAEvB;EACA,OAAO,MAAM,kBAAkB,YAAY;EAC3C,OACE,QAAQ,oBAAoB,kBAC3B,kBAAkB;EACrB,MAAM,SAAS;;KAGL,4BAA4B;EACtC,QAAQ,QAAQ,wBAAwB;EACxC,OAAO,MAAM,kBAAkB,YAAY;EAC3C,QACE,MAAM,kBAAkB,WACxB,yBACC;EACH,QAAQ,OAAO,kBAAkB,cAAc;EAC/C,iBACE,OAAO,kBAAkB,aACzB;IACE;IACA;MAAmB;MAAkB;;;;KAK/B;EACV,QAAQ,QACN;IACE,QAAQ;IACR;;EAGJ,QACE,SAAS,sBACR,eAAe;EAClB,OAAO,MAAM,gCAAgC;
|
|
1
|
+
{"version":3,"file":"thread-history.d.ts","names":[],"sources":["../../src/adapters/thread-history.ts"],"mappings":";;;;UAUiB,oBAAoB;EACnC;EACA;EACA;EACA,SAAS;;UAGM,kBAAkB;EACjC;EACA,SAAS;;UAGM,wBAAwB;EACvC;EACA,UAAU,kBAAkB;;UAGb,qBACf,UACA,uBAAuB;EAEvB;EACA,OAAO,MAAM,kBAAkB,YAAY;EAC3C,OACE,QAAQ,oBAAoB,kBAC3B,kBAAkB;EACrB,MAAM,SAAS;;KAGL,4BAA4B;EACtC,QAAQ,QAAQ,wBAAwB;EACxC,OAAO,MAAM,kBAAkB,YAAY;EAC3C,QACE,MAAM,kBAAkB,WACxB,yBACC;EACH,QAAQ,OAAO,kBAAkB,cAAc;EAC/C,iBACE,OAAO,kBAAkB,aACzB;IACE;IACA;MAAmB;MAAkB;;;;KAK/B;EACV,QAAQ,QACN;IACE,QAAQ;IACR;;EAGJ,QACE,SAAS,sBACR,eAAe;EAClB,OAAO,MAAM,gCAAgC;;;;;;;;EAQ7C,QAAQ,MAAM,gCAAgC;EAC9C,QAAQ,OAAO,kCAAkC;;EAEjD,YAAY,UAAU,uBAAuB,yBAC3C,eAAe,qBAAqB,UAAU,kBAC7C,4BAA4B"}
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { isCreateAttachment } from "./types/attachment.js";
|
|
2
|
-
import { getFileDataURL } from "./adapters/attachment.js";
|
|
2
|
+
import { fileMatchesAccept, getFileDataURL } from "./adapters/attachment.js";
|
|
3
3
|
import { fromThreadMessageLike } from "./runtime/utils/thread-message-like.js";
|
|
4
4
|
import { ExportedMessageRepository, ExportedMessageRepositoryItem, MessageRepository } from "./runtime/utils/message-repository.js";
|
|
5
5
|
import { consumeSuggestionResult } from "./adapters/suggestion.js";
|
|
6
|
+
import { ToolInvocationTracker } from "./runtimes/tool-invocations/ToolInvocationTracker.js";
|
|
6
7
|
import { BaseSubject, BaseSubscribable, EventSubscribable, EventSubscriptionSubject, LazyMemoizeSubject, NestedSubscribable, NestedSubscriptionSubject, SKIP_UPDATE, ShallowMemoizeSubject, Subscribable, SubscribableWithState } from "./subscribable/subscribable.js";
|
|
7
8
|
import { generateErrorMessageId, generateId, isErrorMessageId } from "./utils/id.js";
|
|
8
9
|
import { getThreadMessageText } from "./utils/text.js";
|
|
@@ -44,4 +45,4 @@ import { RemoteThreadData, RemoteThreadState, THREAD_MAPPING_ID, createThreadMap
|
|
|
44
45
|
import "./runtimes/internal.js";
|
|
45
46
|
import { ThreadListItemRuntimeBinding, ThreadRuntimeCoreBinding, ThreadRuntimeImpl, getThreadState } from "./runtime/api/thread-runtime.js";
|
|
46
47
|
import { AssistantRuntimeImpl } from "./runtime/api/assistant-runtime.js";
|
|
47
|
-
export { AssistantRuntimeImpl, AttachmentRuntimeImpl, BaseAssistantRuntimeCore, BaseComposerRuntimeCore, BaseSubject, BaseSubscribable, BaseThreadRuntimeCore, type ComposerRuntimeCoreBinding, ComposerRuntimeImpl, CompositeContextProvider, type ConverterCallback, DefaultEditComposerRuntimeCore, DefaultThreadComposerRuntimeCore, EMPTY_THREAD_CORE, EditComposerAttachmentRuntimeImpl, type EditComposerRuntimeCoreBinding, EditComposerRuntimeImpl, type EventSubscribable, EventSubscriptionSubject, ExportedMessageRepository, type ExportedMessageRepositoryItem, ExternalStoreRuntimeCore, type ExternalStoreThreadFactory, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LazyMemoizeSubject, LocalRuntimeCore, type LocalRuntimeOptionsBase, type LocalThreadFactory, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, MessageAttachmentRuntimeImpl, MessagePartRuntimeImpl, MessageRepository, MessageRuntimeImpl, type MessageStateBinding, type NestedSubscribable, NestedSubscriptionSubject, OptimisticState, ReadonlyThreadRuntimeCore, type RemoteThreadData, type RemoteThreadInitializeResponse, type RemoteThreadListOptions, type RemoteThreadState, type RuntimeExtras, SKIP_UPDATE, type SKIP_UPDATE as SKIP_UPDATE_TYPE, ShallowMemoizeSubject, type Subscribable, type SubscribableWithState, type THREAD_MAPPING_ID, ThreadComposerAttachmentRuntimeImpl, type ThreadComposerRuntimeCoreBinding, ThreadComposerRuntimeImpl, type ThreadListItemRuntimeBinding, ThreadListItemRuntimeImpl, type ThreadListItemStateBinding, type ThreadListRuntimeCoreBinding, ThreadListRuntimeImpl, ThreadMessageConverter, type ThreadRuntimeCoreBinding, ThreadRuntimeImpl, consumeSuggestionResult, createRuntimeExtras, createThreadMappingId, fromThreadMessageLike, generateErrorMessageId, generateId, getAutoStatus, getFileDataURL, getThreadData, getThreadMessageText, getThreadState, hasUpcomingMessage, httpUrlPattern, isAutoStatus, isCreateAttachment, isErrorMessageId, isJSONValue, isRecord, parseDataUrl, resolveToolApprovalResponse, shouldContinue, stableStringifyToolArgs, symbolInnerMessage, trackToolArgsKeyOrder, updateStatusReducer };
|
|
48
|
+
export { AssistantRuntimeImpl, AttachmentRuntimeImpl, BaseAssistantRuntimeCore, BaseComposerRuntimeCore, BaseSubject, BaseSubscribable, BaseThreadRuntimeCore, type ComposerRuntimeCoreBinding, ComposerRuntimeImpl, CompositeContextProvider, type ConverterCallback, DefaultEditComposerRuntimeCore, DefaultThreadComposerRuntimeCore, EMPTY_THREAD_CORE, EditComposerAttachmentRuntimeImpl, type EditComposerRuntimeCoreBinding, EditComposerRuntimeImpl, type EventSubscribable, EventSubscriptionSubject, ExportedMessageRepository, type ExportedMessageRepositoryItem, ExternalStoreRuntimeCore, type ExternalStoreThreadFactory, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LazyMemoizeSubject, LocalRuntimeCore, type LocalRuntimeOptionsBase, type LocalThreadFactory, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, MessageAttachmentRuntimeImpl, MessagePartRuntimeImpl, MessageRepository, MessageRuntimeImpl, type MessageStateBinding, type NestedSubscribable, NestedSubscriptionSubject, OptimisticState, ReadonlyThreadRuntimeCore, type RemoteThreadData, type RemoteThreadInitializeResponse, type RemoteThreadListOptions, type RemoteThreadState, type RuntimeExtras, SKIP_UPDATE, type SKIP_UPDATE as SKIP_UPDATE_TYPE, ShallowMemoizeSubject, type Subscribable, type SubscribableWithState, type THREAD_MAPPING_ID, ThreadComposerAttachmentRuntimeImpl, type ThreadComposerRuntimeCoreBinding, ThreadComposerRuntimeImpl, type ThreadListItemRuntimeBinding, ThreadListItemRuntimeImpl, type ThreadListItemStateBinding, type ThreadListRuntimeCoreBinding, ThreadListRuntimeImpl, ThreadMessageConverter, type ThreadRuntimeCoreBinding, ThreadRuntimeImpl, ToolInvocationTracker, consumeSuggestionResult, createRuntimeExtras, createThreadMappingId, fileMatchesAccept, fromThreadMessageLike, generateErrorMessageId, generateId, getAutoStatus, getFileDataURL, getThreadData, getThreadMessageText, getThreadState, hasUpcomingMessage, httpUrlPattern, isAutoStatus, isCreateAttachment, isErrorMessageId, isJSONValue, isRecord, parseDataUrl, resolveToolApprovalResponse, shouldContinue, stableStringifyToolArgs, symbolInnerMessage, trackToolArgsKeyOrder, updateStatusReducer };
|
package/dist/internal.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isJSONValue, isRecord } from "./utils/json/is-json.js";
|
|
2
2
|
import { generateErrorMessageId, generateId, isErrorMessageId } from "./utils/id.js";
|
|
3
|
-
import { getFileDataURL } from "./adapters/attachment.js";
|
|
3
|
+
import { fileMatchesAccept, getFileDataURL } from "./adapters/attachment.js";
|
|
4
4
|
import { getThreadMessageText } from "./utils/text.js";
|
|
5
5
|
import { consumeSuggestionResult } from "./adapters/suggestion.js";
|
|
6
6
|
import { fromThreadMessageLike } from "./runtime/utils/thread-message-like.js";
|
|
@@ -33,10 +33,11 @@ import { LocalThreadListRuntimeCore } from "./runtimes/local/local-thread-list-r
|
|
|
33
33
|
import { LocalRuntimeCore } from "./runtimes/local/local-runtime-core.js";
|
|
34
34
|
import { ExternalStoreThreadListRuntimeCore } from "./runtimes/external-store/external-store-thread-list-runtime-core.js";
|
|
35
35
|
import { ThreadMessageConverter } from "./runtimes/external-store/thread-message-converter.js";
|
|
36
|
+
import { ToolInvocationTracker } from "./runtimes/tool-invocations/ToolInvocationTracker.js";
|
|
36
37
|
import { ExternalStoreThreadRuntimeCore, hasUpcomingMessage } from "./runtimes/external-store/external-store-thread-runtime-core.js";
|
|
37
38
|
import { ExternalStoreRuntimeCore } from "./runtimes/external-store/external-store-runtime-core.js";
|
|
38
39
|
import { ReadonlyThreadRuntimeCore } from "./runtimes/readonly/ReadonlyThreadRuntimeCore.js";
|
|
39
40
|
import { OptimisticState } from "./runtimes/remote-thread-list/optimistic-state.js";
|
|
40
41
|
import { EMPTY_THREAD_CORE } from "./runtimes/remote-thread-list/empty-thread-core.js";
|
|
41
42
|
import { createThreadMappingId, getThreadData, updateStatusReducer } from "./runtimes/remote-thread-list/remote-thread-state.js";
|
|
42
|
-
export { AssistantRuntimeImpl, AttachmentRuntimeImpl, BaseAssistantRuntimeCore, BaseComposerRuntimeCore, BaseSubject, BaseSubscribable, BaseThreadRuntimeCore, ComposerRuntimeImpl, CompositeContextProvider, DefaultEditComposerRuntimeCore, DefaultThreadComposerRuntimeCore, EMPTY_THREAD_CORE, EditComposerAttachmentRuntimeImpl, EditComposerRuntimeImpl, EventSubscriptionSubject, ExportedMessageRepository, ExternalStoreRuntimeCore, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LazyMemoizeSubject, LocalRuntimeCore, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, MessageAttachmentRuntimeImpl, MessagePartRuntimeImpl, MessageRepository, MessageRuntimeImpl, NestedSubscriptionSubject, OptimisticState, ReadonlyThreadRuntimeCore, SKIP_UPDATE, ShallowMemoizeSubject, ThreadComposerAttachmentRuntimeImpl, ThreadComposerRuntimeImpl, ThreadListItemRuntimeImpl, ThreadListRuntimeImpl, ThreadMessageConverter, ThreadRuntimeImpl, consumeSuggestionResult, createRuntimeExtras, createThreadMappingId, fromThreadMessageLike, generateErrorMessageId, generateId, getAutoStatus, getFileDataURL, getThreadData, getThreadMessageText, getThreadState, hasUpcomingMessage, httpUrlPattern, isAutoStatus, isCreateAttachment, isErrorMessageId, isJSONValue, isRecord, parseDataUrl, resolveToolApprovalResponse, shouldContinue, stableStringifyToolArgs, symbolInnerMessage, trackToolArgsKeyOrder, updateStatusReducer };
|
|
43
|
+
export { AssistantRuntimeImpl, AttachmentRuntimeImpl, BaseAssistantRuntimeCore, BaseComposerRuntimeCore, BaseSubject, BaseSubscribable, BaseThreadRuntimeCore, ComposerRuntimeImpl, CompositeContextProvider, DefaultEditComposerRuntimeCore, DefaultThreadComposerRuntimeCore, EMPTY_THREAD_CORE, EditComposerAttachmentRuntimeImpl, EditComposerRuntimeImpl, EventSubscriptionSubject, ExportedMessageRepository, ExternalStoreRuntimeCore, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LazyMemoizeSubject, LocalRuntimeCore, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, MessageAttachmentRuntimeImpl, MessagePartRuntimeImpl, MessageRepository, MessageRuntimeImpl, NestedSubscriptionSubject, OptimisticState, ReadonlyThreadRuntimeCore, SKIP_UPDATE, ShallowMemoizeSubject, ThreadComposerAttachmentRuntimeImpl, ThreadComposerRuntimeImpl, ThreadListItemRuntimeImpl, ThreadListRuntimeImpl, ThreadMessageConverter, ThreadRuntimeImpl, ToolInvocationTracker, consumeSuggestionResult, createRuntimeExtras, createThreadMappingId, fileMatchesAccept, fromThreadMessageLike, generateErrorMessageId, generateId, getAutoStatus, getFileDataURL, getThreadData, getThreadMessageText, getThreadState, hasUpcomingMessage, httpUrlPattern, isAutoStatus, isCreateAttachment, isErrorMessageId, isJSONValue, isRecord, parseDataUrl, resolveToolApprovalResponse, shouldContinue, stableStringifyToolArgs, symbolInnerMessage, trackToolArgsKeyOrder, updateStatusReducer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","names":[],"sources":["../../../src/model-context/frame/host.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"host.d.ts","names":[],"sources":["../../../src/model-context/frame/host.ts"],"mappings":";;;cAiDa,8BAA8B;UACjC;UACA;UACA;UAOA;UACA;UACA;UACA;EAEI,YAAA,cAAc,QAAQ;UAU1B;UA6BA;UAoBA;UAkBA;UAuDA;UAYA;EAIR,mBAAmB;EAInB,UAAU,uBAAuB;EAKjC"}
|
|
@@ -16,6 +16,12 @@ const deserializeModelContext = (serialized) => ({
|
|
|
16
16
|
...serialized.system !== void 0 && { system: serialized.system },
|
|
17
17
|
...serialized.tools && { tools: Object.fromEntries(Object.entries(serialized.tools).map(([name, tool]) => [name, deserializeTool(tool)])) }
|
|
18
18
|
});
|
|
19
|
+
const getAbortReason = (signal) => {
|
|
20
|
+
if (signal.reason !== void 0) return signal.reason;
|
|
21
|
+
const error = /* @__PURE__ */ new Error("Tool call was aborted");
|
|
22
|
+
error.name = "AbortError";
|
|
23
|
+
return error;
|
|
24
|
+
};
|
|
19
25
|
var AssistantFrameHost = class {
|
|
20
26
|
_context = {};
|
|
21
27
|
_subscribers = /* @__PURE__ */ new Set();
|
|
@@ -57,49 +63,58 @@ var AssistantFrameHost = class {
|
|
|
57
63
|
...context,
|
|
58
64
|
tools: context.tools && Object.fromEntries(Object.entries(context.tools).map(([name, tool]) => [name, {
|
|
59
65
|
...tool,
|
|
60
|
-
execute: (args) => this.callTool(name, args)
|
|
66
|
+
execute: (args, context) => this.callTool(name, args, context.abortSignal)
|
|
61
67
|
}]))
|
|
62
68
|
};
|
|
63
69
|
this.notifySubscribers();
|
|
64
70
|
}
|
|
65
|
-
callTool(toolName, args) {
|
|
71
|
+
callTool(toolName, args, abortSignal) {
|
|
66
72
|
return this.sendRequest({
|
|
67
73
|
type: "tool-call",
|
|
68
74
|
id: `tool-${this._requestCounter++}`,
|
|
69
75
|
toolName,
|
|
70
76
|
args
|
|
71
|
-
}, 3e4, `Tool call "${toolName}" timed out
|
|
77
|
+
}, 3e4, `Tool call "${toolName}" timed out`, abortSignal);
|
|
72
78
|
}
|
|
73
|
-
sendRequest(message, timeout = 3e4, timeoutMessage = "Request timed out") {
|
|
79
|
+
sendRequest(message, timeout = 3e4, timeoutMessage = "Request timed out", abortSignal) {
|
|
74
80
|
if (this._disposed) return Promise.reject(/* @__PURE__ */ new Error("AssistantFrameHost has been disposed"));
|
|
81
|
+
if (abortSignal?.aborted) return Promise.reject(getAbortReason(abortSignal));
|
|
75
82
|
return new Promise((resolve, reject) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
});
|
|
80
|
-
this._iframeWindow.postMessage({
|
|
81
|
-
channel: FRAME_MESSAGE_CHANNEL,
|
|
82
|
-
message
|
|
83
|
-
}, this._targetOrigin);
|
|
84
|
-
const timeoutId = setTimeout(() => {
|
|
83
|
+
let timeoutId;
|
|
84
|
+
const onAbort = () => {
|
|
85
|
+
if (!abortSignal) return;
|
|
85
86
|
const pending = this._pendingRequests.get(message.id);
|
|
86
87
|
if (pending) {
|
|
87
|
-
pending.reject(
|
|
88
|
+
pending.reject(getAbortReason(abortSignal));
|
|
88
89
|
this._pendingRequests.delete(message.id);
|
|
89
90
|
}
|
|
90
|
-
}
|
|
91
|
-
const
|
|
92
|
-
|
|
91
|
+
};
|
|
92
|
+
const cleanup = () => {
|
|
93
|
+
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
94
|
+
abortSignal?.removeEventListener("abort", onAbort);
|
|
95
|
+
};
|
|
93
96
|
this._pendingRequests.set(message.id, {
|
|
94
97
|
resolve: (value) => {
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
cleanup();
|
|
99
|
+
resolve(value);
|
|
97
100
|
},
|
|
98
101
|
reject: (error) => {
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
cleanup();
|
|
103
|
+
reject(error);
|
|
101
104
|
}
|
|
102
105
|
});
|
|
106
|
+
timeoutId = setTimeout(() => {
|
|
107
|
+
const pending = this._pendingRequests.get(message.id);
|
|
108
|
+
if (pending) {
|
|
109
|
+
pending.reject(new Error(timeoutMessage));
|
|
110
|
+
this._pendingRequests.delete(message.id);
|
|
111
|
+
}
|
|
112
|
+
}, timeout);
|
|
113
|
+
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
114
|
+
this._iframeWindow.postMessage({
|
|
115
|
+
channel: FRAME_MESSAGE_CHANNEL,
|
|
116
|
+
message
|
|
117
|
+
}, this._targetOrigin);
|
|
103
118
|
});
|
|
104
119
|
}
|
|
105
120
|
requestContext() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.js","names":["ModelContextProvider","ModelContext","Unsubscribe","Tool","FrameMessage","FRAME_MESSAGE_CHANNEL","SerializedModelContext","SerializedTool","deserializeTool","serializedTool","parameters","description","disabled","undefined","type","deserializeModelContext","serialized","system","tools","Object","fromEntries","entries","map","name","tool","AssistantFrameHost","_context","_subscribers","Set","_pendingRequests","Map","resolve","value","reject","error","_requestCounter","_iframeWindow","Window","_targetOrigin","_disposed","constructor","iframeWindow","targetOrigin","handleMessage","bind","window","addEventListener","requestContext","event","MessageEvent","origin","source","data","channel","message","updateContext","context","pending","get","id","Error","result","delete","serializedContext","execute","args","callTool","notifySubscribers","toolName","Promise","sendRequest","T","timeout","timeoutMessage","set","postMessage","timeoutId","setTimeout","originalResolve","originalReject","clearTimeout","forEach","callback","getModelContext","subscribe","add","dispose","removeEventListener","clear","values"],"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 {\n type FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n type SerializedModelContext,\n type SerializedTool,\n} from \"./types\";\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\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 _requestCounter = 0;\n private _iframeWindow: Window;\n private _targetOrigin: string;\n private _disposed = false;\n\n constructor(iframeWindow: Window, targetOrigin: string = \"*\") {\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 (message.error) {\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) => this.callTool(name, args),\n } as Tool<any, any>,\n ]),\n ),\n };\n this.notifySubscribers();\n }\n\n private callTool(toolName: string, args: any): Promise<any> {\n return this.sendRequest(\n {\n type: \"tool-call\",\n id: `tool-${this._requestCounter++}`,\n toolName,\n args,\n },\n 30000,\n `Tool call \"${toolName}\" timed out`,\n );\n }\n\n private sendRequest<T extends FrameMessage & { id: string }>(\n message: T,\n timeout = 30000,\n timeoutMessage = \"Request timed out\",\n ): Promise<any> {\n if (this._disposed) {\n return Promise.reject(new Error(\"AssistantFrameHost has been disposed\"));\n }\n\n return new Promise((resolve, reject) => {\n this._pendingRequests.set(message.id, { resolve, reject });\n\n this._iframeWindow.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message },\n this._targetOrigin,\n );\n\n const timeoutId = setTimeout(() => {\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n pending.reject(new Error(timeoutMessage));\n this._pendingRequests.delete(message.id);\n }\n }, timeout);\n\n const originalResolve = this._pendingRequests.get(message.id)!.resolve;\n const originalReject = this._pendingRequests.get(message.id)!.reject;\n\n this._pendingRequests.set(message.id, {\n resolve: (value: any) => {\n clearTimeout(timeoutId);\n originalResolve(value);\n },\n reject: (error: any) => {\n clearTimeout(timeoutId);\n originalReject(error);\n },\n });\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 this._subscribers.forEach((callback) => callback());\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 pending of this._pendingRequests.values()) {\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","FrameMessage","FRAME_MESSAGE_CHANNEL","SerializedModelContext","SerializedTool","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","_requestCounter","_iframeWindow","Window","_targetOrigin","_disposed","constructor","iframeWindow","targetOrigin","handleMessage","bind","window","addEventListener","requestContext","event","MessageEvent","origin","source","data","channel","message","updateContext","context","pending","get","id","result","delete","serializedContext","execute","args","abortSignal","callTool","notifySubscribers","toolName","Promise","sendRequest","T","timeout","timeoutMessage","aborted","timeoutId","ReturnType","setTimeout","onAbort","cleanup","clearTimeout","removeEventListener","set","once","postMessage","forEach","callback","getModelContext","subscribe","add","dispose","clear","values"],"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 {\n type FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n type SerializedModelContext,\n type SerializedTool,\n} from \"./types\";\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 _requestCounter = 0;\n private _iframeWindow: Window;\n private _targetOrigin: string;\n private _disposed = false;\n\n constructor(iframeWindow: Window, targetOrigin: string = \"*\") {\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 (message.error) {\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-${this._requestCounter++}`,\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 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 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 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 this._subscribers.forEach((callback) => callback());\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 pending of this._pendingRequests.values()) {\n pending.reject(error);\n }\n this._pendingRequests.clear();\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/model-context/types.ts"],"mappings":";;;KAGY;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;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/model-context/types.ts"],"mappings":";;;KAGY;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,4 +1,9 @@
|
|
|
1
1
|
//#region src/model-context/types.ts
|
|
2
|
+
const stripOverwrite = (tool) => {
|
|
3
|
+
if (!tool.overwrite) return tool;
|
|
4
|
+
const { overwrite: _, ...rest } = tool;
|
|
5
|
+
return rest;
|
|
6
|
+
};
|
|
2
7
|
const mergeModelContexts = (configSet) => {
|
|
3
8
|
const configs = Array.from(configSet).map((c) => c.getModelContext()).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
4
9
|
const toolPriorities = {};
|
|
@@ -10,18 +15,22 @@ const mergeModelContexts = (configSet) => {
|
|
|
10
15
|
const existing = acc.tools?.[name];
|
|
11
16
|
if (existing && existing !== tool) {
|
|
12
17
|
const existingPriority = toolPriorities[name];
|
|
13
|
-
if (existingPriority === priority)
|
|
18
|
+
if (existingPriority === priority) {
|
|
19
|
+
if (!tool.overwrite) throw new Error(`You tried to define a tool with the name ${name}, but it already exists.`);
|
|
20
|
+
acc.tools[name] = stripOverwrite(tool);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
14
23
|
const higherPriorityTool = existingPriority > priority ? existing : tool;
|
|
15
24
|
const lowerPriorityTool = existingPriority > priority ? tool : existing;
|
|
16
|
-
acc.tools[name] = {
|
|
25
|
+
acc.tools[name] = stripOverwrite({
|
|
17
26
|
...lowerPriorityTool,
|
|
18
27
|
...higherPriorityTool
|
|
19
|
-
};
|
|
28
|
+
});
|
|
20
29
|
toolPriorities[name] = Math.max(existingPriority, priority);
|
|
21
30
|
continue;
|
|
22
31
|
}
|
|
23
32
|
if (!acc.tools) acc.tools = {};
|
|
24
|
-
acc.tools[name] = tool;
|
|
33
|
+
acc.tools[name] = stripOverwrite(tool);
|
|
25
34
|
toolPriorities[name] ??= priority;
|
|
26
35
|
}
|
|
27
36
|
if (config.config) acc.config = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":["Unsubscribe","Tool","LanguageModelV1CallSettings","maxTokens","temperature","topP","presencePenalty","frequencyPenalty","seed","headers","Record","LanguageModelConfig","apiKey","baseUrl","modelName","reasoningEffort","ModelContext","priority","system","tools","callSettings","config","unstable_composerMetadata","ModelContextProvider","getModelContext","subscribe","callback","AssistantToolProps","TArgs","TResult","toolName","render","AssistantInstructionsConfig","disabled","instruction","AssistantContextConfig","getContext","mergeModelContexts","configSet","Set","configs","Array","from","map","c","sort","a","b","toolPriorities","reduce","acc","name","
|
|
1
|
+
{"version":3,"file":"types.js","names":["Unsubscribe","Tool","LanguageModelV1CallSettings","maxTokens","temperature","topP","presencePenalty","frequencyPenalty","seed","headers","Record","LanguageModelConfig","apiKey","baseUrl","modelName","reasoningEffort","ModelContext","priority","system","tools","callSettings","config","unstable_composerMetadata","ModelContextProvider","getModelContext","subscribe","callback","AssistantToolProps","TArgs","TResult","toolName","render","AssistantInstructionsConfig","disabled","instruction","AssistantContextConfig","getContext","stripOverwrite","tool","overwrite","_","rest","mergeModelContexts","configSet","Set","configs","Array","from","map","c","sort","a","b","toolPriorities","reduce","acc","name","Object","entries","existing","existingPriority","Error","higherPriorityTool","lowerPriorityTool","Math","max"],"sources":["../../src/model-context/types.ts"],"sourcesContent":["import type { Unsubscribe } from \"../types/unsubscribe\";\nimport type { Tool } from \"assistant-stream\";\n\nexport type LanguageModelV1CallSettings = {\n maxTokens?: number;\n temperature?: number;\n topP?: number;\n presencePenalty?: number;\n frequencyPenalty?: number;\n seed?: number;\n headers?: Record<string, string | undefined>;\n};\n\nexport type LanguageModelConfig = {\n apiKey?: string;\n baseUrl?: string;\n modelName?: string;\n reasoningEffort?: string;\n};\n\nexport type ModelContext = {\n priority?: number | undefined;\n system?: string | undefined;\n tools?: Record<string, Tool<any, any>> | undefined;\n callSettings?: LanguageModelV1CallSettings | undefined;\n config?: LanguageModelConfig | undefined;\n /**\n * Persisted message metadata pulled at send time and merged into the outgoing\n * user message's `metadata.custom` (not forwarded to the model directly).\n * Ignored by the transport, which only reads system/tools/callSettings/config.\n */\n unstable_composerMetadata?: Record<string, unknown> | undefined;\n};\n\nexport type ModelContextProvider = {\n getModelContext: () => ModelContext;\n subscribe?: (callback: () => void) => Unsubscribe;\n};\n\nexport type AssistantToolProps<\n TArgs extends Record<string, unknown>,\n TResult,\n> = Tool<TArgs, TResult> & {\n toolName: string;\n render?: unknown;\n};\n\nexport type AssistantInstructionsConfig = {\n disabled?: boolean | undefined;\n instruction: string;\n};\n\nexport type AssistantContextConfig = {\n getContext: () => string;\n disabled?: boolean | undefined;\n};\n\nconst stripOverwrite = (tool: Tool<any, any>): Tool<any, any> => {\n if (!tool.overwrite) return tool;\n const { overwrite: _, ...rest } = tool;\n return rest as Tool<any, any>;\n};\n\nexport const mergeModelContexts = (\n configSet: Set<ModelContextProvider>,\n): ModelContext => {\n const configs = Array.from(configSet)\n .map((c) => c.getModelContext())\n .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\n\n const toolPriorities: Record<string, number> = {};\n\n return configs.reduce((acc, config) => {\n const priority = config.priority ?? 0;\n if (config.system) {\n if (acc.system) {\n acc.system += `\\n\\n${config.system}`;\n } else {\n acc.system = config.system;\n }\n }\n if (config.tools) {\n for (const [name, tool] of Object.entries(config.tools)) {\n const existing = acc.tools?.[name];\n if (existing && existing !== tool) {\n const existingPriority = toolPriorities[name]!;\n if (existingPriority === priority) {\n if (!tool.overwrite) {\n throw new Error(\n `You tried to define a tool with the name ${name}, but it already exists.`,\n );\n }\n acc.tools![name] = stripOverwrite(tool);\n continue;\n }\n\n const higherPriorityTool =\n existingPriority > priority ? existing : tool;\n const lowerPriorityTool =\n existingPriority > priority ? tool : existing;\n acc.tools![name] = stripOverwrite({\n ...lowerPriorityTool,\n ...higherPriorityTool,\n } as Tool<any, any>);\n toolPriorities[name] = Math.max(existingPriority, priority);\n continue;\n }\n\n if (!acc.tools) acc.tools = {};\n acc.tools[name] = stripOverwrite(tool);\n toolPriorities[name] ??= priority;\n }\n }\n if (config.config) {\n acc.config = {\n ...acc.config,\n ...config.config,\n };\n }\n if (config.callSettings) {\n acc.callSettings = {\n ...acc.callSettings,\n ...config.callSettings,\n };\n }\n if (config.unstable_composerMetadata) {\n acc.unstable_composerMetadata = {\n ...acc.unstable_composerMetadata,\n ...config.unstable_composerMetadata,\n };\n }\n return acc;\n }, {} as ModelContext);\n};\n"],"mappings":";AAyDA,MAAMqC,kBAAkBC,SAAyC;CAC/D,IAAI,CAACA,KAAKC,WAAW,OAAOD;CAC5B,MAAM,EAAEC,WAAWC,GAAG,GAAGC,SAASH;CAClC,OAAOG;AACT;AAEA,MAAaC,sBACXC,cACiB;CACjB,MAAME,UAAUC,MAAMC,KAAKJ,SAAS,CAAC,CAClCK,KAAKC,MAAMA,EAAEzB,gBAAgB,CAAC,CAAC,CAC/B0B,MAAMC,GAAGC,OAAOA,EAAEnC,YAAY,MAAMkC,EAAElC,YAAY,EAAE;CAEvD,MAAMoC,iBAAyC,CAAC;CAEhD,OAAOR,QAAQS,QAAQC,KAAKlC,WAAW;EACrC,MAAMJ,WAAWI,OAAOJ,YAAY;EACpC,IAAII,OAAOH,QACT,IAAIqC,IAAIrC,QACNqC,IAAIrC,UAAU,OAAOG,OAAOH;OAE5BqC,IAAIrC,SAASG,OAAOH;EAGxB,IAAIG,OAAOF,OACT,KAAK,MAAM,CAACqC,MAAMlB,SAASmB,OAAOC,QAAQrC,OAAOF,KAAK,GAAG;GACvD,MAAMwC,WAAWJ,IAAIpC,QAAQqC;GAC7B,IAAIG,YAAYA,aAAarB,MAAM;IACjC,MAAMsB,mBAAmBP,eAAeG;IACxC,IAAII,qBAAqB3C,UAAU;KACjC,IAAI,CAACqB,KAAKC,WACR,MAAM,IAAIsB,MACR,4CAA4CL,KAAI,yBAClD;KAEFD,IAAIpC,MAAOqC,QAAQnB,eAAeC,IAAI;KACtC;IACF;IAEA,MAAMwB,qBACJF,mBAAmB3C,WAAW0C,WAAWrB;IAC3C,MAAMyB,oBACJH,mBAAmB3C,WAAWqB,OAAOqB;IACvCJ,IAAIpC,MAAOqC,QAAQnB,eAAe;KAChC,GAAG0B;KACH,GAAGD;IACL,CAAmB;IACnBT,eAAeG,QAAQQ,KAAKC,IAAIL,kBAAkB3C,QAAQ;IAC1D;GACF;GAEA,IAAI,CAACsC,IAAIpC,OAAOoC,IAAIpC,QAAQ,CAAC;GAC7BoC,IAAIpC,MAAMqC,QAAQnB,eAAeC,IAAI;GACrCe,eAAeG,UAAUvC;EAC3B;EAEF,IAAII,OAAOA,QACTkC,IAAIlC,SAAS;GACX,GAAGkC,IAAIlC;GACP,GAAGA,OAAOA;EACZ;EAEF,IAAIA,OAAOD,cACTmC,IAAInC,eAAe;GACjB,GAAGmC,IAAInC;GACP,GAAGC,OAAOD;EACZ;EAEF,IAAIC,OAAOC,2BACTiC,IAAIjC,4BAA4B;GAC9B,GAAGiC,IAAIjC;GACP,GAAGD,OAAOC;EACZ;EAEF,OAAOiC;CACT,GAAG,CAAC,CAAiB;AACvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalStorageThreadListAdapter.d.ts","names":[],"sources":["../../../src/react/adapters/LocalStorageThreadListAdapter.tsx"],"mappings":";;;;;;KAmBY;EACV,QAAQ,cAAc;EACtB,QAAQ,aAAa,gBAAgB;EACrC,WAAW,cAAc;;KAkCtB;EACH,SAAS;EACT;EACA,iBAAiB;;KAGd;EACH;EACA;EACA;EACA;EACA,SAAS;;cAwIE,4BACX,uBACC;cAoCU,+BACX,uBACC;
|
|
1
|
+
{"version":3,"file":"LocalStorageThreadListAdapter.d.ts","names":[],"sources":["../../../src/react/adapters/LocalStorageThreadListAdapter.tsx"],"mappings":";;;;;;KAmBY;EACV,QAAQ,cAAc;EACtB,QAAQ,aAAa,gBAAgB;EACrC,WAAW,cAAc;;KAkCtB;EACH,SAAS;EACT;EACA,iBAAiB;;KAGd;EACH;EACA;EACA;EACA;EACA,SAAS;;cAwIE,4BACX,uBACC;cAoCU,+BACX,uBACC;cA4GU,4BACX,SAAS,+BACR"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RuntimeAdapterProvider } from "../runtimes/RuntimeAdapterProvider.js";
|
|
2
2
|
import { createAssistantStream } from "assistant-stream";
|
|
3
3
|
import { useAui } from "@assistant-ui/store";
|
|
4
|
+
import "@assistant-ui/tap/react-shim";
|
|
4
5
|
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
5
6
|
import { jsx } from "react/jsx-runtime";
|
|
6
7
|
//#region src/react/adapters/LocalStorageThreadListAdapter.tsx
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalStorageThreadListAdapter.js","names":["AssistantStream","createAssistantStream","FC","PropsWithChildren","useMemo","useAui","RemoteThreadInitializeResponse","RemoteThreadListAdapter","RemoteThreadListResponse","RemoteThreadMetadata","ThreadHistoryAdapter","ThreadMessage","RunConfig","ExportedMessageRepository","ExportedMessageRepositoryItem","RuntimeAdapterProvider","TitleGenerationAdapter","AsyncStorageLike","getItem","key","Promise","setItem","value","removeItem","KeyedMutationQueue","tails","Map","run","mutation","T","previous","get","result","then","tail","undefined","set","delete","mutationQueues","WeakMap","getMutationQueue","storage","queue","LocalStorageAdapterOptions","prefix","titleGenerator","StoredThreadMetadata","remoteId","externalId","status","title","custom","Record","StoredSystemMessage","Extract","role","StoredUserMessage","StoredAssistantMessage","isRecord","Array","isArray","parseJSON","raw","JSON","parse","parseStoredThread","parseDate","Date","Number","isNaN","getTime","date","isMessageRole","parseStoredThreadMessage","id","content","createdAt","metadata","type","submittedFeedback","submittedFeedbackType","unstable_state","unstable_annotations","unstable_data","steps","timing","NonNullable","isOptimistic","attachments","length","parseStoredThreadMetadata","parsed","flatMap","item","thread","parseStoredMessageRepositoryItem","message","parentId","runConfig","parseStoredMessageRepository","messages","candidateMessages","parsedItem","acceptedIds","Set","has","add","headId","some","AsyncStorageHistoryAdapter","constructor","aui","ReturnType","mutationQueue","_messagesKey","load","threadListItem","getState","append","initialize","repo","idx","findIndex","m","push","stringify","createHistoryProvider","Provider","t0","$","_c","children","t1","history","t2","adapters","t3","createLocalStorageAdapter","options","threadsKey","messagesKey","threadId","loadThreadMetadata","saveThreadMetadata","threads","updateThreadMetadata","update","find","adapter","unstable_Provider","list","map","t","unshift","rename","newTitle","updateCustom","archive","unarchive","filtered","filter","fetch","Error","generateTitle","controller","appendText"],"sources":["../../../src/react/adapters/LocalStorageThreadListAdapter.tsx"],"sourcesContent":["import { type AssistantStream, createAssistantStream } from \"assistant-stream\";\nimport { type FC, type PropsWithChildren, useMemo } from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type {\n RemoteThreadInitializeResponse,\n RemoteThreadListAdapter,\n RemoteThreadListResponse,\n RemoteThreadMetadata,\n ThreadHistoryAdapter,\n ThreadMessage,\n RunConfig,\n} from \"../../index\";\nimport type {\n ExportedMessageRepository,\n ExportedMessageRepositoryItem,\n} from \"../../internal\";\nimport { RuntimeAdapterProvider } from \"../runtimes/RuntimeAdapterProvider\";\nimport type { TitleGenerationAdapter } from \"./TitleGenerationAdapter\";\n\nexport type AsyncStorageLike = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n};\n\nclass KeyedMutationQueue {\n private readonly tails = new Map<string, Promise<void>>();\n\n run<T>(key: string, mutation: () => Promise<T>): Promise<T> {\n const previous = this.tails.get(key);\n const result = previous ? previous.then(mutation) : mutation();\n const tail = result.then(\n () => undefined,\n () => undefined,\n );\n\n this.tails.set(key, tail);\n void tail.then(() => {\n if (this.tails.get(key) === tail) this.tails.delete(key);\n });\n\n return result;\n }\n}\n\nconst mutationQueues = new WeakMap<AsyncStorageLike, KeyedMutationQueue>();\n\nconst getMutationQueue = (storage: AsyncStorageLike): KeyedMutationQueue => {\n let queue = mutationQueues.get(storage);\n if (!queue) {\n queue = new KeyedMutationQueue();\n mutationQueues.set(storage, queue);\n }\n return queue;\n};\n\ntype LocalStorageAdapterOptions = {\n storage: AsyncStorageLike;\n prefix?: string | undefined;\n titleGenerator?: TitleGenerationAdapter | undefined;\n};\n\ntype StoredThreadMetadata = {\n remoteId: string;\n externalId?: string;\n status: \"regular\" | \"archived\";\n title?: string;\n custom?: Record<string, unknown> | undefined;\n};\n\ntype StoredSystemMessage = Extract<ThreadMessage, { role: \"system\" }>;\ntype StoredUserMessage = Extract<ThreadMessage, { role: \"user\" }>;\ntype StoredAssistantMessage = Extract<ThreadMessage, { role: \"assistant\" }>;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst parseJSON = (raw: string | null): unknown => {\n if (!raw) return undefined;\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n return undefined;\n }\n};\n\nconst parseStoredThread = (value: unknown): StoredThreadMetadata | null => {\n if (!isRecord(value) || typeof value.remoteId !== \"string\") return null;\n\n const status = value.status ?? \"regular\";\n if (status !== \"regular\" && status !== \"archived\") return null;\n\n return {\n remoteId: value.remoteId,\n status,\n ...(typeof value.externalId === \"string\"\n ? { externalId: value.externalId }\n : undefined),\n ...(typeof value.title === \"string\" ? { title: value.title } : undefined),\n ...(isRecord(value.custom) ? { custom: value.custom } : undefined),\n };\n};\n\nconst parseDate = (value: unknown): Date | null => {\n if (value instanceof Date && !Number.isNaN(value.getTime())) return value;\n if (typeof value !== \"string\" && typeof value !== \"number\") return null;\n\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? null : date;\n};\n\nconst isMessageRole = (value: unknown): value is ThreadMessage[\"role\"] =>\n value === \"system\" || value === \"user\" || value === \"assistant\";\n\nconst parseStoredThreadMessage = (value: unknown): ThreadMessage | null => {\n if (!isRecord(value) || typeof value.id !== \"string\") return null;\n if (!isMessageRole(value.role)) return null;\n if (!Array.isArray(value.content)) return null;\n\n const createdAt = parseDate(value.createdAt);\n if (!createdAt) return null;\n\n const metadata = value.metadata;\n if (!isRecord(metadata) || !isRecord(metadata.custom)) return null;\n\n if (value.role === \"assistant\") {\n const status = value.status;\n if (!isRecord(status) || typeof status.type !== \"string\") return null;\n\n const submittedFeedback = isRecord(metadata.submittedFeedback)\n ? metadata.submittedFeedback\n : undefined;\n const submittedFeedbackType = submittedFeedback?.type;\n\n return {\n id: value.id,\n role: \"assistant\",\n content: value.content as StoredAssistantMessage[\"content\"],\n status: status as StoredAssistantMessage[\"status\"],\n createdAt,\n metadata: {\n unstable_state: (metadata.unstable_state ??\n null) as StoredAssistantMessage[\"metadata\"][\"unstable_state\"],\n unstable_annotations: Array.isArray(metadata.unstable_annotations)\n ? (metadata.unstable_annotations as StoredAssistantMessage[\"metadata\"][\"unstable_annotations\"])\n : [],\n unstable_data: Array.isArray(metadata.unstable_data)\n ? (metadata.unstable_data as StoredAssistantMessage[\"metadata\"][\"unstable_data\"])\n : [],\n steps: Array.isArray(metadata.steps)\n ? (metadata.steps as StoredAssistantMessage[\"metadata\"][\"steps\"])\n : [],\n ...(submittedFeedbackType === \"positive\" ||\n submittedFeedbackType === \"negative\"\n ? {\n submittedFeedback: {\n type: submittedFeedbackType,\n },\n }\n : undefined),\n ...(metadata.timing !== undefined\n ? {\n timing: metadata.timing as NonNullable<\n StoredAssistantMessage[\"metadata\"][\"timing\"]\n >,\n }\n : undefined),\n ...(metadata.isOptimistic === true\n ? { isOptimistic: true }\n : undefined),\n custom: metadata.custom,\n },\n };\n }\n\n if (value.role === \"user\") {\n return {\n id: value.id,\n role: \"user\",\n content: value.content as StoredUserMessage[\"content\"],\n attachments: Array.isArray(value.attachments)\n ? (value.attachments as StoredUserMessage[\"attachments\"])\n : [],\n createdAt,\n metadata: {\n custom: metadata.custom,\n },\n };\n }\n\n if (value.content.length !== 1) return null;\n\n return {\n id: value.id,\n role: \"system\",\n content: [value.content[0] as StoredSystemMessage[\"content\"][0]],\n createdAt,\n metadata: {\n custom: metadata.custom,\n },\n };\n};\n\nexport const parseStoredThreadMetadata = (\n raw: string | null,\n): StoredThreadMetadata[] => {\n const parsed = parseJSON(raw);\n if (!Array.isArray(parsed)) return [];\n\n return parsed.flatMap((item) => {\n const thread = parseStoredThread(item);\n return thread ? [thread] : [];\n });\n};\n\nconst parseStoredMessageRepositoryItem = (\n value: unknown,\n): ExportedMessageRepositoryItem | null => {\n if (!isRecord(value)) return null;\n\n const message = parseStoredThreadMessage(value.message);\n if (!message) return null;\n\n const parentId = value.parentId;\n if (\n parentId !== undefined &&\n parentId !== null &&\n typeof parentId !== \"string\"\n ) {\n return null;\n }\n\n return {\n message,\n parentId: parentId ?? null,\n ...(isRecord(value.runConfig)\n ? { runConfig: value.runConfig as RunConfig }\n : undefined),\n };\n};\n\nexport const parseStoredMessageRepository = (\n raw: string | null,\n): ExportedMessageRepository => {\n const parsed = parseJSON(raw);\n if (!isRecord(parsed) || !Array.isArray(parsed.messages)) {\n return { messages: [] };\n }\n\n const candidateMessages = parsed.messages.flatMap((item) => {\n const parsedItem = parseStoredMessageRepositoryItem(item);\n return parsedItem ? [parsedItem] : [];\n });\n\n const acceptedIds = new Set<string>();\n const messages = candidateMessages.flatMap((item) => {\n if (acceptedIds.has(item.message.id)) return [];\n if (item.parentId !== null && !acceptedIds.has(item.parentId)) return [];\n\n acceptedIds.add(item.message.id);\n return [item];\n });\n\n const headId =\n parsed.headId === null ||\n (typeof parsed.headId === \"string\" &&\n messages.some((item) => item.message.id === parsed.headId))\n ? parsed.headId\n : undefined;\n\n return {\n ...(headId !== undefined ? { headId } : undefined),\n messages,\n };\n};\n\nclass AsyncStorageHistoryAdapter implements ThreadHistoryAdapter {\n constructor(\n private storage: AsyncStorageLike,\n private aui: ReturnType<typeof useAui>,\n private prefix: string,\n private mutationQueue: KeyedMutationQueue,\n ) {}\n\n private _messagesKey(remoteId: string) {\n return `${this.prefix}messages:${remoteId}`;\n }\n\n async load(): Promise<ExportedMessageRepository> {\n const remoteId = this.aui.threadListItem().getState().remoteId;\n if (!remoteId) return { messages: [] };\n\n const raw = await this.storage.getItem(this._messagesKey(remoteId));\n return parseStoredMessageRepository(raw);\n }\n\n async append(item: ExportedMessageRepositoryItem): Promise<void> {\n const { remoteId } = await this.aui.threadListItem().initialize();\n\n const key = this._messagesKey(remoteId);\n await this.mutationQueue.run(key, async () => {\n const raw = await this.storage.getItem(key);\n const repo = parseStoredMessageRepository(raw);\n\n const idx = repo.messages.findIndex(\n (m) => m.message.id === item.message.id,\n );\n if (idx >= 0) {\n repo.messages[idx] = item;\n } else {\n repo.messages.push(item);\n }\n repo.headId = item.message.id;\n\n await this.storage.setItem(key, JSON.stringify(repo));\n });\n }\n}\n\nconst createHistoryProvider = (\n storage: AsyncStorageLike,\n prefix: string,\n mutationQueue: KeyedMutationQueue,\n): FC<PropsWithChildren> => {\n const Provider: FC<PropsWithChildren> = ({ children }) => {\n const aui = useAui();\n const history = useMemo(\n () => new AsyncStorageHistoryAdapter(storage, aui, prefix, mutationQueue),\n [aui],\n );\n const adapters = useMemo(() => ({ history }), [history]);\n\n return (\n <RuntimeAdapterProvider adapters={adapters}>\n {children}\n </RuntimeAdapterProvider>\n );\n };\n return Provider;\n};\n\nexport const createLocalStorageAdapter = (\n options: LocalStorageAdapterOptions,\n): RemoteThreadListAdapter => {\n const { storage, prefix = \"@assistant-ui:\", titleGenerator } = options;\n\n const threadsKey = `${prefix}threads`;\n const messagesKey = (threadId: string) => `${prefix}messages:${threadId}`;\n const mutationQueue = getMutationQueue(storage);\n\n const loadThreadMetadata = async (): Promise<StoredThreadMetadata[]> => {\n const raw = await storage.getItem(threadsKey);\n return parseStoredThreadMetadata(raw);\n };\n\n const saveThreadMetadata = async (\n threads: StoredThreadMetadata[],\n ): Promise<void> => {\n await storage.setItem(threadsKey, JSON.stringify(threads));\n };\n\n const updateThreadMetadata = async (\n remoteId: string,\n update: (thread: StoredThreadMetadata) => void,\n ): Promise<void> => {\n await mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n const thread = threads.find((item) => item.remoteId === remoteId);\n if (thread) {\n update(thread);\n await saveThreadMetadata(threads);\n }\n });\n };\n\n const adapter: RemoteThreadListAdapter = {\n unstable_Provider: createHistoryProvider(storage, prefix, mutationQueue),\n\n async list(): Promise<RemoteThreadListResponse> {\n const threads = await loadThreadMetadata();\n return {\n threads: threads.map((t) => ({\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: t.status,\n title: t.title,\n custom: t.custom,\n })),\n };\n },\n\n async initialize(\n threadId: string,\n ): Promise<RemoteThreadInitializeResponse> {\n const remoteId = threadId;\n return mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n\n // Only add if not already present\n if (!threads.some((t) => t.remoteId === remoteId)) {\n threads.unshift({\n remoteId,\n status: \"regular\",\n });\n await saveThreadMetadata(threads);\n }\n\n return { remoteId, externalId: undefined };\n });\n },\n\n async rename(remoteId: string, newTitle: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.title = newTitle;\n });\n },\n\n async updateCustom(\n remoteId: string,\n custom: Record<string, unknown> | undefined,\n ): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.custom = custom;\n });\n },\n\n async archive(remoteId: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.status = \"archived\";\n });\n },\n\n async unarchive(remoteId: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.status = \"regular\";\n });\n },\n\n async delete(remoteId: string): Promise<void> {\n await mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n const filtered = threads.filter((t) => t.remoteId !== remoteId);\n await saveThreadMetadata(filtered);\n });\n const key = messagesKey(remoteId);\n await mutationQueue.run(key, () => storage.removeItem(key));\n },\n\n async fetch(threadId: string): Promise<RemoteThreadMetadata> {\n const threads = await loadThreadMetadata();\n const thread = threads.find((t) => t.remoteId === threadId);\n if (!thread)\n throw new Error(\n `Stored thread \"${threadId}\" not found while fetching thread metadata.`,\n );\n return {\n remoteId: thread.remoteId,\n externalId: thread.externalId,\n status: thread.status,\n title: thread.title,\n custom: thread.custom,\n };\n },\n\n async generateTitle(\n remoteId: string,\n messages: readonly ThreadMessage[],\n ): Promise<AssistantStream> {\n if (titleGenerator) {\n const title = await titleGenerator.generateTitle(messages);\n\n // Update the stored title\n await updateThreadMetadata(remoteId, (thread) => {\n thread.title = title;\n });\n\n // Return a stream with a single text part\n return createAssistantStream((controller) => {\n controller.appendText(title);\n });\n }\n\n // No title generator — return empty stream\n return createAssistantStream(() => {});\n },\n };\n\n return adapter;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LocalStorageThreadListAdapter.js","names":["AssistantStream","createAssistantStream","FC","PropsWithChildren","useMemo","useAui","RemoteThreadInitializeResponse","RemoteThreadListAdapter","RemoteThreadListResponse","RemoteThreadMetadata","ThreadHistoryAdapter","ThreadMessage","RunConfig","ExportedMessageRepository","ExportedMessageRepositoryItem","RuntimeAdapterProvider","TitleGenerationAdapter","AsyncStorageLike","getItem","key","Promise","setItem","value","removeItem","KeyedMutationQueue","tails","Map","run","mutation","T","previous","get","result","then","tail","undefined","set","delete","mutationQueues","WeakMap","getMutationQueue","storage","queue","LocalStorageAdapterOptions","prefix","titleGenerator","StoredThreadMetadata","remoteId","externalId","status","title","custom","Record","StoredSystemMessage","Extract","role","StoredUserMessage","StoredAssistantMessage","isRecord","Array","isArray","parseJSON","raw","JSON","parse","parseStoredThread","parseDate","Date","Number","isNaN","getTime","date","isMessageRole","parseStoredThreadMessage","id","content","createdAt","metadata","type","submittedFeedback","submittedFeedbackType","unstable_state","unstable_annotations","unstable_data","steps","timing","NonNullable","isOptimistic","attachments","length","parseStoredThreadMetadata","parsed","flatMap","item","thread","parseStoredMessageRepositoryItem","message","parentId","runConfig","parseStoredMessageRepository","messages","candidateMessages","parsedItem","acceptedIds","Set","has","add","headId","some","AsyncStorageHistoryAdapter","aui","ReturnType","mutationQueue","constructor","_messagesKey","load","threadListItem","getState","append","initialize","repo","idx","findIndex","m","push","stringify","createHistoryProvider","Provider","t0","$","_c","children","t1","history","t2","adapters","t3","createLocalStorageAdapter","options","threadsKey","messagesKey","threadId","loadThreadMetadata","saveThreadMetadata","threads","updateThreadMetadata","update","find","adapter","unstable_Provider","list","map","t","unshift","rename","newTitle","updateCustom","archive","unarchive","filtered","filter","fetch","Error","generateTitle","controller","appendText"],"sources":["../../../src/react/adapters/LocalStorageThreadListAdapter.tsx"],"sourcesContent":["import { type AssistantStream, createAssistantStream } from \"assistant-stream\";\nimport { type FC, type PropsWithChildren, useMemo } from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type {\n RemoteThreadInitializeResponse,\n RemoteThreadListAdapter,\n RemoteThreadListResponse,\n RemoteThreadMetadata,\n ThreadHistoryAdapter,\n ThreadMessage,\n RunConfig,\n} from \"../../index\";\nimport type {\n ExportedMessageRepository,\n ExportedMessageRepositoryItem,\n} from \"../../internal\";\nimport { RuntimeAdapterProvider } from \"../runtimes/RuntimeAdapterProvider\";\nimport type { TitleGenerationAdapter } from \"./TitleGenerationAdapter\";\n\nexport type AsyncStorageLike = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n};\n\nclass KeyedMutationQueue {\n private readonly tails = new Map<string, Promise<void>>();\n\n run<T>(key: string, mutation: () => Promise<T>): Promise<T> {\n const previous = this.tails.get(key);\n const result = previous ? previous.then(mutation) : mutation();\n const tail = result.then(\n () => undefined,\n () => undefined,\n );\n\n this.tails.set(key, tail);\n void tail.then(() => {\n if (this.tails.get(key) === tail) this.tails.delete(key);\n });\n\n return result;\n }\n}\n\nconst mutationQueues = new WeakMap<AsyncStorageLike, KeyedMutationQueue>();\n\nconst getMutationQueue = (storage: AsyncStorageLike): KeyedMutationQueue => {\n let queue = mutationQueues.get(storage);\n if (!queue) {\n queue = new KeyedMutationQueue();\n mutationQueues.set(storage, queue);\n }\n return queue;\n};\n\ntype LocalStorageAdapterOptions = {\n storage: AsyncStorageLike;\n prefix?: string | undefined;\n titleGenerator?: TitleGenerationAdapter | undefined;\n};\n\ntype StoredThreadMetadata = {\n remoteId: string;\n externalId?: string;\n status: \"regular\" | \"archived\";\n title?: string;\n custom?: Record<string, unknown> | undefined;\n};\n\ntype StoredSystemMessage = Extract<ThreadMessage, { role: \"system\" }>;\ntype StoredUserMessage = Extract<ThreadMessage, { role: \"user\" }>;\ntype StoredAssistantMessage = Extract<ThreadMessage, { role: \"assistant\" }>;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst parseJSON = (raw: string | null): unknown => {\n if (!raw) return undefined;\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n return undefined;\n }\n};\n\nconst parseStoredThread = (value: unknown): StoredThreadMetadata | null => {\n if (!isRecord(value) || typeof value.remoteId !== \"string\") return null;\n\n const status = value.status ?? \"regular\";\n if (status !== \"regular\" && status !== \"archived\") return null;\n\n return {\n remoteId: value.remoteId,\n status,\n ...(typeof value.externalId === \"string\"\n ? { externalId: value.externalId }\n : undefined),\n ...(typeof value.title === \"string\" ? { title: value.title } : undefined),\n ...(isRecord(value.custom) ? { custom: value.custom } : undefined),\n };\n};\n\nconst parseDate = (value: unknown): Date | null => {\n if (value instanceof Date && !Number.isNaN(value.getTime())) return value;\n if (typeof value !== \"string\" && typeof value !== \"number\") return null;\n\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? null : date;\n};\n\nconst isMessageRole = (value: unknown): value is ThreadMessage[\"role\"] =>\n value === \"system\" || value === \"user\" || value === \"assistant\";\n\nconst parseStoredThreadMessage = (value: unknown): ThreadMessage | null => {\n if (!isRecord(value) || typeof value.id !== \"string\") return null;\n if (!isMessageRole(value.role)) return null;\n if (!Array.isArray(value.content)) return null;\n\n const createdAt = parseDate(value.createdAt);\n if (!createdAt) return null;\n\n const metadata = value.metadata;\n if (!isRecord(metadata) || !isRecord(metadata.custom)) return null;\n\n if (value.role === \"assistant\") {\n const status = value.status;\n if (!isRecord(status) || typeof status.type !== \"string\") return null;\n\n const submittedFeedback = isRecord(metadata.submittedFeedback)\n ? metadata.submittedFeedback\n : undefined;\n const submittedFeedbackType = submittedFeedback?.type;\n\n return {\n id: value.id,\n role: \"assistant\",\n content: value.content as StoredAssistantMessage[\"content\"],\n status: status as StoredAssistantMessage[\"status\"],\n createdAt,\n metadata: {\n unstable_state: (metadata.unstable_state ??\n null) as StoredAssistantMessage[\"metadata\"][\"unstable_state\"],\n unstable_annotations: Array.isArray(metadata.unstable_annotations)\n ? (metadata.unstable_annotations as StoredAssistantMessage[\"metadata\"][\"unstable_annotations\"])\n : [],\n unstable_data: Array.isArray(metadata.unstable_data)\n ? (metadata.unstable_data as StoredAssistantMessage[\"metadata\"][\"unstable_data\"])\n : [],\n steps: Array.isArray(metadata.steps)\n ? (metadata.steps as StoredAssistantMessage[\"metadata\"][\"steps\"])\n : [],\n ...(submittedFeedbackType === \"positive\" ||\n submittedFeedbackType === \"negative\"\n ? {\n submittedFeedback: {\n type: submittedFeedbackType,\n },\n }\n : undefined),\n ...(metadata.timing !== undefined\n ? {\n timing: metadata.timing as NonNullable<\n StoredAssistantMessage[\"metadata\"][\"timing\"]\n >,\n }\n : undefined),\n ...(metadata.isOptimistic === true\n ? { isOptimistic: true }\n : undefined),\n custom: metadata.custom,\n },\n };\n }\n\n if (value.role === \"user\") {\n return {\n id: value.id,\n role: \"user\",\n content: value.content as StoredUserMessage[\"content\"],\n attachments: Array.isArray(value.attachments)\n ? (value.attachments as StoredUserMessage[\"attachments\"])\n : [],\n createdAt,\n metadata: {\n custom: metadata.custom,\n },\n };\n }\n\n if (value.content.length !== 1) return null;\n\n return {\n id: value.id,\n role: \"system\",\n content: [value.content[0] as StoredSystemMessage[\"content\"][0]],\n createdAt,\n metadata: {\n custom: metadata.custom,\n },\n };\n};\n\nexport const parseStoredThreadMetadata = (\n raw: string | null,\n): StoredThreadMetadata[] => {\n const parsed = parseJSON(raw);\n if (!Array.isArray(parsed)) return [];\n\n return parsed.flatMap((item) => {\n const thread = parseStoredThread(item);\n return thread ? [thread] : [];\n });\n};\n\nconst parseStoredMessageRepositoryItem = (\n value: unknown,\n): ExportedMessageRepositoryItem | null => {\n if (!isRecord(value)) return null;\n\n const message = parseStoredThreadMessage(value.message);\n if (!message) return null;\n\n const parentId = value.parentId;\n if (\n parentId !== undefined &&\n parentId !== null &&\n typeof parentId !== \"string\"\n ) {\n return null;\n }\n\n return {\n message,\n parentId: parentId ?? null,\n ...(isRecord(value.runConfig)\n ? { runConfig: value.runConfig as RunConfig }\n : undefined),\n };\n};\n\nexport const parseStoredMessageRepository = (\n raw: string | null,\n): ExportedMessageRepository => {\n const parsed = parseJSON(raw);\n if (!isRecord(parsed) || !Array.isArray(parsed.messages)) {\n return { messages: [] };\n }\n\n const candidateMessages = parsed.messages.flatMap((item) => {\n const parsedItem = parseStoredMessageRepositoryItem(item);\n return parsedItem ? [parsedItem] : [];\n });\n\n const acceptedIds = new Set<string>();\n const messages = candidateMessages.flatMap((item) => {\n if (acceptedIds.has(item.message.id)) return [];\n if (item.parentId !== null && !acceptedIds.has(item.parentId)) return [];\n\n acceptedIds.add(item.message.id);\n return [item];\n });\n\n const headId =\n parsed.headId === null ||\n (typeof parsed.headId === \"string\" &&\n messages.some((item) => item.message.id === parsed.headId))\n ? parsed.headId\n : undefined;\n\n return {\n ...(headId !== undefined ? { headId } : undefined),\n messages,\n };\n};\n\nclass AsyncStorageHistoryAdapter implements ThreadHistoryAdapter {\n private storage: AsyncStorageLike;\n private aui: ReturnType<typeof useAui>;\n private prefix: string;\n private mutationQueue: KeyedMutationQueue;\n\n constructor(\n storage: AsyncStorageLike,\n aui: ReturnType<typeof useAui>,\n prefix: string,\n mutationQueue: KeyedMutationQueue,\n ) {\n this.storage = storage;\n this.aui = aui;\n this.prefix = prefix;\n this.mutationQueue = mutationQueue;\n }\n\n private _messagesKey(remoteId: string) {\n return `${this.prefix}messages:${remoteId}`;\n }\n\n async load(): Promise<ExportedMessageRepository> {\n const remoteId = this.aui.threadListItem().getState().remoteId;\n if (!remoteId) return { messages: [] };\n\n const raw = await this.storage.getItem(this._messagesKey(remoteId));\n return parseStoredMessageRepository(raw);\n }\n\n async append(item: ExportedMessageRepositoryItem): Promise<void> {\n const { remoteId } = await this.aui.threadListItem().initialize();\n\n const key = this._messagesKey(remoteId);\n await this.mutationQueue.run(key, async () => {\n const raw = await this.storage.getItem(key);\n const repo = parseStoredMessageRepository(raw);\n\n const idx = repo.messages.findIndex(\n (m) => m.message.id === item.message.id,\n );\n if (idx >= 0) {\n repo.messages[idx] = item;\n } else {\n repo.messages.push(item);\n }\n repo.headId = item.message.id;\n\n await this.storage.setItem(key, JSON.stringify(repo));\n });\n }\n}\n\nconst createHistoryProvider = (\n storage: AsyncStorageLike,\n prefix: string,\n mutationQueue: KeyedMutationQueue,\n): FC<PropsWithChildren> => {\n const Provider: FC<PropsWithChildren> = ({ children }) => {\n const aui = useAui();\n const history = useMemo(\n () => new AsyncStorageHistoryAdapter(storage, aui, prefix, mutationQueue),\n [aui],\n );\n const adapters = useMemo(() => ({ history }), [history]);\n\n return (\n <RuntimeAdapterProvider adapters={adapters}>\n {children}\n </RuntimeAdapterProvider>\n );\n };\n return Provider;\n};\n\nexport const createLocalStorageAdapter = (\n options: LocalStorageAdapterOptions,\n): RemoteThreadListAdapter => {\n const { storage, prefix = \"@assistant-ui:\", titleGenerator } = options;\n\n const threadsKey = `${prefix}threads`;\n const messagesKey = (threadId: string) => `${prefix}messages:${threadId}`;\n const mutationQueue = getMutationQueue(storage);\n\n const loadThreadMetadata = async (): Promise<StoredThreadMetadata[]> => {\n const raw = await storage.getItem(threadsKey);\n return parseStoredThreadMetadata(raw);\n };\n\n const saveThreadMetadata = async (\n threads: StoredThreadMetadata[],\n ): Promise<void> => {\n await storage.setItem(threadsKey, JSON.stringify(threads));\n };\n\n const updateThreadMetadata = async (\n remoteId: string,\n update: (thread: StoredThreadMetadata) => void,\n ): Promise<void> => {\n await mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n const thread = threads.find((item) => item.remoteId === remoteId);\n if (thread) {\n update(thread);\n await saveThreadMetadata(threads);\n }\n });\n };\n\n const adapter: RemoteThreadListAdapter = {\n unstable_Provider: createHistoryProvider(storage, prefix, mutationQueue),\n\n async list(): Promise<RemoteThreadListResponse> {\n const threads = await loadThreadMetadata();\n return {\n threads: threads.map((t) => ({\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: t.status,\n title: t.title,\n custom: t.custom,\n })),\n };\n },\n\n async initialize(\n threadId: string,\n ): Promise<RemoteThreadInitializeResponse> {\n const remoteId = threadId;\n return mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n\n // Only add if not already present\n if (!threads.some((t) => t.remoteId === remoteId)) {\n threads.unshift({\n remoteId,\n status: \"regular\",\n });\n await saveThreadMetadata(threads);\n }\n\n return { remoteId, externalId: undefined };\n });\n },\n\n async rename(remoteId: string, newTitle: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.title = newTitle;\n });\n },\n\n async updateCustom(\n remoteId: string,\n custom: Record<string, unknown> | undefined,\n ): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.custom = custom;\n });\n },\n\n async archive(remoteId: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.status = \"archived\";\n });\n },\n\n async unarchive(remoteId: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.status = \"regular\";\n });\n },\n\n async delete(remoteId: string): Promise<void> {\n await mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n const filtered = threads.filter((t) => t.remoteId !== remoteId);\n await saveThreadMetadata(filtered);\n });\n const key = messagesKey(remoteId);\n await mutationQueue.run(key, () => storage.removeItem(key));\n },\n\n async fetch(threadId: string): Promise<RemoteThreadMetadata> {\n const threads = await loadThreadMetadata();\n const thread = threads.find((t) => t.remoteId === threadId);\n if (!thread)\n throw new Error(\n `Stored thread \"${threadId}\" not found while fetching thread metadata.`,\n );\n return {\n remoteId: thread.remoteId,\n externalId: thread.externalId,\n status: thread.status,\n title: thread.title,\n custom: thread.custom,\n };\n },\n\n async generateTitle(\n remoteId: string,\n messages: readonly ThreadMessage[],\n ): Promise<AssistantStream> {\n if (titleGenerator) {\n const title = await titleGenerator.generateTitle(messages);\n\n // Update the stored title\n await updateThreadMetadata(remoteId, (thread) => {\n thread.title = title;\n });\n\n // Return a stream with a single text part\n return createAssistantStream((controller) => {\n controller.appendText(title);\n });\n }\n\n // No title generator — return empty stream\n return createAssistantStream(() => {});\n },\n };\n\n return adapter;\n};\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isRecord } from "../../utils/json/is-json.js";
|
|
2
2
|
import { interactableToolName, shallowMergeInteractableState } from "../../model-context/interactable-composer-metadata.js";
|
|
3
3
|
import { generateId } from "../../utils/id.js";
|
|
4
|
+
import "assistant-stream";
|
|
4
5
|
//#region src/react/client/interactable-model-context.ts
|
|
5
6
|
const ID_PROPERTY = {
|
|
6
7
|
type: "string",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactable-model-context.js","names":["Tool","toJSONSchema","Unstable_InteractableDefinition","interactableToolName","shallowMergeInteractableState","Unstable_InteractableSnapshotEntry","generateId","isRecord","PartialJSONSchema","ReturnType","ID_PROPERTY","type","const","description","hasIdProperty","schema","Record","properties","id","undefined","withRequiredItemId","required","withoutItemId","_omitted","Array","isArray","filter","key","toArrayUpdateSchema","field","itemSchema","items","idKeyed","add","remove","clear","update","additionalProperties","idKeyedArrayFieldNames","Set","names","value","Object","entries","withArrayUpdateSchemas","fromEntries","map","withRequiredId","partial","process","env","NODE_ENV","console","warn","_reserved","buildInteractableModelContext","definitions","partialSchemaCache","Map","setDefState","updater","prev","streamBaselines","targetId","state","tools","unstable_composerMetadata","values","length","byName","def","list","get","name","push","set","instances","toolName","first","partialSchema","idKeyedFields","resolveTarget","parameters","streamCall","reader","toolCallId","partialArgs","args","streamValues","keys","idIndex","indexOf","target","baseline","arrayBaseline","execute","validIds","d","success","error","JSON","stringify","join","delete","addedItemIds","idFactory","itemId","result","interactables"],"sources":["../../../src/react/client/interactable-model-context.ts"],"sourcesContent":["import type { Tool } from \"assistant-stream\";\nimport { toJSONSchema } from \"assistant-stream\";\nimport type { Unstable_InteractableDefinition } from \"../types/scopes/interactables\";\nimport {\n interactableToolName,\n shallowMergeInteractableState,\n type Unstable_InteractableSnapshotEntry,\n} from \"../../model-context/interactable-composer-metadata\";\nimport { generateId } from \"../../utils/id\";\nimport { isRecord } from \"../../utils/json/is-json\";\n\nexport type PartialJSONSchema = ReturnType<typeof toJSONSchema>;\n\nconst ID_PROPERTY = {\n type: \"string\" as const,\n description:\n \"The id of the instance to update, as shown in its state snapshot in the conversation.\",\n};\n\nconst hasIdProperty = (schema: Record<string, unknown>) => {\n const properties = schema.properties;\n return isRecord(properties) && properties.id !== undefined;\n};\n\nconst withRequiredItemId = (schema: Record<string, unknown>) => ({\n ...schema,\n required: [\"id\"],\n});\n\n// The framework assigns ids to new items, so the model never sees the `id`\n// field when adding (it can't address an item that doesn't exist yet).\nconst withoutItemId = (schema: Record<string, unknown>) => {\n const { id: _omitted, ...properties } = isRecord(schema.properties)\n ? schema.properties\n : {};\n const required = Array.isArray(schema.required)\n ? schema.required.filter((key) => key !== \"id\")\n : schema.required;\n return { ...schema, properties, required };\n};\n\nconst toArrayUpdateSchema = (schema: unknown, field: string) => {\n if (!isRecord(schema) || schema.type !== \"array\") return schema;\n const itemSchema = schema.items;\n if (Array.isArray(itemSchema) || !isRecord(itemSchema)) return schema;\n\n const idKeyed = hasIdProperty(itemSchema);\n const properties: Record<string, unknown> = {\n add: {\n type: \"array\",\n items: idKeyed ? withoutItemId(itemSchema) : itemSchema,\n },\n remove: {\n type: \"array\",\n items: idKeyed ? ID_PROPERTY : itemSchema,\n },\n clear: { type: \"boolean\" },\n };\n\n if (idKeyed) {\n properties.update = {\n type: \"array\",\n items: withRequiredItemId(itemSchema),\n };\n }\n\n return {\n type: \"object\" as const,\n description:\n `Operations for array field \"${field}\". To change one item use update ` +\n `with its id; add new items (their ids are assigned for you), remove items ` +\n `by id, or clear to empty. Change only the items you mean to — never resend ` +\n `the whole array to edit one item.`,\n properties,\n additionalProperties: false,\n };\n};\n\n// Top-level array fields whose items carry an `id` — the fields the framework\n// mints ids for on add.\nconst idKeyedArrayFieldNames = (\n properties: Record<string, unknown>,\n): Set<string> => {\n const names = new Set<string>();\n for (const [key, value] of Object.entries(properties)) {\n if (\n isRecord(value) &&\n value.type === \"array\" &&\n isRecord(value.items) &&\n hasIdProperty(value.items)\n ) {\n names.add(key);\n }\n }\n return names;\n};\n\nconst withArrayUpdateSchemas = (properties: Record<string, unknown>) =>\n Object.fromEntries(\n Object.entries(properties).map(([key, value]) => [\n key,\n toArrayUpdateSchema(value, key),\n ]),\n );\n\n/**\n * Wraps an interactable's partial state schema with the required `id`\n * parameter. Falls back to a permissive schema when the partial conversion\n * failed at registration time.\n */\nfunction withRequiredId(partial: PartialJSONSchema | undefined) {\n if (!partial || typeof partial !== \"object\" || partial.type !== \"object\") {\n return {\n type: \"object\" as const,\n properties: { id: ID_PROPERTY },\n required: [\"id\"],\n additionalProperties: true,\n };\n }\n if (process.env.NODE_ENV !== \"production\" && partial.properties?.id) {\n console.warn(\n `[Interactables] a top-level \"id\" field in an interactable's stateSchema is ` +\n `reserved for instance addressing by the update tool and cannot be updated ` +\n `by the model. Rename the field to make it model-writable.`,\n );\n }\n const { id: _reserved, ...properties } = partial.properties ?? {};\n return {\n ...partial,\n properties: { id: ID_PROPERTY, ...withArrayUpdateSchemas(properties) },\n required: [\"id\"],\n };\n}\n\nexport function buildInteractableModelContext(\n definitions: Record<string, Unstable_InteractableDefinition>,\n partialSchemaCache: Map<string, PartialJSONSchema>,\n setDefState: (id: string, updater: (prev: unknown) => unknown) => void,\n streamBaselines = new Map<string, { targetId: string; state: unknown }>(),\n):\n | {\n tools: Record<string, Tool<any, any>>;\n unstable_composerMetadata?: Record<string, unknown>;\n }\n | undefined {\n const entries = Object.values(definitions);\n if (entries.length === 0) return undefined;\n\n const byName = new Map<string, Unstable_InteractableDefinition[]>();\n for (const def of entries) {\n const list = byName.get(def.name) ?? [];\n list.push(def);\n byName.set(def.name, list);\n }\n\n const tools: Record<string, Tool<any, any>> = {};\n\n for (const [name, instances] of byName) {\n const toolName = interactableToolName(name);\n if (tools[toolName]) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `[Interactables] interactable names \"${name}\" and another registered name ` +\n `both sanitize to the tool name \"${toolName}\". Rename one of them.`,\n );\n }\n continue;\n }\n\n const first = instances[0]!;\n const partialSchema = partialSchemaCache.get(first.id);\n const idKeyedFields =\n partialSchema && isRecord(partialSchema.properties)\n ? idKeyedArrayFieldNames(partialSchema.properties)\n : new Set<string>();\n\n // `id` resolves to a definition of this name; an id-less call is accepted\n // only while exactly one instance exists.\n const resolveTarget = (\n id: unknown,\n ): Unstable_InteractableDefinition | undefined => {\n if (typeof id === \"string\") {\n const def = definitions[id];\n return def?.name === name ? def : undefined;\n }\n return instances.length === 1 ? first : undefined;\n };\n\n tools[toolName] = {\n type: \"frontend\",\n description:\n `Update the state of interactable component \"${name}\". ${first.description} ` +\n `Pass the id of the instance to update — instance ids and current state ` +\n `appear in the conversation as state snapshots. Only include the fields ` +\n `you want to change; omitted fields keep their current values.`,\n parameters: withRequiredId(partialSchema),\n streamCall: async (reader, { toolCallId }) => {\n try {\n for await (const partialArgs of reader.args.streamValues()) {\n if (!partialArgs || typeof partialArgs !== \"object\") continue;\n const args = partialArgs as Record<string, unknown>;\n const keys = Object.keys(args);\n const idIndex = keys.indexOf(\"id\");\n if (idIndex === keys.length - 1) continue;\n\n const { id, ...partial } = args;\n if (Object.keys(partial).length === 0) continue;\n const target = resolveTarget(id);\n if (!target) continue;\n\n const baseline = streamBaselines.get(toolCallId);\n const arrayBaseline =\n baseline?.targetId === target.id ? baseline.state : target.state;\n if (!baseline || baseline.targetId !== target.id) {\n streamBaselines.set(toolCallId, {\n targetId: target.id,\n state: target.state,\n });\n }\n\n setDefState(target.id, (prev) =>\n shallowMergeInteractableState(prev, partial, { arrayBaseline }),\n );\n }\n } catch {\n // Non-fatal: execute handles the final state\n }\n },\n execute: async (args: unknown, { toolCallId }) => {\n const { id, ...partial } = (args ?? {}) as Record<string, unknown>;\n const target = resolveTarget(id);\n if (!target) {\n const validIds = instances.map((d) => d.id);\n return {\n success: false,\n error: `Unknown id ${JSON.stringify(id)} for interactable \"${name}\". Valid ids: ${validIds.join(\", \")}`,\n };\n }\n const baseline = streamBaselines.get(toolCallId);\n streamBaselines.delete(toolCallId);\n const addedItemIds: Record<string, string[]> = {};\n setDefState(target.id, (prev) =>\n shallowMergeInteractableState(prev, partial, {\n arrayBaseline:\n baseline?.targetId === target.id ? baseline.state : undefined,\n idFactory: (field) => {\n const itemId = generateId();\n (addedItemIds[field] ??= []).push(itemId);\n return itemId;\n },\n idKeyedFields,\n }),\n );\n // The resolved id lets an id-less call's UI (and the model) address\n // the instance that was actually updated.\n const result: {\n success: true;\n id: string;\n addedItemIds?: Record<string, string[]>;\n } = { success: true, id: target.id };\n if (Object.keys(addedItemIds).length > 0) {\n result.addedItemIds = addedItemIds;\n }\n return result;\n },\n };\n }\n\n const interactables: Unstable_InteractableSnapshotEntry[] = entries.map(\n (def) => ({\n id: def.id,\n name: def.name,\n state: def.state,\n }),\n );\n return { tools, unstable_composerMetadata: { interactables } };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"interactable-model-context.js","names":["Tool","toJSONSchema","Unstable_InteractableDefinition","interactableToolName","shallowMergeInteractableState","Unstable_InteractableSnapshotEntry","generateId","isRecord","PartialJSONSchema","ReturnType","ID_PROPERTY","type","const","description","hasIdProperty","schema","Record","properties","id","undefined","withRequiredItemId","required","withoutItemId","_omitted","Array","isArray","filter","key","toArrayUpdateSchema","field","itemSchema","items","idKeyed","add","remove","clear","update","additionalProperties","idKeyedArrayFieldNames","Set","names","value","Object","entries","withArrayUpdateSchemas","fromEntries","map","withRequiredId","partial","process","env","NODE_ENV","console","warn","_reserved","buildInteractableModelContext","definitions","partialSchemaCache","Map","setDefState","updater","prev","streamBaselines","targetId","state","tools","unstable_composerMetadata","values","length","byName","def","list","get","name","push","set","instances","toolName","first","partialSchema","idKeyedFields","resolveTarget","parameters","streamCall","reader","toolCallId","partialArgs","args","streamValues","keys","idIndex","indexOf","target","baseline","arrayBaseline","execute","validIds","d","success","error","JSON","stringify","join","delete","addedItemIds","idFactory","itemId","result","interactables"],"sources":["../../../src/react/client/interactable-model-context.ts"],"sourcesContent":["import type { Tool } from \"assistant-stream\";\nimport { toJSONSchema } from \"assistant-stream\";\nimport type { Unstable_InteractableDefinition } from \"../types/scopes/interactables\";\nimport {\n interactableToolName,\n shallowMergeInteractableState,\n type Unstable_InteractableSnapshotEntry,\n} from \"../../model-context/interactable-composer-metadata\";\nimport { generateId } from \"../../utils/id\";\nimport { isRecord } from \"../../utils/json/is-json\";\n\nexport type PartialJSONSchema = ReturnType<typeof toJSONSchema>;\n\nconst ID_PROPERTY = {\n type: \"string\" as const,\n description:\n \"The id of the instance to update, as shown in its state snapshot in the conversation.\",\n};\n\nconst hasIdProperty = (schema: Record<string, unknown>) => {\n const properties = schema.properties;\n return isRecord(properties) && properties.id !== undefined;\n};\n\nconst withRequiredItemId = (schema: Record<string, unknown>) => ({\n ...schema,\n required: [\"id\"],\n});\n\n// The framework assigns ids to new items, so the model never sees the `id`\n// field when adding (it can't address an item that doesn't exist yet).\nconst withoutItemId = (schema: Record<string, unknown>) => {\n const { id: _omitted, ...properties } = isRecord(schema.properties)\n ? schema.properties\n : {};\n const required = Array.isArray(schema.required)\n ? schema.required.filter((key) => key !== \"id\")\n : schema.required;\n return { ...schema, properties, required };\n};\n\nconst toArrayUpdateSchema = (schema: unknown, field: string) => {\n if (!isRecord(schema) || schema.type !== \"array\") return schema;\n const itemSchema = schema.items;\n if (Array.isArray(itemSchema) || !isRecord(itemSchema)) return schema;\n\n const idKeyed = hasIdProperty(itemSchema);\n const properties: Record<string, unknown> = {\n add: {\n type: \"array\",\n items: idKeyed ? withoutItemId(itemSchema) : itemSchema,\n },\n remove: {\n type: \"array\",\n items: idKeyed ? ID_PROPERTY : itemSchema,\n },\n clear: { type: \"boolean\" },\n };\n\n if (idKeyed) {\n properties.update = {\n type: \"array\",\n items: withRequiredItemId(itemSchema),\n };\n }\n\n return {\n type: \"object\" as const,\n description:\n `Operations for array field \"${field}\". To change one item use update ` +\n `with its id; add new items (their ids are assigned for you), remove items ` +\n `by id, or clear to empty. Change only the items you mean to — never resend ` +\n `the whole array to edit one item.`,\n properties,\n additionalProperties: false,\n };\n};\n\n// Top-level array fields whose items carry an `id` — the fields the framework\n// mints ids for on add.\nconst idKeyedArrayFieldNames = (\n properties: Record<string, unknown>,\n): Set<string> => {\n const names = new Set<string>();\n for (const [key, value] of Object.entries(properties)) {\n if (\n isRecord(value) &&\n value.type === \"array\" &&\n isRecord(value.items) &&\n hasIdProperty(value.items)\n ) {\n names.add(key);\n }\n }\n return names;\n};\n\nconst withArrayUpdateSchemas = (properties: Record<string, unknown>) =>\n Object.fromEntries(\n Object.entries(properties).map(([key, value]) => [\n key,\n toArrayUpdateSchema(value, key),\n ]),\n );\n\n/**\n * Wraps an interactable's partial state schema with the required `id`\n * parameter. Falls back to a permissive schema when the partial conversion\n * failed at registration time.\n */\nfunction withRequiredId(partial: PartialJSONSchema | undefined) {\n if (!partial || typeof partial !== \"object\" || partial.type !== \"object\") {\n return {\n type: \"object\" as const,\n properties: { id: ID_PROPERTY },\n required: [\"id\"],\n additionalProperties: true,\n };\n }\n if (process.env.NODE_ENV !== \"production\" && partial.properties?.id) {\n console.warn(\n `[Interactables] a top-level \"id\" field in an interactable's stateSchema is ` +\n `reserved for instance addressing by the update tool and cannot be updated ` +\n `by the model. Rename the field to make it model-writable.`,\n );\n }\n const { id: _reserved, ...properties } = partial.properties ?? {};\n return {\n ...partial,\n properties: { id: ID_PROPERTY, ...withArrayUpdateSchemas(properties) },\n required: [\"id\"],\n };\n}\n\nexport function buildInteractableModelContext(\n definitions: Record<string, Unstable_InteractableDefinition>,\n partialSchemaCache: Map<string, PartialJSONSchema>,\n setDefState: (id: string, updater: (prev: unknown) => unknown) => void,\n streamBaselines = new Map<string, { targetId: string; state: unknown }>(),\n):\n | {\n tools: Record<string, Tool<any, any>>;\n unstable_composerMetadata?: Record<string, unknown>;\n }\n | undefined {\n const entries = Object.values(definitions);\n if (entries.length === 0) return undefined;\n\n const byName = new Map<string, Unstable_InteractableDefinition[]>();\n for (const def of entries) {\n const list = byName.get(def.name) ?? [];\n list.push(def);\n byName.set(def.name, list);\n }\n\n const tools: Record<string, Tool<any, any>> = {};\n\n for (const [name, instances] of byName) {\n const toolName = interactableToolName(name);\n if (tools[toolName]) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `[Interactables] interactable names \"${name}\" and another registered name ` +\n `both sanitize to the tool name \"${toolName}\". Rename one of them.`,\n );\n }\n continue;\n }\n\n const first = instances[0]!;\n const partialSchema = partialSchemaCache.get(first.id);\n const idKeyedFields =\n partialSchema && isRecord(partialSchema.properties)\n ? idKeyedArrayFieldNames(partialSchema.properties)\n : new Set<string>();\n\n // `id` resolves to a definition of this name; an id-less call is accepted\n // only while exactly one instance exists.\n const resolveTarget = (\n id: unknown,\n ): Unstable_InteractableDefinition | undefined => {\n if (typeof id === \"string\") {\n const def = definitions[id];\n return def?.name === name ? def : undefined;\n }\n return instances.length === 1 ? first : undefined;\n };\n\n tools[toolName] = {\n type: \"frontend\",\n description:\n `Update the state of interactable component \"${name}\". ${first.description} ` +\n `Pass the id of the instance to update — instance ids and current state ` +\n `appear in the conversation as state snapshots. Only include the fields ` +\n `you want to change; omitted fields keep their current values.`,\n parameters: withRequiredId(partialSchema),\n streamCall: async (reader, { toolCallId }) => {\n try {\n for await (const partialArgs of reader.args.streamValues()) {\n if (!partialArgs || typeof partialArgs !== \"object\") continue;\n const args = partialArgs as Record<string, unknown>;\n const keys = Object.keys(args);\n const idIndex = keys.indexOf(\"id\");\n if (idIndex === keys.length - 1) continue;\n\n const { id, ...partial } = args;\n if (Object.keys(partial).length === 0) continue;\n const target = resolveTarget(id);\n if (!target) continue;\n\n const baseline = streamBaselines.get(toolCallId);\n const arrayBaseline =\n baseline?.targetId === target.id ? baseline.state : target.state;\n if (!baseline || baseline.targetId !== target.id) {\n streamBaselines.set(toolCallId, {\n targetId: target.id,\n state: target.state,\n });\n }\n\n setDefState(target.id, (prev) =>\n shallowMergeInteractableState(prev, partial, { arrayBaseline }),\n );\n }\n } catch {\n // Non-fatal: execute handles the final state\n }\n },\n execute: async (args: unknown, { toolCallId }) => {\n const { id, ...partial } = (args ?? {}) as Record<string, unknown>;\n const target = resolveTarget(id);\n if (!target) {\n const validIds = instances.map((d) => d.id);\n return {\n success: false,\n error: `Unknown id ${JSON.stringify(id)} for interactable \"${name}\". Valid ids: ${validIds.join(\", \")}`,\n };\n }\n const baseline = streamBaselines.get(toolCallId);\n streamBaselines.delete(toolCallId);\n const addedItemIds: Record<string, string[]> = {};\n setDefState(target.id, (prev) =>\n shallowMergeInteractableState(prev, partial, {\n arrayBaseline:\n baseline?.targetId === target.id ? baseline.state : undefined,\n idFactory: (field) => {\n const itemId = generateId();\n (addedItemIds[field] ??= []).push(itemId);\n return itemId;\n },\n idKeyedFields,\n }),\n );\n // The resolved id lets an id-less call's UI (and the model) address\n // the instance that was actually updated.\n const result: {\n success: true;\n id: string;\n addedItemIds?: Record<string, string[]>;\n } = { success: true, id: target.id };\n if (Object.keys(addedItemIds).length > 0) {\n result.addedItemIds = addedItemIds;\n }\n return result;\n },\n };\n }\n\n const interactables: Unstable_InteractableSnapshotEntry[] = entries.map(\n (def) => ({\n id: def.id,\n name: def.name,\n state: def.state,\n }),\n );\n return { tools, unstable_composerMetadata: { interactables } };\n}\n"],"mappings":";;;;;AAaA,MAAMU,cAAc;CAClBC,MAAM;CACNE,aACE;AACJ;AAEA,MAAMC,iBAAiBC,WAAoC;CACzD,MAAME,aAAaF,OAAOE;CAC1B,OAAOV,SAASU,UAAU,KAAKA,WAAWC,OAAOC,KAAAA;AACnD;AAEA,MAAMC,sBAAsBL,YAAqC;CAC/D,GAAGA;CACHM,UAAU,CAAC,IAAI;AACjB;AAIA,MAAMC,iBAAiBP,WAAoC;CACzD,MAAM,EAAEG,IAAIK,UAAU,GAAGN,eAAeV,SAASQ,OAAOE,UAAU,IAC9DF,OAAOE,aACP,CAAC;CACL,MAAMI,WAAWG,MAAMC,QAAQV,OAAOM,QAAQ,IAC1CN,OAAOM,SAASK,QAAQC,QAAQA,QAAQ,IAAI,IAC5CZ,OAAOM;CACX,OAAO;EAAE,GAAGN;EAAQE;EAAYI;CAAS;AAC3C;AAEA,MAAMO,uBAAuBb,QAAiBc,UAAkB;CAC9D,IAAI,CAACtB,SAASQ,MAAM,KAAKA,OAAOJ,SAAS,SAAS,OAAOI;CACzD,MAAMe,aAAaf,OAAOgB;CAC1B,IAAIP,MAAMC,QAAQK,UAAU,KAAK,CAACvB,SAASuB,UAAU,GAAG,OAAOf;CAE/D,MAAMiB,UAAUlB,cAAcgB,UAAU;CACxC,MAAMb,aAAsC;EAC1CgB,KAAK;GACHtB,MAAM;GACNoB,OAAOC,UAAUV,cAAcQ,UAAU,IAAIA;EAC/C;EACAI,QAAQ;GACNvB,MAAM;GACNoB,OAAOC,UAAUtB,cAAcoB;EACjC;EACAK,OAAO,EAAExB,MAAM,UAAU;CAC3B;CAEA,IAAIqB,SACFf,WAAWmB,SAAS;EAClBzB,MAAM;EACNoB,OAAOX,mBAAmBU,UAAU;CACtC;CAGF,OAAO;EACLnB,MAAM;EACNE,aACE,+BAA+BgB,MAAK;EAItCZ;EACAoB,sBAAsB;CACxB;AACF;AAIA,MAAMC,0BACJrB,eACgB;CAChB,MAAMuB,wBAAQ,IAAID,IAAY;CAC9B,KAAK,MAAM,CAACZ,KAAKc,UAAUC,OAAOC,QAAQ1B,UAAU,GAClD,IACEV,SAASkC,KAAK,KACdA,MAAM9B,SAAS,WACfJ,SAASkC,MAAMV,KAAK,KACpBjB,cAAc2B,MAAMV,KAAK,GAEzBS,MAAMP,IAAIN,GAAG;CAGjB,OAAOa;AACT;AAEA,MAAMI,0BAA0B3B,eAC9ByB,OAAOG,YACLH,OAAOC,QAAQ1B,UAAU,CAAC,CAAC6B,KAAK,CAACnB,KAAKc,WAAW,CAC/Cd,KACAC,oBAAoBa,OAAOd,GAAG,CAAC,CAChC,CACH;;;;;;AAOF,SAASoB,eAAeC,SAAwC;CAC9D,IAAI,CAACA,WAAW,OAAOA,YAAY,YAAYA,QAAQrC,SAAS,UAC9D,OAAO;EACLA,MAAM;EACNM,YAAY,EAAEC,IAAIR,YAAY;EAC9BW,UAAU,CAAC,IAAI;EACfgB,sBAAsB;CACxB;CAEF,IAAIY,QAAQC,IAAIC,aAAa,gBAAgBH,QAAQ/B,YAAYC,IAC/DkC,QAAQC,KACN,kNAGF;CAEF,MAAM,EAAEnC,IAAIoC,WAAW,GAAGrC,eAAe+B,QAAQ/B,cAAc,CAAC;CAChE,OAAO;EACL,GAAG+B;EACH/B,YAAY;GAAEC,IAAIR;GAAa,GAAGkC,uBAAuB3B,UAAU;EAAE;EACrEI,UAAU,CAAC,IAAI;CACjB;AACF;AAEA,SAAgBkC,8BACdC,aACAC,oBACAE,aACAG,kCAAkB,IAAIJ,IAAkD,GAM5D;CACZ,MAAMf,UAAUD,OAAOyB,OAAOX,WAAW;CACzC,IAAIb,QAAQyB,WAAW,GAAG,OAAOjD,KAAAA;CAEjC,MAAMkD,yBAAS,IAAIX,IAA+C;CAClE,KAAK,MAAMY,OAAO3B,SAAS;EACzB,MAAM4B,OAAOF,OAAOG,IAAIF,IAAIG,IAAI,KAAK,CAAA;EACrCF,KAAKG,KAAKJ,GAAG;EACbD,OAAOM,IAAIL,IAAIG,MAAMF,IAAI;CAC3B;CAEA,MAAMN,QAAwC,CAAC;CAE/C,KAAK,MAAM,CAACQ,MAAMG,cAAcP,QAAQ;EACtC,MAAMQ,WAAW1E,qBAAqBsE,IAAI;EAC1C,IAAIR,MAAMY,WAAW;GACnB,IAAI5B,QAAQC,IAAIC,aAAa,cAC3BC,QAAQC,KACN,uCAAuCoB,KAAI,gEACNI,SAAQ,uBAC/C;GAEF;EACF;EAEA,MAAMC,QAAQF,UAAU;EACxB,MAAMG,gBAAgBtB,mBAAmBe,IAAIM,MAAM5D,EAAE;EACrD,MAAM8D,gBACJD,iBAAiBxE,SAASwE,cAAc9D,UAAU,IAC9CqB,uBAAuByC,cAAc9D,UAAU,oBAC/C,IAAIsB,IAAY;EAItB,MAAM0C,iBACJ/D,OACgD;GAChD,IAAI,OAAOA,OAAO,UAAU;IAC1B,MAAMoD,MAAMd,YAAYtC;IACxB,OAAOoD,KAAKG,SAASA,OAAOH,MAAMnD,KAAAA;GACpC;GACA,OAAOyD,UAAUR,WAAW,IAAIU,QAAQ3D,KAAAA;EAC1C;EAEA8C,MAAMY,YAAY;GAChBlE,MAAM;GACNE,aACE,+CAA+C4D,KAAI,KAAMK,MAAMjE,YAAW;GAI5EqE,YAAYnC,eAAegC,aAAa;GACxCI,YAAY,OAAOC,QAAQ,EAAEC,iBAAiB;IAC5C,IAAI;KACF,WAAW,MAAMC,eAAeF,OAAOG,KAAKC,aAAa,GAAG;MAC1D,IAAI,CAACF,eAAe,OAAOA,gBAAgB,UAAU;MACrD,MAAMC,OAAOD;MACb,MAAMG,OAAO/C,OAAO+C,KAAKF,IAAI;MAE7B,IADgBE,KAAKE,QAAQ,IACzBD,MAAYD,KAAKrB,SAAS,GAAG;MAEjC,MAAM,EAAElD,IAAI,GAAG8B,YAAYuC;MAC3B,IAAI7C,OAAO+C,KAAKzC,OAAO,CAAC,CAACoB,WAAW,GAAG;MACvC,MAAMwB,SAASX,cAAc/D,EAAE;MAC/B,IAAI,CAAC0E,QAAQ;MAEb,MAAMC,WAAW/B,gBAAgBU,IAAIa,UAAU;MAC/C,MAAMS,gBACJD,UAAU9B,aAAa6B,OAAO1E,KAAK2E,SAAS7B,QAAQ4B,OAAO5B;MAC7D,IAAI,CAAC6B,YAAYA,SAAS9B,aAAa6B,OAAO1E,IAC5C4C,gBAAgBa,IAAIU,YAAY;OAC9BtB,UAAU6B,OAAO1E;OACjB8C,OAAO4B,OAAO5B;MAChB,CAAC;MAGHL,YAAYiC,OAAO1E,KAAK2C,SACtBzD,8BAA8ByD,MAAMb,SAAS,EAAE8C,cAAc,CAAC,CAChE;KACF;IACF,QAAQ,CACN;GAEJ;GACAC,SAAS,OAAOR,MAAe,EAAEF,iBAAiB;IAChD,MAAM,EAAEnE,IAAI,GAAG8B,YAAauC,QAAQ,CAAC;IACrC,MAAMK,SAASX,cAAc/D,EAAE;IAC/B,IAAI,CAAC0E,QAAQ;KACX,MAAMI,WAAWpB,UAAU9B,KAAKmD,MAAMA,EAAE/E,EAAE;KAC1C,OAAO;MACLgF,SAAS;MACTC,OAAO,cAAcC,KAAKC,UAAUnF,EAAE,EAAC,qBAAsBuD,KAAI,gBAAiBuB,SAASM,KAAK,IAAI;KACtG;IACF;IACA,MAAMT,WAAW/B,gBAAgBU,IAAIa,UAAU;IAC/CvB,gBAAgByC,OAAOlB,UAAU;IACjC,MAAMmB,eAAyC,CAAC;IAChD7C,YAAYiC,OAAO1E,KAAK2C,SACtBzD,8BAA8ByD,MAAMb,SAAS;KAC3C8C,eACED,UAAU9B,aAAa6B,OAAO1E,KAAK2E,SAAS7B,QAAQ7C,KAAAA;KACtDsF,YAAY5E,UAAU;MACpB,MAAM6E,SAASpG,WAAW;MAC1B,CAACkG,aAAa3E,WAAW,CAAA,EAAA,CAAI6C,KAAKgC,MAAM;MACxC,OAAOA;KACT;KACA1B;IACF,CAAC,CACH;IAGA,MAAM2B,SAIF;KAAET,SAAS;KAAMhF,IAAI0E,OAAO1E;IAAG;IACnC,IAAIwB,OAAO+C,KAAKe,YAAY,CAAC,CAACpC,SAAS,GACrCuC,OAAOH,eAAeA;IAExB,OAAOG;GACT;EACF;CACF;CASA,OAAO;EAAE1C;EAAOC,2BAA2B,EAAE0C,eAPejE,QAAQG,KACjEwB,SAAS;GACRpD,IAAIoD,IAAIpD;GACRuD,MAAMH,IAAIG;GACVT,OAAOM,IAAIN;EACb,EAE2C4C,EAAc;CAAE;AAC/D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useInteractableState.js","names":["useCallback","useAui","useAuiState","StateUpdater","TState","prev","useInteractableState","id","fallback","$","_c","aui","state","s","interactables","definitions","t0","s_0","persistence","persistenceStatus","t1","updater","setState","t2","selected","setSelected","t3","flush","t4","isPending","t5","error","t6","t7"],"sources":["../../../src/react/interactables-legacy/useInteractableState.ts"],"sourcesContent":["import { useCallback } from \"react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\n\ntype StateUpdater<TState> = TState | ((prev: TState) => TState);\n\n/**\n * Reads and writes the state of a registered interactable.\n *\n * Pair with {@link useAssistantInteractable} which handles registration.\n *\n * @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API.\n * Scheduled for removal on/after 2026-09-14. See\n * {@link https://www.assistant-ui.com/docs/tools/interactables#migrating-from-the-previous-api | Interactables migration guide}.\n */\nexport const useInteractableState = <TState>(\n id: string,\n fallback: TState,\n): [\n TState,\n {\n setState: (updater: StateUpdater<TState>) => void;\n setSelected: (selected: boolean) => void;\n isPending: boolean;\n error: unknown;\n flush: () => Promise<void>;\n },\n] => {\n const aui = useAui();\n\n const state =\n (useAuiState((s) => s.interactables.definitions[id]?.state) as TState) ??\n (fallback as TState);\n\n const persistenceStatus = useAuiState((s) => s.interactables.persistence[id]);\n\n const setState = useCallback(\n (updater: StateUpdater<TState>) => {\n aui.interactables().setState(id, (prev) => {\n if (typeof updater === \"function\") {\n return (updater as (prev: TState) => TState)(prev as TState);\n }\n return updater;\n });\n },\n [aui, id],\n );\n\n const setSelected = useCallback(\n (selected: boolean) => {\n aui.interactables().setSelected(id, selected);\n },\n [aui, id],\n );\n\n const flush = useCallback(() => aui.interactables().flush(), [aui]);\n\n return [\n state,\n {\n setState,\n setSelected,\n isPending: persistenceStatus?.isPending ?? false,\n error: persistenceStatus?.error,\n flush,\n },\n ];\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"useInteractableState.js","names":["useCallback","useAui","useAuiState","StateUpdater","TState","prev","useInteractableState","id","fallback","$","_c","aui","state","s","interactables","definitions","t0","s_0","persistence","persistenceStatus","t1","updater","setState","t2","selected","setSelected","t3","flush","t4","isPending","t5","error","t6","t7"],"sources":["../../../src/react/interactables-legacy/useInteractableState.ts"],"sourcesContent":["import { useCallback } from \"react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\n\ntype StateUpdater<TState> = TState | ((prev: TState) => TState);\n\n/**\n * Reads and writes the state of a registered interactable.\n *\n * Pair with {@link useAssistantInteractable} which handles registration.\n *\n * @deprecated Since 2026-06-14 — migrate to the Unstable / Experimental API.\n * Scheduled for removal on/after 2026-09-14. See\n * {@link https://www.assistant-ui.com/docs/tools/interactables#migrating-from-the-previous-api | Interactables migration guide}.\n */\nexport const useInteractableState = <TState>(\n id: string,\n fallback: TState,\n): [\n TState,\n {\n setState: (updater: StateUpdater<TState>) => void;\n setSelected: (selected: boolean) => void;\n isPending: boolean;\n error: unknown;\n flush: () => Promise<void>;\n },\n] => {\n const aui = useAui();\n\n const state =\n (useAuiState((s) => s.interactables.definitions[id]?.state) as TState) ??\n (fallback as TState);\n\n const persistenceStatus = useAuiState((s) => s.interactables.persistence[id]);\n\n const setState = useCallback(\n (updater: StateUpdater<TState>) => {\n aui.interactables().setState(id, (prev) => {\n if (typeof updater === \"function\") {\n return (updater as (prev: TState) => TState)(prev as TState);\n }\n return updater;\n });\n },\n [aui, id],\n );\n\n const setSelected = useCallback(\n (selected: boolean) => {\n aui.interactables().setSelected(id, selected);\n },\n [aui, id],\n );\n\n const flush = useCallback(() => aui.interactables().flush(), [aui]);\n\n return [\n state,\n {\n setState,\n setSelected,\n isPending: persistenceStatus?.isPending ?? false,\n error: persistenceStatus?.error,\n flush,\n },\n ];\n};\n"],"mappings":";;;;;;;;;;;;;AAcA,MAAaM,wBAAuBC,IAAAC,aAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAalC,MAAAC,MAAYV,OAAO;CAEnB,MAAAW,QACGV,aAAYW,MAAOA,EAACC,cAAcC,YAAaR,GAAU,EAAAK,KAAA,KACzDJ;CAAoB,IAAAQ;CAAA,IAAAP,EAAA,OAAAF,IAAA;EAEeS,MAAAC,QAAOJ,IAACC,cAAcI,YAAaX;EAAGE,EAAA,KAAAF;EAAAE,EAAA,KAAAO;CAAA,OAAAA,KAAAP,EAAA;CAA5E,MAAAU,oBAA0BjB,YAAYc,EAAsC;CAAE,IAAAI;CAAA,IAAAX,EAAA,OAAAE,OAAAF,EAAA,OAAAF,IAAA;EAG5Ea,MAAAC,YAAA;GACEV,IAAGG,cAAe,CAAC,CAAAQ,SAAUf,KAAIF,SAAA;IAC/B,IAAI,OAAOgB,YAAY,YAAU,OACvBA,QAAqChB,IAAc;IAC5D,OACMgB;GAAO,CACf;EAAC;EACHZ,EAAA,KAAAE;EAAAF,EAAA,KAAAF;EAAAE,EAAA,KAAAW;CAAA,OAAAA,KAAAX,EAAA;CARH,MAAAa,WAAiBF;CAUf,IAAAG;CAAA,IAAAd,EAAA,OAAAE,OAAAF,EAAA,OAAAF,IAAA;EAGAgB,MAAAC,aAAA;GACEb,IAAGG,cAAe,CAAC,CAAAW,YAAalB,IAAIiB,QAAQ;EAAC;EAC9Cf,EAAA,KAAAE;EAAAF,EAAA,KAAAF;EAAAE,EAAA,KAAAc;CAAA,OAAAA,KAAAd,EAAA;CAHH,MAAAgB,cAAoBF;CAKlB,IAAAG;CAAA,IAAAjB,EAAA,OAAAE,KAAA;EAEwBe,WAAMf,IAAGG,cAAe,CAAC,CAAAa,MAAO;EAAClB,EAAA,KAAAE;EAAAF,EAAA,KAAAiB;CAAA,OAAAA,KAAAjB,EAAA;CAA3D,MAAAkB,QAAcD;CAOC,MAAAE,KAAAT,mBAAiBU,aAAjB;CACJ,MAAAC,KAAAX,mBAAiBY;CAAO,IAAAC;CAAA,IAAAvB,EAAA,QAAAkB,SAAAlB,EAAA,QAAAgB,eAAAhB,EAAA,QAAAa,YAAAb,EAAA,QAAAmB,MAAAnB,EAAA,QAAAqB,IAAA;EAJjCE,KAAA;GAAAV;GAAAG;GAAAI,WAGaD;GAAqCG,OACzCD;GAAwBH;EAEjC;EAAClB,EAAA,MAAAkB;EAAAlB,EAAA,MAAAgB;EAAAhB,EAAA,MAAAa;EAAAb,EAAA,MAAAmB;EAAAnB,EAAA,MAAAqB;EAAArB,EAAA,MAAAuB;CAAA,OAAAA,KAAAvB,EAAA;CAAA,IAAAwB;CAAA,IAAAxB,EAAA,QAAAG,SAAAH,EAAA,QAAAuB,IAAA;EARIC,KAAA,CACLrB,OACAoB,EAMC;EACFvB,EAAA,MAAAG;EAAAH,EAAA,MAAAuB;EAAAvB,EAAA,MAAAwB;CAAA,OAAAA,KAAAxB,EAAA;CAAA,OATMwB;AASN"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
3
|
+
import "@assistant-ui/tap/react-shim";
|
|
3
4
|
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
4
5
|
//#region src/react/model-context/useInteractableState.ts
|
|
5
6
|
const useInteractableState = (id) => {
|