@assistant-ui/core 0.2.12 → 0.2.14
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 +3 -1
- package/dist/adapters/thread-history.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js.map +1 -1
- package/dist/react/AssistantProvider.js +6 -1
- package/dist/react/AssistantProvider.js.map +1 -1
- package/dist/react/RuntimeAdapter.d.ts +1 -1
- package/dist/react/RuntimeAdapter.d.ts.map +1 -1
- package/dist/react/RuntimeAdapter.js +16 -6
- package/dist/react/RuntimeAdapter.js.map +1 -1
- package/dist/react/client/DataRenderers.d.ts +1 -8
- package/dist/react/client/DataRenderers.d.ts.map +1 -1
- package/dist/react/client/DataRenderers.js +3 -2
- package/dist/react/client/DataRenderers.js.map +1 -1
- package/dist/react/client/Interactables.d.ts +1 -1
- package/dist/react/client/Interactables.d.ts.map +1 -1
- package/dist/react/client/Interactables.js +4 -3
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/Tools.d.ts +2 -13
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +4 -3
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.d.ts +3 -2
- package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageGroupedParts.js +4 -4
- package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
- package/dist/react/primitives/message/MessageParts.d.ts +28 -1
- package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageParts.js +43 -9
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/providers/TextMessagePartProvider.d.ts.map +1 -1
- package/dist/react/providers/TextMessagePartProvider.js +3 -2
- package/dist/react/providers/TextMessagePartProvider.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +2 -0
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +2 -0
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +1 -0
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +6 -0
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +2 -0
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/utils/groupParts.d.ts +13 -1
- package/dist/react/utils/groupParts.d.ts.map +1 -1
- package/dist/react/utils/groupParts.js +17 -5
- package/dist/react/utils/groupParts.js.map +1 -1
- package/dist/runtime/api/bindings.d.ts +1 -0
- package/dist/runtime/api/bindings.d.ts.map +1 -1
- package/dist/runtime/api/message-runtime.d.ts +2 -0
- package/dist/runtime/api/message-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-runtime.js +5 -0
- package/dist/runtime/api/message-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +1 -0
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +3 -0
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +4 -0
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -0
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/branch/external-thread-branch-adapter.d.ts +30 -0
- package/dist/runtime/branch/external-thread-branch-adapter.d.ts.map +1 -0
- package/dist/runtime/branch/external-thread-branch-adapter.js +0 -0
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +1 -0
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +2 -0
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-adapter.d.ts +1 -0
- package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +1 -0
- 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 +13 -0
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/local/local-runtime-options.d.ts +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +8 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +63 -5
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/local/should-continue.js +4 -2
- package/dist/runtimes/local/should-continue.js.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +2 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +4 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.js +4 -0
- package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +1 -0
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.js +1 -0
- package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
- package/dist/runtimes/remote-thread-list/types.d.ts +1 -0
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/store/clients/chain-of-thought-client.d.ts +2 -7
- package/dist/store/clients/chain-of-thought-client.d.ts.map +1 -1
- package/dist/store/clients/chain-of-thought-client.js +3 -2
- package/dist/store/clients/chain-of-thought-client.js.map +1 -1
- package/dist/store/clients/model-context-client.d.ts +1 -1
- package/dist/store/clients/model-context-client.d.ts.map +1 -1
- package/dist/store/clients/model-context-client.js +3 -2
- package/dist/store/clients/model-context-client.js.map +1 -1
- package/dist/store/clients/no-op-composer-client.d.ts +2 -4
- package/dist/store/clients/no-op-composer-client.d.ts.map +1 -1
- package/dist/store/clients/no-op-composer-client.js +3 -2
- package/dist/store/clients/no-op-composer-client.js.map +1 -1
- package/dist/store/clients/runtime-adapter.d.ts +1 -3
- package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
- package/dist/store/clients/runtime-adapter.js +2 -15
- package/dist/store/clients/runtime-adapter.js.map +1 -1
- package/dist/store/clients/suggestions.d.ts +1 -4
- package/dist/store/clients/suggestions.d.ts.map +1 -1
- package/dist/store/clients/suggestions.js +6 -4
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/clients/thread-message-client.d.ts +1 -1
- package/dist/store/clients/thread-message-client.d.ts.map +1 -1
- package/dist/store/clients/thread-message-client.js +14 -10
- package/dist/store/clients/thread-message-client.js.map +1 -1
- package/dist/store/internal.d.ts +2 -2
- package/dist/store/internal.js +2 -2
- package/dist/store/runtime-clients/attachment-runtime-client.d.ts +2 -4
- package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/attachment-runtime-client.js +3 -2
- package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.d.ts +2 -10
- package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js +9 -6
- package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/message-part-runtime-client.d.ts +2 -4
- package/dist/store/runtime-clients/message-part-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/message-part-runtime-client.js +3 -2
- package/dist/store/runtime-clients/message-part-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.d.ts +2 -7
- package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.js +10 -6
- package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts +2 -4
- package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js +3 -2
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.d.ts +2 -5
- package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js +6 -4
- package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.d.ts +2 -4
- package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +7 -4
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scopes/message.d.ts +1 -0
- package/dist/store/scopes/message.d.ts.map +1 -1
- package/dist/store/scopes/thread-list-item.d.ts +1 -0
- package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
- package/dist/store/scopes/thread.d.ts +1 -0
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/adapters/thread-history.ts +2 -0
- package/src/index.ts +1 -0
- package/src/react/AssistantProvider.tsx +3 -1
- package/src/react/RuntimeAdapter.ts +25 -8
- package/src/react/client/DataRenderers.ts +42 -45
- package/src/react/client/Interactables.ts +261 -261
- package/src/react/client/Tools.ts +6 -4
- package/src/react/primitives/message/MessageGroupedParts.tsx +19 -7
- package/src/react/primitives/message/MessageParts.tsx +64 -13
- package/src/react/providers/TextMessagePartProvider.tsx +5 -3
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +1 -0
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +11 -0
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +6 -0
- package/src/react/utils/groupParts.ts +27 -0
- package/src/runtime/api/bindings.ts +1 -0
- package/src/runtime/api/message-runtime.ts +7 -0
- package/src/runtime/api/thread-list-runtime.ts +1 -0
- package/src/runtime/api/thread-runtime.ts +7 -0
- package/src/runtime/base/base-thread-runtime-core.ts +1 -0
- package/src/runtime/branch/external-thread-branch-adapter.ts +26 -0
- package/src/runtime/interfaces/thread-list-runtime-core.ts +1 -0
- package/src/runtime/interfaces/thread-runtime-core.ts +2 -0
- package/src/runtimes/external-store/external-store-adapter.ts +1 -0
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +24 -0
- package/src/runtimes/local/local-runtime-options.ts +1 -1
- package/src/runtimes/local/local-thread-runtime-core.test.ts +311 -0
- package/src/runtimes/local/local-thread-runtime-core.ts +104 -7
- package/src/runtimes/local/should-continue.ts +23 -13
- package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +5 -0
- package/src/runtimes/remote-thread-list/empty-thread-core.ts +5 -0
- package/src/runtimes/remote-thread-list/remote-thread-state.ts +2 -0
- package/src/runtimes/remote-thread-list/types.ts +1 -0
- package/src/store/clients/chain-of-thought-client.ts +5 -3
- package/src/store/clients/model-context-client.test.ts +5 -4
- package/src/store/clients/model-context-client.ts +21 -21
- package/src/store/clients/no-op-composer-client.ts +5 -3
- package/src/store/clients/runtime-adapter.ts +0 -24
- package/src/store/clients/suggestions.ts +9 -18
- package/src/store/clients/thread-message-client.ts +29 -26
- package/src/store/internal.ts +1 -4
- package/src/store/runtime-clients/attachment-runtime-client.ts +14 -14
- package/src/store/runtime-clients/composer-runtime-client.ts +30 -24
- package/src/store/runtime-clients/message-part-runtime-client.ts +5 -3
- package/src/store/runtime-clients/message-runtime-client.ts +26 -19
- package/src/store/runtime-clients/thread-list-item-runtime-client.ts +5 -3
- package/src/store/runtime-clients/thread-list-runtime-client.ts +10 -6
- package/src/store/runtime-clients/thread-runtime-client.ts +11 -6
- package/src/store/scopes/message.ts +1 -0
- package/src/store/scopes/thread-list-item.ts +1 -0
- package/src/store/scopes/thread.ts +1 -0
- package/src/tests/external-store-thread-runtime-core.test.ts +57 -0
- package/src/tests/groupMessageParts.test.ts +84 -0
- package/src/tests/groupParts.test.ts +55 -0
|
@@ -26,6 +26,7 @@ type GenericThreadHistoryAdapter<TMessage> = {
|
|
|
26
26
|
load(): Promise<MessageFormatRepository<TMessage>>;
|
|
27
27
|
append(item: MessageFormatItem<TMessage>): Promise<void>;
|
|
28
28
|
update?(item: MessageFormatItem<TMessage>, localMessageId: string): Promise<void>;
|
|
29
|
+
delete?(items: MessageFormatItem<TMessage>[]): Promise<void>;
|
|
29
30
|
reportTelemetry?(items: MessageFormatItem<TMessage>[], options?: {
|
|
30
31
|
durationMs?: number;
|
|
31
32
|
stepTimestamps?: {
|
|
@@ -39,7 +40,8 @@ type ThreadHistoryAdapter = {
|
|
|
39
40
|
unstable_resume?: boolean;
|
|
40
41
|
}>;
|
|
41
42
|
resume?(options: ChatModelRunOptions): AsyncGenerator<ChatModelRunResult, void, unknown>;
|
|
42
|
-
append(item: ExportedMessageRepositoryItem): Promise<void>;
|
|
43
|
+
append(item: ExportedMessageRepositoryItem): Promise<void>;
|
|
44
|
+
delete?(items: ExportedMessageRepositoryItem[]): Promise<void>; /** Required when used with `useAISDKRuntime` / `useChatRuntime`. */
|
|
43
45
|
withFormat?<TMessage, TStorageFormat extends Record<string, unknown>>(formatAdapter: MessageFormatAdapter<TMessage, TStorageFormat>): GenericThreadHistoryAdapter<TMessage>;
|
|
44
46
|
};
|
|
45
47
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-history.d.ts","names":[],"sources":["../../src/adapters/thread-history.ts"],"mappings":";;;;UASiB,mBAAA;EACf,EAAA;EACA,SAAA;EACA,MAAA;EACA,OAAA,EAAS,QAAQ;AAAA;AAAA,UAGF,iBAAA;EACf,QAAA;EACA,OAAA,EAAS,QAAQ;AAAA;AAAA,UAGF,uBAAA;EACf,MAAA;EACA,QAAA,EAAU,iBAAiB,CAAC,QAAA;AAAA;AAAA,UAGb,oBAAA,kCAEQ,MAAA;EAEvB,MAAA;EACA,MAAA,CAAO,IAAA,EAAM,iBAAA,CAAkB,QAAA,IAAY,cAAA;EAC3C,MAAA,CACE,MAAA,EAAQ,mBAAA,CAAoB,cAAA,IAC3B,iBAAA,CAAkB,QAAA;EACrB,KAAA,CAAM,OAAA,EAAS,QAAA;AAAA;AAAA,KAGL,2BAAA;EACV,IAAA,IAAQ,OAAA,CAAQ,uBAAA,CAAwB,QAAA;EACxC,MAAA,CAAO,IAAA,EAAM,iBAAA,CAAkB,QAAA,IAAY,OAAA;EAC3C,MAAA,EACE,IAAA,EAAM,iBAAA,CAAkB,QAAA,GACxB,cAAA,WACC,OAAA;EACH,eAAA,EACE,KAAA,EAAO,iBAAA,CAAkB,QAAA,KACzB,OAAA;IACE,UAAA;IACA,cAAA;MAAmB,QAAA;MAAkB,MAAA;IAAA;EAAA;AAAA;AAAA,KAK/B,oBAAA;EACV,IAAA,IAAQ,OAAA,CAAQ,yBAAA;IAA8B,eAAA;EAAA;EAC9C,MAAA,EACE,OAAA,EAAS,mBAAA,GACR,cAAA,CAAe,kBAAA;EAClB,MAAA,CAAO,IAAA,EAAM,6BAAA,GAAgC,OAAA,
|
|
1
|
+
{"version":3,"file":"thread-history.d.ts","names":[],"sources":["../../src/adapters/thread-history.ts"],"mappings":";;;;UASiB,mBAAA;EACf,EAAA;EACA,SAAA;EACA,MAAA;EACA,OAAA,EAAS,QAAQ;AAAA;AAAA,UAGF,iBAAA;EACf,QAAA;EACA,OAAA,EAAS,QAAQ;AAAA;AAAA,UAGF,uBAAA;EACf,MAAA;EACA,QAAA,EAAU,iBAAiB,CAAC,QAAA;AAAA;AAAA,UAGb,oBAAA,kCAEQ,MAAA;EAEvB,MAAA;EACA,MAAA,CAAO,IAAA,EAAM,iBAAA,CAAkB,QAAA,IAAY,cAAA;EAC3C,MAAA,CACE,MAAA,EAAQ,mBAAA,CAAoB,cAAA,IAC3B,iBAAA,CAAkB,QAAA;EACrB,KAAA,CAAM,OAAA,EAAS,QAAA;AAAA;AAAA,KAGL,2BAAA;EACV,IAAA,IAAQ,OAAA,CAAQ,uBAAA,CAAwB,QAAA;EACxC,MAAA,CAAO,IAAA,EAAM,iBAAA,CAAkB,QAAA,IAAY,OAAA;EAC3C,MAAA,EACE,IAAA,EAAM,iBAAA,CAAkB,QAAA,GACxB,cAAA,WACC,OAAA;EACH,MAAA,EAAQ,KAAA,EAAO,iBAAA,CAAkB,QAAA,MAAc,OAAA;EAC/C,eAAA,EACE,KAAA,EAAO,iBAAA,CAAkB,QAAA,KACzB,OAAA;IACE,UAAA;IACA,cAAA;MAAmB,QAAA;MAAkB,MAAA;IAAA;EAAA;AAAA;AAAA,KAK/B,oBAAA;EACV,IAAA,IAAQ,OAAA,CAAQ,yBAAA;IAA8B,eAAA;EAAA;EAC9C,MAAA,EACE,OAAA,EAAS,mBAAA,GACR,cAAA,CAAe,kBAAA;EAClB,MAAA,CAAO,IAAA,EAAM,6BAAA,GAAgC,OAAA;EAC7C,MAAA,EAAQ,KAAA,EAAO,6BAAA,KAAkC,OAAA,QA9BpC;EAgCb,UAAA,mCAA6C,MAAA,mBAC3C,aAAA,EAAe,oBAAA,CAAqB,QAAA,EAAU,cAAA,IAC7C,2BAAA,CAA4B,QAAA;AAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -44,7 +44,8 @@ import { RemoteThreadInitializeResponse, RemoteThreadListAdapter, RemoteThreadLi
|
|
|
44
44
|
import { CreateAppendMessage, CreateResumeRunConfig, CreateStartRunConfig, ThreadRuntime, ThreadState } from "./runtime/api/thread-runtime.js";
|
|
45
45
|
import { AssistantRuntime } from "./runtime/api/assistant-runtime.js";
|
|
46
46
|
import { ExternalStoreSharedOptions, pickExternalStoreSharedOptions } from "./runtimes/external-store/external-store-shared-options.js";
|
|
47
|
+
import { ExternalThreadBranchAdapter } from "./runtime/branch/external-thread-branch-adapter.js";
|
|
47
48
|
import { MessageQueueController, MessageQueueDriver, createMessageQueue } from "./runtime/queue/message-queue.js";
|
|
48
49
|
import { InMemoryThreadListAdapter } from "./runtimes/remote-thread-list/adapter/in-memory.js";
|
|
49
50
|
import { createRequestHeaders } from "./runtimes/assistant-transport/utils.js";
|
|
50
|
-
export { type AddToolResultOptions, type AppendMessage, type AssistantContextConfig, AssistantFrameHost, AssistantFrameProvider, type AssistantInstructionsConfig, type AssistantRuntime, type AssistantRuntimeCore, type AssistantToolProps, type Attachment, type AttachmentAdapter, type AttachmentAddErrorEvent, type AttachmentAddErrorReason, type AttachmentRuntime, type AttachmentRuntimePath, type AttachmentState, type AttachmentStatus, type ChatModelAdapter, type ChatModelRunOptions, type ChatModelRunResult, type ChatModelRunUpdate, type CompleteAttachment, type CompleteAttachmentStatus, type ComposerRuntime, type ComposerRuntimeCore, type ComposerRuntimeEventCallback, type ComposerRuntimeEventPayload, type ComposerRuntimeEventType, type ComposerRuntimePath, type ComposerState, CompositeAttachmentAdapter, type CoreChatModelRunResult, type CreateAppendMessage, type CreateAttachment, type CreateResumeRunConfig, type CreateStartRunConfig, type DataMessagePart, type DictationAdapter, type DictationState, type EditComposerRuntime, type EditComposerRuntimeCore, type EditComposerState, ExportedMessageRepository, type ExportedMessageRepositoryItem, type ExternalStoreAdapter, type ExternalStoreMessageConverter, type ExternalStoreSharedOptions, type ExternalStoreThreadData, type ExternalStoreThreadListAdapter, type ExternalThreadQueueAdapter, FRAME_MESSAGE_CHANNEL, type FeedbackAdapter, type FileMessagePart, type FrameMessage, type FrameMessageType, type GenerativeUIMessagePart, type GenerativeUINode, type GenerativeUISpec, type GenericThreadHistoryAdapter, type ImageMessagePart, InMemoryThreadListAdapter, type LanguageModelConfig, type LanguageModelV1CallSettings, type LocalRuntimeOptionsBase, MCP_APP_URI_SCHEME, type McpAppMetadata, type MessageFormatAdapter, type MessageFormatItem, type MessageFormatRepository, type MessagePartRuntime, type MessagePartRuntimePath, type MessagePartState, type MessagePartStatus, type MessageQueueController, type MessageQueueDriver, type MessageRole, type MessageRuntime, type MessageRuntimePath, type MessageState, type MessageStatus, type MessageStorageEntry, type MessageTiming, type ModelContext, type ModelContextProvider, ModelContextRegistry, type ModelContextRegistryInstructionHandle, type ModelContextRegistryProviderHandle, type ModelContextRegistryToolHandle, type PendingAttachment, type PendingAttachmentStatus, type QuoteInfo, type RealtimeVoiceAdapter, type ReasoningMessagePart, type RemoteThreadInitializeResponse, type RemoteThreadListAdapter, type RemoteThreadListOptions, type RemoteThreadListPageOptions, type RemoteThreadListResponse, type RemoteThreadMetadata, type RespondToToolApprovalOptions, type ResumeRunConfig, type ResumeToolCallOptions, type RunConfig, type RuntimeCapabilities, type SendOptions, type SerializedModelContext, type SerializedTool, SimpleImageAttachmentAdapter, SimpleTextAttachmentAdapter, type SourceMessagePart, type SourceProviderMetadata, type SpeechState, type SpeechSynthesisAdapter, type StartRunConfig, type SubmitFeedbackOptions, type SubmittedFeedback, type SuggestionAdapter, type TextMessagePart, type ThreadAssistantMessage, type ThreadAssistantMessagePart, type ThreadComposerRuntime, type ThreadComposerRuntimeCore, type ThreadComposerState, type ThreadHistoryAdapter, type ThreadListItemCoreState, type ThreadListItemEventCallback, type ThreadListItemEventPayload, type ThreadListItemEventType, type ThreadListItemRuntime, type ThreadListItemRuntimePath, type ThreadListItemState, type ThreadListItemStatus, type ThreadListRuntime, type ThreadListRuntimeCore, type ThreadListState, type ThreadMessage, type ThreadMessageLike, type ThreadRuntime, type ThreadRuntimeCore, type ThreadRuntimeEventCallback, type ThreadRuntimeEventPayload, type ThreadRuntimeEventType, type ThreadRuntimePath, type ThreadState, type ThreadStep, type ThreadSuggestion, type ThreadSystemMessage, type ThreadUserMessage, type ThreadUserMessagePart, type ToolCallMessagePart, type ToolCallMessagePartMcpMetadata, type ToolCallMessagePartStatus, type ToolExecutionStatus, type ToolModelContentPart, type Unstable_AudioMessagePart, type Unstable_DirectiveFormatter, type Unstable_DirectiveSegment, type Unstable_TriggerAdapter, type Unstable_TriggerCategory, type Unstable_TriggerItem, type Unsubscribe, type VoiceSessionControls, type VoiceSessionHelpers, type VoiceSessionState, WebSpeechDictationAdapter, WebSpeechSynthesisAdapter, bindExternalStoreMessage, createMessageQueue, createRequestHeaders, createVoiceSession, getExternalStoreMessages, isMcpAppUri, mergeModelContexts, pickExternalStoreSharedOptions, tool, unstable_defaultDirectiveFormatter };
|
|
51
|
+
export { type AddToolResultOptions, type AppendMessage, type AssistantContextConfig, AssistantFrameHost, AssistantFrameProvider, type AssistantInstructionsConfig, type AssistantRuntime, type AssistantRuntimeCore, type AssistantToolProps, type Attachment, type AttachmentAdapter, type AttachmentAddErrorEvent, type AttachmentAddErrorReason, type AttachmentRuntime, type AttachmentRuntimePath, type AttachmentState, type AttachmentStatus, type ChatModelAdapter, type ChatModelRunOptions, type ChatModelRunResult, type ChatModelRunUpdate, type CompleteAttachment, type CompleteAttachmentStatus, type ComposerRuntime, type ComposerRuntimeCore, type ComposerRuntimeEventCallback, type ComposerRuntimeEventPayload, type ComposerRuntimeEventType, type ComposerRuntimePath, type ComposerState, CompositeAttachmentAdapter, type CoreChatModelRunResult, type CreateAppendMessage, type CreateAttachment, type CreateResumeRunConfig, type CreateStartRunConfig, type DataMessagePart, type DictationAdapter, type DictationState, type EditComposerRuntime, type EditComposerRuntimeCore, type EditComposerState, ExportedMessageRepository, type ExportedMessageRepositoryItem, type ExternalStoreAdapter, type ExternalStoreMessageConverter, type ExternalStoreSharedOptions, type ExternalStoreThreadData, type ExternalStoreThreadListAdapter, type ExternalThreadBranchAdapter, type ExternalThreadQueueAdapter, FRAME_MESSAGE_CHANNEL, type FeedbackAdapter, type FileMessagePart, type FrameMessage, type FrameMessageType, type GenerativeUIMessagePart, type GenerativeUINode, type GenerativeUISpec, type GenericThreadHistoryAdapter, type ImageMessagePart, InMemoryThreadListAdapter, type LanguageModelConfig, type LanguageModelV1CallSettings, type LocalRuntimeOptionsBase, MCP_APP_URI_SCHEME, type McpAppMetadata, type MessageFormatAdapter, type MessageFormatItem, type MessageFormatRepository, type MessagePartRuntime, type MessagePartRuntimePath, type MessagePartState, type MessagePartStatus, type MessageQueueController, type MessageQueueDriver, type MessageRole, type MessageRuntime, type MessageRuntimePath, type MessageState, type MessageStatus, type MessageStorageEntry, type MessageTiming, type ModelContext, type ModelContextProvider, ModelContextRegistry, type ModelContextRegistryInstructionHandle, type ModelContextRegistryProviderHandle, type ModelContextRegistryToolHandle, type PendingAttachment, type PendingAttachmentStatus, type QuoteInfo, type RealtimeVoiceAdapter, type ReasoningMessagePart, type RemoteThreadInitializeResponse, type RemoteThreadListAdapter, type RemoteThreadListOptions, type RemoteThreadListPageOptions, type RemoteThreadListResponse, type RemoteThreadMetadata, type RespondToToolApprovalOptions, type ResumeRunConfig, type ResumeToolCallOptions, type RunConfig, type RuntimeCapabilities, type SendOptions, type SerializedModelContext, type SerializedTool, SimpleImageAttachmentAdapter, SimpleTextAttachmentAdapter, type SourceMessagePart, type SourceProviderMetadata, type SpeechState, type SpeechSynthesisAdapter, type StartRunConfig, type SubmitFeedbackOptions, type SubmittedFeedback, type SuggestionAdapter, type TextMessagePart, type ThreadAssistantMessage, type ThreadAssistantMessagePart, type ThreadComposerRuntime, type ThreadComposerRuntimeCore, type ThreadComposerState, type ThreadHistoryAdapter, type ThreadListItemCoreState, type ThreadListItemEventCallback, type ThreadListItemEventPayload, type ThreadListItemEventType, type ThreadListItemRuntime, type ThreadListItemRuntimePath, type ThreadListItemState, type ThreadListItemStatus, type ThreadListRuntime, type ThreadListRuntimeCore, type ThreadListState, type ThreadMessage, type ThreadMessageLike, type ThreadRuntime, type ThreadRuntimeCore, type ThreadRuntimeEventCallback, type ThreadRuntimeEventPayload, type ThreadRuntimeEventType, type ThreadRuntimePath, type ThreadState, type ThreadStep, type ThreadSuggestion, type ThreadSystemMessage, type ThreadUserMessage, type ThreadUserMessagePart, type ToolCallMessagePart, type ToolCallMessagePartMcpMetadata, type ToolCallMessagePartStatus, type ToolExecutionStatus, type ToolModelContentPart, type Unstable_AudioMessagePart, type Unstable_DirectiveFormatter, type Unstable_DirectiveSegment, type Unstable_TriggerAdapter, type Unstable_TriggerCategory, type Unstable_TriggerItem, type Unsubscribe, type VoiceSessionControls, type VoiceSessionHelpers, type VoiceSessionState, WebSpeechDictationAdapter, WebSpeechSynthesisAdapter, bindExternalStoreMessage, createMessageQueue, createRequestHeaders, createVoiceSession, getExternalStoreMessages, isMcpAppUri, mergeModelContexts, pickExternalStoreSharedOptions, tool, unstable_defaultDirectiveFormatter };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["// @assistant-ui/core - Framework-agnostic core runtime (public API)\n\n/// <reference path=\"./store/scope-registration.ts\" />\n\nimport { checkDuplicateCore } from \"./internal/duplicate-detection\";\n\nif (process.env.NODE_ENV !== \"production\") {\n checkDuplicateCore();\n}\n\nexport type {\n // Message parts\n TextMessagePart,\n ReasoningMessagePart,\n SourceProviderMetadata,\n SourceMessagePart,\n ImageMessagePart,\n FileMessagePart,\n DataMessagePart,\n GenerativeUIMessagePart,\n GenerativeUINode,\n GenerativeUISpec,\n Unstable_AudioMessagePart,\n ToolCallMessagePart,\n ToolCallMessagePartMcpMetadata,\n McpAppMetadata,\n ToolModelContentPart,\n ThreadUserMessagePart,\n ThreadAssistantMessagePart,\n // Message status\n MessagePartStatus,\n ToolCallMessagePartStatus,\n MessageStatus,\n // Thread messages\n MessageTiming,\n ThreadStep,\n ThreadSystemMessage,\n ThreadUserMessage,\n ThreadAssistantMessage,\n ThreadMessage,\n MessageRole,\n // Config\n RunConfig,\n AppendMessage,\n} from \"./types/message\";\n\nexport { MCP_APP_URI_SCHEME, isMcpAppUri } from \"./types/message\";\n\nexport type {\n Attachment,\n PendingAttachment,\n PendingAttachmentStatus,\n CompleteAttachment,\n CompleteAttachmentStatus,\n AttachmentStatus,\n CreateAttachment,\n} from \"./types/attachment\";\n\nexport type { Unsubscribe } from \"./types/unsubscribe\";\n\nexport type { QuoteInfo } from \"./types/quote\";\n\nexport type {\n Unstable_DirectiveSegment,\n Unstable_DirectiveFormatter,\n} from \"./types/directive\";\n\nexport type {\n Unstable_TriggerItem,\n Unstable_TriggerCategory,\n} from \"./types/trigger\";\n\nexport type { Unstable_TriggerAdapter } from \"./adapters/trigger\";\n\nexport type {\n // Language model settings\n LanguageModelV1CallSettings,\n LanguageModelConfig,\n // Model context\n ModelContext,\n ModelContextProvider,\n // Tool & instruction config\n AssistantToolProps,\n AssistantInstructionsConfig,\n AssistantContextConfig,\n} from \"./model-context/types\";\nexport { mergeModelContexts } from \"./model-context/types\";\n\nexport { tool } from \"./model-context/tool\";\n\nexport type { ToolExecutionStatus } from \"./runtimes/tool-invocations/ToolInvocationTracker\";\n\nexport { ModelContextRegistry } from \"./model-context/registry\";\nexport type {\n ModelContextRegistryToolHandle,\n ModelContextRegistryInstructionHandle,\n ModelContextRegistryProviderHandle,\n} from \"./model-context/registry-handles\";\n\nexport { AssistantFrameHost } from \"./model-context/frame/host\";\nexport { AssistantFrameProvider } from \"./model-context/frame/provider\";\nexport type {\n SerializedTool,\n SerializedModelContext,\n FrameMessageType,\n FrameMessage,\n} from \"./model-context/frame/types\";\nexport { FRAME_MESSAGE_CHANNEL } from \"./model-context/frame/types\";\n\n// Attachment adapters\nexport type { AttachmentAdapter } from \"./adapters/attachment\";\nexport {\n SimpleImageAttachmentAdapter,\n SimpleTextAttachmentAdapter,\n CompositeAttachmentAdapter,\n} from \"./adapters/attachment\";\n\n// Speech adapters\nexport type {\n SpeechSynthesisAdapter,\n DictationAdapter,\n} from \"./adapters/speech\";\nexport {\n WebSpeechSynthesisAdapter,\n WebSpeechDictationAdapter,\n} from \"./adapters/speech\";\n\n// Voice adapter\nexport type { RealtimeVoiceAdapter } from \"./adapters/voice\";\nexport { createVoiceSession } from \"./adapters/voice\";\nexport type {\n VoiceSessionControls,\n VoiceSessionHelpers,\n} from \"./adapters/voice\";\n\n// Feedback adapter\nexport type { FeedbackAdapter } from \"./adapters/feedback\";\n\n// Suggestion adapter\nexport type { SuggestionAdapter } from \"./adapters/suggestion\";\n\n// Directive formatter\nexport { unstable_defaultDirectiveFormatter } from \"./adapters/directive-formatter\";\n\n// Thread history adapters\nexport type {\n ThreadHistoryAdapter,\n GenericThreadHistoryAdapter,\n MessageFormatAdapter,\n MessageFormatItem,\n MessageFormatRepository,\n MessageStorageEntry,\n} from \"./adapters/thread-history\";\n\n// Path Types\nexport type {\n ThreadListItemRuntimePath,\n ThreadRuntimePath,\n MessageRuntimePath,\n MessagePartRuntimePath,\n AttachmentRuntimePath,\n ComposerRuntimePath,\n} from \"./runtime/api/paths\";\n\n// Runtime Core Interface Types\nexport type {\n AttachmentAddErrorEvent,\n AttachmentAddErrorReason,\n ComposerRuntimeCore,\n ComposerRuntimeEventCallback,\n ComposerRuntimeEventPayload,\n ComposerRuntimeEventType,\n DictationState,\n EditComposerRuntimeCore,\n SendOptions,\n ThreadComposerRuntimeCore,\n} from \"./runtime/interfaces/composer-runtime-core\";\n\nexport type {\n RuntimeCapabilities,\n AddToolResultOptions,\n ResumeToolCallOptions,\n RespondToToolApprovalOptions,\n SubmitFeedbackOptions,\n ThreadSuggestion,\n SpeechState,\n VoiceSessionState,\n SubmittedFeedback,\n ThreadRuntimeEventCallback,\n ThreadRuntimeEventPayload,\n ThreadRuntimeEventType,\n StartRunConfig,\n ResumeRunConfig,\n ThreadRuntimeCore,\n} from \"./runtime/interfaces/thread-runtime-core\";\n\nexport type {\n ThreadListItemStatus,\n ThreadListItemCoreState,\n ThreadListRuntimeCore,\n} from \"./runtime/interfaces/thread-list-runtime-core\";\n\nexport type { AssistantRuntimeCore } from \"./runtime/interfaces/assistant-runtime-core\";\n\n// Public Runtime Types\nexport type { AssistantRuntime } from \"./runtime/api/assistant-runtime\";\n\nexport type {\n CreateStartRunConfig,\n CreateResumeRunConfig,\n CreateAppendMessage,\n ThreadState,\n ThreadRuntime,\n} from \"./runtime/api/thread-runtime\";\n\nexport type {\n ThreadListState,\n ThreadListRuntime,\n} from \"./runtime/api/thread-list-runtime\";\n\nexport type {\n ThreadListItemEventCallback,\n ThreadListItemEventPayload,\n ThreadListItemEventType,\n ThreadListItemRuntime,\n} from \"./runtime/api/thread-list-item-runtime\";\n\nexport type { ThreadListItemState } from \"./runtime/api/bindings\";\n\nexport type {\n MessageState,\n MessageRuntime,\n} from \"./runtime/api/message-runtime\";\nexport type {\n MessagePartState,\n MessagePartRuntime,\n} from \"./runtime/api/message-part-runtime\";\n\nexport type {\n ThreadComposerState,\n EditComposerState,\n ComposerState,\n ComposerRuntime,\n ThreadComposerRuntime,\n EditComposerRuntime,\n} from \"./runtime/api/composer-runtime\";\n\nexport type {\n AttachmentState,\n AttachmentRuntime,\n} from \"./runtime/api/attachment-runtime\";\n\n// ChatModel Types\nexport type {\n ChatModelRunUpdate,\n ChatModelRunResult,\n CoreChatModelRunResult,\n ChatModelRunOptions,\n ChatModelAdapter,\n} from \"./runtime/utils/chat-model-adapter\";\n\n// ThreadMessageLike\nexport type { ThreadMessageLike } from \"./runtime/utils/thread-message-like\";\n\n// External Store Message Utilities\nexport {\n getExternalStoreMessages,\n bindExternalStoreMessage,\n} from \"./runtime/utils/external-store-message\";\n\n// ExportedMessageRepository\nexport type { ExportedMessageRepositoryItem } from \"./runtime/utils/message-repository\";\nexport { ExportedMessageRepository } from \"./runtime/utils/message-repository\";\n\n// Local Runtime Options\nexport type { LocalRuntimeOptionsBase } from \"./runtimes/local/local-runtime-options\";\n\n// External Store Adapter Types (user-facing)\nexport type {\n ExternalStoreAdapter,\n ExternalStoreMessageConverter,\n ExternalStoreThreadListAdapter,\n ExternalStoreThreadData,\n} from \"./runtimes/external-store/external-store-adapter\";\nexport type { ExternalStoreSharedOptions } from \"./runtimes/external-store/external-store-shared-options\";\nexport { pickExternalStoreSharedOptions } from \"./runtimes/external-store/external-store-shared-options\";\n\n// Message queue\nexport type { ExternalThreadQueueAdapter } from \"./runtime/queue/external-thread-queue-adapter\";\nexport {\n createMessageQueue,\n type MessageQueueDriver,\n type MessageQueueController,\n} from \"./runtime/queue/message-queue\";\n\n// Remote Thread List (user-facing)\nexport type {\n RemoteThreadListAdapter,\n RemoteThreadListOptions,\n RemoteThreadInitializeResponse,\n RemoteThreadMetadata,\n RemoteThreadListResponse,\n RemoteThreadListPageOptions,\n} from \"./runtimes/remote-thread-list/types\";\n\nexport { InMemoryThreadListAdapter } from \"./runtimes/remote-thread-list/adapter/in-memory\";\n\n// Assistant Transport Utilities\nexport { createRequestHeaders } from \"./runtimes/assistant-transport/utils\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAMA,IAAI,QAAQ,IAAI,aAAa,cAC3B,mBAAmB"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["// @assistant-ui/core - Framework-agnostic core runtime (public API)\n\n/// <reference path=\"./store/scope-registration.ts\" />\n\nimport { checkDuplicateCore } from \"./internal/duplicate-detection\";\n\nif (process.env.NODE_ENV !== \"production\") {\n checkDuplicateCore();\n}\n\nexport type {\n // Message parts\n TextMessagePart,\n ReasoningMessagePart,\n SourceProviderMetadata,\n SourceMessagePart,\n ImageMessagePart,\n FileMessagePart,\n DataMessagePart,\n GenerativeUIMessagePart,\n GenerativeUINode,\n GenerativeUISpec,\n Unstable_AudioMessagePart,\n ToolCallMessagePart,\n ToolCallMessagePartMcpMetadata,\n McpAppMetadata,\n ToolModelContentPart,\n ThreadUserMessagePart,\n ThreadAssistantMessagePart,\n // Message status\n MessagePartStatus,\n ToolCallMessagePartStatus,\n MessageStatus,\n // Thread messages\n MessageTiming,\n ThreadStep,\n ThreadSystemMessage,\n ThreadUserMessage,\n ThreadAssistantMessage,\n ThreadMessage,\n MessageRole,\n // Config\n RunConfig,\n AppendMessage,\n} from \"./types/message\";\n\nexport { MCP_APP_URI_SCHEME, isMcpAppUri } from \"./types/message\";\n\nexport type {\n Attachment,\n PendingAttachment,\n PendingAttachmentStatus,\n CompleteAttachment,\n CompleteAttachmentStatus,\n AttachmentStatus,\n CreateAttachment,\n} from \"./types/attachment\";\n\nexport type { Unsubscribe } from \"./types/unsubscribe\";\n\nexport type { QuoteInfo } from \"./types/quote\";\n\nexport type {\n Unstable_DirectiveSegment,\n Unstable_DirectiveFormatter,\n} from \"./types/directive\";\n\nexport type {\n Unstable_TriggerItem,\n Unstable_TriggerCategory,\n} from \"./types/trigger\";\n\nexport type { Unstable_TriggerAdapter } from \"./adapters/trigger\";\n\nexport type {\n // Language model settings\n LanguageModelV1CallSettings,\n LanguageModelConfig,\n // Model context\n ModelContext,\n ModelContextProvider,\n // Tool & instruction config\n AssistantToolProps,\n AssistantInstructionsConfig,\n AssistantContextConfig,\n} from \"./model-context/types\";\nexport { mergeModelContexts } from \"./model-context/types\";\n\nexport { tool } from \"./model-context/tool\";\n\nexport type { ToolExecutionStatus } from \"./runtimes/tool-invocations/ToolInvocationTracker\";\n\nexport { ModelContextRegistry } from \"./model-context/registry\";\nexport type {\n ModelContextRegistryToolHandle,\n ModelContextRegistryInstructionHandle,\n ModelContextRegistryProviderHandle,\n} from \"./model-context/registry-handles\";\n\nexport { AssistantFrameHost } from \"./model-context/frame/host\";\nexport { AssistantFrameProvider } from \"./model-context/frame/provider\";\nexport type {\n SerializedTool,\n SerializedModelContext,\n FrameMessageType,\n FrameMessage,\n} from \"./model-context/frame/types\";\nexport { FRAME_MESSAGE_CHANNEL } from \"./model-context/frame/types\";\n\n// Attachment adapters\nexport type { AttachmentAdapter } from \"./adapters/attachment\";\nexport {\n SimpleImageAttachmentAdapter,\n SimpleTextAttachmentAdapter,\n CompositeAttachmentAdapter,\n} from \"./adapters/attachment\";\n\n// Speech adapters\nexport type {\n SpeechSynthesisAdapter,\n DictationAdapter,\n} from \"./adapters/speech\";\nexport {\n WebSpeechSynthesisAdapter,\n WebSpeechDictationAdapter,\n} from \"./adapters/speech\";\n\n// Voice adapter\nexport type { RealtimeVoiceAdapter } from \"./adapters/voice\";\nexport { createVoiceSession } from \"./adapters/voice\";\nexport type {\n VoiceSessionControls,\n VoiceSessionHelpers,\n} from \"./adapters/voice\";\n\n// Feedback adapter\nexport type { FeedbackAdapter } from \"./adapters/feedback\";\n\n// Suggestion adapter\nexport type { SuggestionAdapter } from \"./adapters/suggestion\";\n\n// Directive formatter\nexport { unstable_defaultDirectiveFormatter } from \"./adapters/directive-formatter\";\n\n// Thread history adapters\nexport type {\n ThreadHistoryAdapter,\n GenericThreadHistoryAdapter,\n MessageFormatAdapter,\n MessageFormatItem,\n MessageFormatRepository,\n MessageStorageEntry,\n} from \"./adapters/thread-history\";\n\n// Path Types\nexport type {\n ThreadListItemRuntimePath,\n ThreadRuntimePath,\n MessageRuntimePath,\n MessagePartRuntimePath,\n AttachmentRuntimePath,\n ComposerRuntimePath,\n} from \"./runtime/api/paths\";\n\n// Runtime Core Interface Types\nexport type {\n AttachmentAddErrorEvent,\n AttachmentAddErrorReason,\n ComposerRuntimeCore,\n ComposerRuntimeEventCallback,\n ComposerRuntimeEventPayload,\n ComposerRuntimeEventType,\n DictationState,\n EditComposerRuntimeCore,\n SendOptions,\n ThreadComposerRuntimeCore,\n} from \"./runtime/interfaces/composer-runtime-core\";\n\nexport type {\n RuntimeCapabilities,\n AddToolResultOptions,\n ResumeToolCallOptions,\n RespondToToolApprovalOptions,\n SubmitFeedbackOptions,\n ThreadSuggestion,\n SpeechState,\n VoiceSessionState,\n SubmittedFeedback,\n ThreadRuntimeEventCallback,\n ThreadRuntimeEventPayload,\n ThreadRuntimeEventType,\n StartRunConfig,\n ResumeRunConfig,\n ThreadRuntimeCore,\n} from \"./runtime/interfaces/thread-runtime-core\";\n\nexport type {\n ThreadListItemStatus,\n ThreadListItemCoreState,\n ThreadListRuntimeCore,\n} from \"./runtime/interfaces/thread-list-runtime-core\";\n\nexport type { AssistantRuntimeCore } from \"./runtime/interfaces/assistant-runtime-core\";\n\n// Public Runtime Types\nexport type { AssistantRuntime } from \"./runtime/api/assistant-runtime\";\n\nexport type {\n CreateStartRunConfig,\n CreateResumeRunConfig,\n CreateAppendMessage,\n ThreadState,\n ThreadRuntime,\n} from \"./runtime/api/thread-runtime\";\n\nexport type {\n ThreadListState,\n ThreadListRuntime,\n} from \"./runtime/api/thread-list-runtime\";\n\nexport type {\n ThreadListItemEventCallback,\n ThreadListItemEventPayload,\n ThreadListItemEventType,\n ThreadListItemRuntime,\n} from \"./runtime/api/thread-list-item-runtime\";\n\nexport type { ThreadListItemState } from \"./runtime/api/bindings\";\n\nexport type {\n MessageState,\n MessageRuntime,\n} from \"./runtime/api/message-runtime\";\nexport type {\n MessagePartState,\n MessagePartRuntime,\n} from \"./runtime/api/message-part-runtime\";\n\nexport type {\n ThreadComposerState,\n EditComposerState,\n ComposerState,\n ComposerRuntime,\n ThreadComposerRuntime,\n EditComposerRuntime,\n} from \"./runtime/api/composer-runtime\";\n\nexport type {\n AttachmentState,\n AttachmentRuntime,\n} from \"./runtime/api/attachment-runtime\";\n\n// ChatModel Types\nexport type {\n ChatModelRunUpdate,\n ChatModelRunResult,\n CoreChatModelRunResult,\n ChatModelRunOptions,\n ChatModelAdapter,\n} from \"./runtime/utils/chat-model-adapter\";\n\n// ThreadMessageLike\nexport type { ThreadMessageLike } from \"./runtime/utils/thread-message-like\";\n\n// External Store Message Utilities\nexport {\n getExternalStoreMessages,\n bindExternalStoreMessage,\n} from \"./runtime/utils/external-store-message\";\n\n// ExportedMessageRepository\nexport type { ExportedMessageRepositoryItem } from \"./runtime/utils/message-repository\";\nexport { ExportedMessageRepository } from \"./runtime/utils/message-repository\";\n\n// Local Runtime Options\nexport type { LocalRuntimeOptionsBase } from \"./runtimes/local/local-runtime-options\";\n\n// External Store Adapter Types (user-facing)\nexport type {\n ExternalStoreAdapter,\n ExternalStoreMessageConverter,\n ExternalStoreThreadListAdapter,\n ExternalStoreThreadData,\n} from \"./runtimes/external-store/external-store-adapter\";\nexport type { ExternalStoreSharedOptions } from \"./runtimes/external-store/external-store-shared-options\";\nexport { pickExternalStoreSharedOptions } from \"./runtimes/external-store/external-store-shared-options\";\n\n// Message queue\nexport type { ExternalThreadQueueAdapter } from \"./runtime/queue/external-thread-queue-adapter\";\nexport type { ExternalThreadBranchAdapter } from \"./runtime/branch/external-thread-branch-adapter\";\nexport {\n createMessageQueue,\n type MessageQueueDriver,\n type MessageQueueController,\n} from \"./runtime/queue/message-queue\";\n\n// Remote Thread List (user-facing)\nexport type {\n RemoteThreadListAdapter,\n RemoteThreadListOptions,\n RemoteThreadInitializeResponse,\n RemoteThreadMetadata,\n RemoteThreadListResponse,\n RemoteThreadListPageOptions,\n} from \"./runtimes/remote-thread-list/types\";\n\nexport { InMemoryThreadListAdapter } from \"./runtimes/remote-thread-list/adapter/in-memory\";\n\n// Assistant Transport Utilities\nexport { createRequestHeaders } from \"./runtimes/assistant-transport/utils\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAMA,IAAI,QAAQ,IAAI,aAAa,cAC3B,mBAAmB"}
|
|
@@ -9,10 +9,15 @@ const getRenderComponent = (runtime) => {
|
|
|
9
9
|
const AssistantProviderBase = memo(({ runtime, aui: parent = null, children }) => {
|
|
10
10
|
const aui = useAui({ threads: RuntimeAdapter(runtime) }, { parent });
|
|
11
11
|
const RenderComponent = getRenderComponent(runtime);
|
|
12
|
-
|
|
12
|
+
const inner = /* @__PURE__ */ jsxs(AuiProvider, {
|
|
13
13
|
value: aui,
|
|
14
14
|
children: [RenderComponent && /* @__PURE__ */ jsx(RenderComponent, {}), children]
|
|
15
15
|
});
|
|
16
|
+
if (!parent) return inner;
|
|
17
|
+
return /* @__PURE__ */ jsx(AuiProvider, {
|
|
18
|
+
value: parent,
|
|
19
|
+
children: inner
|
|
20
|
+
});
|
|
16
21
|
});
|
|
17
22
|
//#endregion
|
|
18
23
|
export { AssistantProviderBase, getRenderComponent };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantProvider.js","names":[],"sources":["../../src/react/AssistantProvider.tsx"],"sourcesContent":["import {\n memo,\n type ComponentType,\n type FC,\n type PropsWithChildren,\n} from \"react\";\nimport { useAui, AuiProvider, type AssistantClient } from \"@assistant-ui/store\";\nimport type { AssistantRuntime } from \"../runtime/api/assistant-runtime\";\nimport type { AssistantRuntimeCore } from \"../runtime/interfaces/assistant-runtime-core\";\nimport { RuntimeAdapter } from \"./RuntimeAdapter\";\n\nexport const getRenderComponent = (runtime: AssistantRuntime) => {\n return (runtime as { _core?: AssistantRuntimeCore })._core\n ?.RenderComponent as ComponentType | undefined;\n};\n\nexport type AssistantProviderBaseProps = PropsWithChildren<{\n runtime: AssistantRuntime;\n aui?: AssistantClient | null;\n}>;\n\nexport const AssistantProviderBase: FC<AssistantProviderBaseProps> = memo(\n ({ runtime, aui: parent = null, children }) => {\n const aui = useAui({ threads: RuntimeAdapter(runtime) }, { parent });\n const RenderComponent = getRenderComponent(runtime);\n
|
|
1
|
+
{"version":3,"file":"AssistantProvider.js","names":[],"sources":["../../src/react/AssistantProvider.tsx"],"sourcesContent":["import {\n memo,\n type ComponentType,\n type FC,\n type PropsWithChildren,\n} from \"react\";\nimport { useAui, AuiProvider, type AssistantClient } from \"@assistant-ui/store\";\nimport type { AssistantRuntime } from \"../runtime/api/assistant-runtime\";\nimport type { AssistantRuntimeCore } from \"../runtime/interfaces/assistant-runtime-core\";\nimport { RuntimeAdapter } from \"./RuntimeAdapter\";\n\nexport const getRenderComponent = (runtime: AssistantRuntime) => {\n return (runtime as { _core?: AssistantRuntimeCore })._core\n ?.RenderComponent as ComponentType | undefined;\n};\n\nexport type AssistantProviderBaseProps = PropsWithChildren<{\n runtime: AssistantRuntime;\n aui?: AssistantClient | null;\n}>;\n\nexport const AssistantProviderBase: FC<AssistantProviderBaseProps> = memo(\n ({ runtime, aui: parent = null, children }) => {\n const aui = useAui({ threads: RuntimeAdapter(runtime) }, { parent });\n const RenderComponent = getRenderComponent(runtime);\n const inner = (\n <AuiProvider value={aui}>\n {RenderComponent && <RenderComponent />}\n {children}\n </AuiProvider>\n );\n if (!parent) return inner;\n return <AuiProvider value={parent}>{inner}</AuiProvider>;\n },\n);\n"],"mappings":";;;;;AAWA,MAAa,sBAAsB,YAA8B;CAC/D,OAAQ,QAA6C,OACjD;AACN;AAOA,MAAa,wBAAwD,MAClE,EAAE,SAAS,KAAK,SAAS,MAAM,eAAe;CAC7C,MAAM,MAAM,OAAO,EAAE,SAAS,eAAe,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC;CACnE,MAAM,kBAAkB,mBAAmB,OAAO;CAClD,MAAM,QACJ,qBAAC,aAAD;EAAa,OAAO;YAApB,CACG,mBAAmB,oBAAC,iBAAD,CAAkB,CAAA,GACrC,QACU;;CAEf,IAAI,CAAC,QAAQ,OAAO;CACpB,OAAO,oBAAC,aAAD;EAAa,OAAO;YAAS;CAAmB,CAAA;AACzD,CACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AssistantRuntime } from "../runtime/api/assistant-runtime.js";
|
|
2
2
|
//#region src/react/RuntimeAdapter.d.ts
|
|
3
|
-
declare const RuntimeAdapter:
|
|
3
|
+
declare const RuntimeAdapter: import("@assistant-ui/tap").Resource<import("@assistant-ui/store").ClientOutput<"threads">, [runtime: AssistantRuntime]>;
|
|
4
4
|
//#endregion
|
|
5
5
|
export { RuntimeAdapter };
|
|
6
6
|
//# sourceMappingURL=RuntimeAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuntimeAdapter.d.ts","names":[],"sources":["../../src/react/RuntimeAdapter.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"RuntimeAdapter.d.ts","names":[],"sources":["../../src/react/RuntimeAdapter.ts"],"mappings":";;cA+Ba,cAAA,8BAAc,QAAA,+BAAA,YAAA,cAAA,OAAA,EAAA,gBAAA"}
|
|
@@ -1,13 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ThreadListClient } from "../store/runtime-clients/thread-list-runtime-client.js";
|
|
2
|
+
import { baseRuntimeAdapterTransformScopes } from "../store/clients/runtime-adapter.js";
|
|
2
3
|
import { DataRenderers } from "./client/DataRenderers.js";
|
|
3
4
|
import { Tools } from "./client/Tools.js";
|
|
4
|
-
import {
|
|
5
|
+
import { useEffect } from "@assistant-ui/tap/react-shim";
|
|
6
|
+
import { attachTransformScopes, useAssistantClientRef } from "@assistant-ui/store";
|
|
5
7
|
import { resource, useResource } from "@assistant-ui/tap";
|
|
6
8
|
//#region src/react/RuntimeAdapter.ts
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const useRuntimeAdapter = (runtime) => {
|
|
10
|
+
const clientRef = useAssistantClientRef();
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
return runtime.registerModelContextProvider(clientRef.current.modelContext());
|
|
13
|
+
}, [runtime, clientRef]);
|
|
14
|
+
return useResource(ThreadListClient({
|
|
15
|
+
runtime: runtime.threads,
|
|
16
|
+
__internal_assistantRuntime: runtime
|
|
17
|
+
}));
|
|
18
|
+
};
|
|
19
|
+
const RuntimeAdapter = resource(useRuntimeAdapter);
|
|
20
|
+
attachTransformScopes(useRuntimeAdapter, (scopes, parent) => {
|
|
11
21
|
baseRuntimeAdapterTransformScopes(scopes, parent);
|
|
12
22
|
if (!scopes.tools && parent.tools.source === null) scopes.tools = Tools({});
|
|
13
23
|
if (!scopes.dataRenderers && parent.dataRenderers.source === null) scopes.dataRenderers = DataRenderers();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuntimeAdapter.js","names":[],"sources":["../../src/react/RuntimeAdapter.ts"],"sourcesContent":["import { useResource, resource } from \"@assistant-ui/tap\";\nimport type { AssistantRuntime } from \"..\";\nimport {\n
|
|
1
|
+
{"version":3,"file":"RuntimeAdapter.js","names":[],"sources":["../../src/react/RuntimeAdapter.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useResource, resource } from \"@assistant-ui/tap\";\nimport type { AssistantRuntime } from \"..\";\nimport {\n baseRuntimeAdapterTransformScopes,\n ThreadListClient,\n} from \"../store/internal\";\nimport {\n attachTransformScopes,\n useAssistantClientRef,\n} from \"@assistant-ui/store\";\nimport { DataRenderers } from \"./client/DataRenderers\";\nimport { Tools } from \"./client/Tools\";\n\nconst useRuntimeAdapter = (runtime: AssistantRuntime) => {\n const clientRef = useAssistantClientRef();\n\n useEffect(() => {\n return runtime.registerModelContextProvider(\n clientRef.current!.modelContext(),\n );\n }, [runtime, clientRef]);\n\n return useResource(\n ThreadListClient({\n runtime: runtime.threads,\n __internal_assistantRuntime: runtime,\n }),\n );\n};\n\nexport const RuntimeAdapter = resource(useRuntimeAdapter);\n\nattachTransformScopes(useRuntimeAdapter, (scopes, parent) => {\n baseRuntimeAdapterTransformScopes(scopes, parent);\n\n if (!scopes.tools && parent.tools.source === null) {\n scopes.tools = Tools({});\n }\n\n if (!scopes.dataRenderers && parent.dataRenderers.source === null) {\n scopes.dataRenderers = DataRenderers();\n }\n});\n"],"mappings":";;;;;;;;AAcA,MAAM,qBAAqB,YAA8B;CACvD,MAAM,YAAY,sBAAsB;CAExC,gBAAgB;EACd,OAAO,QAAQ,6BACb,UAAU,QAAS,aAAa,CAClC;CACF,GAAG,CAAC,SAAS,SAAS,CAAC;CAEvB,OAAO,YACL,iBAAiB;EACf,SAAS,QAAQ;EACjB,6BAA6B;CAC/B,CAAC,CACH;AACF;AAEA,MAAa,iBAAiB,SAAS,iBAAiB;AAExD,sBAAsB,oBAAoB,QAAQ,WAAW;CAC3D,kCAAkC,QAAQ,MAAM;CAEhD,IAAI,CAAC,OAAO,SAAS,OAAO,MAAM,WAAW,MAC3C,OAAO,QAAQ,MAAM,CAAC,CAAC;CAGzB,IAAI,CAAC,OAAO,iBAAiB,OAAO,cAAc,WAAW,MAC3D,OAAO,gBAAgB,cAAc;AAEzC,CAAC"}
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import { ClientOutput } from "@assistant-ui/store";
|
|
2
2
|
|
|
3
3
|
//#region src/react/client/DataRenderers.d.ts
|
|
4
|
-
|
|
5
|
-
* Registers renderers for `data` message parts.
|
|
6
|
-
*
|
|
7
|
-
* Data renderers are looked up by the part's `name` field. Use this resource
|
|
8
|
-
* directly for a renderer scope, or prefer {@link useAssistantDataUI} /
|
|
9
|
-
* {@link makeAssistantDataUI} when registering from React components.
|
|
10
|
-
*/
|
|
11
|
-
declare const DataRenderers: () => import("@assistant-ui/tap").ResourceElement<ClientOutput<"dataRenderers">, undefined>;
|
|
4
|
+
declare const DataRenderers: import("@assistant-ui/tap").Resource<ClientOutput<"dataRenderers">, []>;
|
|
12
5
|
//#endregion
|
|
13
6
|
export { DataRenderers };
|
|
14
7
|
//# sourceMappingURL=DataRenderers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataRenderers.d.ts","names":[],"sources":["../../../src/react/client/DataRenderers.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"DataRenderers.d.ts","names":[],"sources":["../../../src/react/client/DataRenderers.ts"],"mappings":";;;cAmEa,aAAA,8BAAa,QAAA,CAAA,YAAA"}
|
|
@@ -8,7 +8,7 @@ import { resource } from "@assistant-ui/tap";
|
|
|
8
8
|
* directly for a renderer scope, or prefer {@link useAssistantDataUI} /
|
|
9
9
|
* {@link makeAssistantDataUI} when registering from React components.
|
|
10
10
|
*/
|
|
11
|
-
const
|
|
11
|
+
const useDataRenderers = () => {
|
|
12
12
|
const [state, setState] = useState(() => ({
|
|
13
13
|
renderers: {},
|
|
14
14
|
fallbacks: []
|
|
@@ -50,7 +50,8 @@ const DataRenderers = resource(function DataRenderers() {
|
|
|
50
50
|
};
|
|
51
51
|
}, [])
|
|
52
52
|
};
|
|
53
|
-
}
|
|
53
|
+
};
|
|
54
|
+
const DataRenderers = resource(useDataRenderers);
|
|
54
55
|
//#endregion
|
|
55
56
|
export { DataRenderers };
|
|
56
57
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataRenderers.js","names":[],"sources":["../../../src/react/client/DataRenderers.ts"],"sourcesContent":["import { useState, useCallback } from \"react\";\nimport { resource } from \"@assistant-ui/tap\";\nimport type { ClientOutput } from \"@assistant-ui/store\";\nimport type { DataRenderersState } from \"../types/scopes/dataRenderers\";\nimport type { DataMessagePartComponent } from \"../types/MessagePartComponentTypes\";\n\n/**\n * Registers renderers for `data` message parts.\n *\n * Data renderers are looked up by the part's `name` field. Use this resource\n * directly for a renderer scope, or prefer {@link useAssistantDataUI} /\n * {@link makeAssistantDataUI} when registering from React components.\n */\
|
|
1
|
+
{"version":3,"file":"DataRenderers.js","names":[],"sources":["../../../src/react/client/DataRenderers.ts"],"sourcesContent":["import { useState, useCallback } from \"react\";\nimport { resource } from \"@assistant-ui/tap\";\nimport type { ClientOutput } from \"@assistant-ui/store\";\nimport type { DataRenderersState } from \"../types/scopes/dataRenderers\";\nimport type { DataMessagePartComponent } from \"../types/MessagePartComponentTypes\";\n\n/**\n * Registers renderers for `data` message parts.\n *\n * Data renderers are looked up by the part's `name` field. Use this resource\n * directly for a renderer scope, or prefer {@link useAssistantDataUI} /\n * {@link makeAssistantDataUI} when registering from React components.\n */\nconst useDataRenderers = (): ClientOutput<\"dataRenderers\"> => {\n const [state, setState] = useState<DataRenderersState>(() => ({\n renderers: {},\n fallbacks: [],\n }));\n\n const setDataUI = useCallback(\n (name: string, render: DataMessagePartComponent) => {\n setState((prev) => {\n return {\n ...prev,\n renderers: {\n ...prev.renderers,\n [name]: [...(prev.renderers[name] ?? []), render],\n },\n };\n });\n\n return () => {\n setState((prev) => {\n return {\n ...prev,\n renderers: {\n ...prev.renderers,\n [name]: prev.renderers[name]?.filter((r) => r !== render) ?? [],\n },\n };\n });\n };\n },\n [],\n );\n\n const setFallbackDataUI = useCallback((render: DataMessagePartComponent) => {\n setState((prev) => ({\n ...prev,\n fallbacks: [...prev.fallbacks, render],\n }));\n\n return () => {\n setState((prev) => ({\n ...prev,\n fallbacks: prev.fallbacks.filter((r) => r !== render),\n }));\n };\n }, []);\n\n return {\n getState: () => state,\n setDataUI,\n setFallbackDataUI,\n };\n};\n\nexport const DataRenderers = resource(useDataRenderers);\n"],"mappings":";;;;;;;;;;AAaA,MAAM,yBAAwD;CAC5D,MAAM,CAAC,OAAO,YAAY,gBAAoC;EAC5D,WAAW,CAAC;EACZ,WAAW,CAAC;CACd,EAAE;CA2CF,OAAO;EACL,gBAAgB;EAChB,WA3CgB,aACf,MAAc,WAAqC;GAClD,UAAU,SAAS;IACjB,OAAO;KACL,GAAG;KACH,WAAW;MACT,GAAG,KAAK;OACP,OAAO,CAAC,GAAI,KAAK,UAAU,SAAS,CAAC,GAAI,MAAM;KAClD;IACF;GACF,CAAC;GAED,aAAa;IACX,UAAU,SAAS;KACjB,OAAO;MACL,GAAG;MACH,WAAW;OACT,GAAG,KAAK;QACP,OAAO,KAAK,UAAU,KAAK,EAAE,QAAQ,MAAM,MAAM,MAAM,KAAK,CAAC;MAChE;KACF;IACF,CAAC;GACH;EACF,GACA,CAAC,CAmBO;EACR,mBAjBwB,aAAa,WAAqC;GAC1E,UAAU,UAAU;IAClB,GAAG;IACH,WAAW,CAAC,GAAG,KAAK,WAAW,MAAM;GACvC,EAAE;GAEF,aAAa;IACX,UAAU,UAAU;KAClB,GAAG;KACH,WAAW,KAAK,UAAU,QAAQ,MAAM,MAAM,MAAM;IACtD,EAAE;GACJ;EACF,GAAG,CAAC,CAKc;CAClB;AACF;AAEA,MAAa,gBAAgB,SAAS,gBAAgB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ClientOutput } from "@assistant-ui/store";
|
|
2
2
|
|
|
3
3
|
//#region src/react/client/Interactables.d.ts
|
|
4
|
-
declare const Interactables:
|
|
4
|
+
declare const Interactables: import("@assistant-ui/tap").Resource<ClientOutput<"interactables">, []>;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { Interactables };
|
|
7
7
|
//# sourceMappingURL=Interactables.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Interactables.d.ts","names":[],"sources":["../../../src/react/client/Interactables.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"Interactables.d.ts","names":[],"sources":["../../../src/react/client/Interactables.ts"],"mappings":";;;cAgUa,aAAA,8BAAa,QAAA,CAAA,YAAA"}
|
|
@@ -6,7 +6,7 @@ import { attachTransformScopes, useAssistantClientRef } from "@assistant-ui/stor
|
|
|
6
6
|
import { resource } from "@assistant-ui/tap";
|
|
7
7
|
//#region src/react/client/Interactables.ts
|
|
8
8
|
const PERSISTENCE_DEBOUNCE_MS = 500;
|
|
9
|
-
const
|
|
9
|
+
const useInteractables = () => {
|
|
10
10
|
const [state, setState] = useState(() => ({
|
|
11
11
|
definitions: {},
|
|
12
12
|
persistence: {}
|
|
@@ -248,8 +248,9 @@ const Interactables = resource(function Interactables() {
|
|
|
248
248
|
setPersistenceAdapter,
|
|
249
249
|
flush
|
|
250
250
|
};
|
|
251
|
-
}
|
|
252
|
-
|
|
251
|
+
};
|
|
252
|
+
const Interactables = resource(useInteractables);
|
|
253
|
+
attachTransformScopes(useInteractables, (scopes, parent) => {
|
|
253
254
|
if (!scopes.modelContext && parent.modelContext.source === null) scopes.modelContext = ModelContext();
|
|
254
255
|
});
|
|
255
256
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Interactables.js","names":[],"sources":["../../../src/react/client/Interactables.ts"],"sourcesContent":["import { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport { resource } from \"@assistant-ui/tap\";\nimport {\n useAssistantClientRef,\n type ClientOutput,\n attachTransformScopes,\n} from \"@assistant-ui/store\";\nimport type {\n InteractablesState,\n InteractableRegistration,\n InteractableStateSchema,\n InteractablePersistedState,\n InteractablePersistenceAdapter,\n} from \"../types/scopes/interactables\";\nimport { toJSONSchema, toPartialJSONSchema } from \"assistant-stream\";\nimport { ModelContext } from \"../../store\";\nimport { buildInteractableModelContext } from \"./interactable-model-context\";\n\nconst PERSISTENCE_DEBOUNCE_MS = 500;\n\nexport const Interactables = resource(\n function Interactables(): ClientOutput<\"interactables\"> {\n const [state, setState] = useState<InteractablesState>(() => ({\n definitions: {},\n persistence: {},\n }));\n\n const clientRef = useAssistantClientRef();\n\n const stateRef = useRef(state);\n useEffect(() => {\n stateRef.current = state;\n }, [state]);\n\n const subscribersRef = useRef(new Set<() => void>());\n const partialSchemaCacheRef = useRef(\n new Map<string, InteractableStateSchema>(),\n );\n const detachedStateRef = useRef(new Map<string, unknown>());\n\n const adapterRef = useRef<InteractablePersistenceAdapter | undefined>(\n undefined,\n );\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(\n undefined,\n );\n const syncSeqRef = useRef(0);\n const hasPendingLocalChangeRef = useRef(false);\n const flushResolversRef = useRef<Array<() => void>>([]);\n const dirtyIdsRef = useRef(new Set<string>());\n\n const runPersistence = useCallback(async () => {\n const adapter = adapterRef.current;\n if (!adapter) {\n for (const resolve of flushResolversRef.current) resolve();\n flushResolversRef.current = [];\n return;\n }\n\n const seq = ++syncSeqRef.current;\n const dirtyIds = new Set(dirtyIdsRef.current);\n dirtyIdsRef.current.clear();\n hasPendingLocalChangeRef.current = true;\n\n // Snapshot before any await so unregistered definitions are still included.\n const exported = stateRef.current.definitions;\n const payload: InteractablePersistedState = {};\n for (const [id, def] of Object.entries(exported)) {\n payload[id] = { name: def.name, state: def.state };\n }\n\n setState((prev) => ({\n ...prev,\n persistence: {\n ...prev.persistence,\n ...Object.fromEntries(\n [...dirtyIds].map((id) => [\n id,\n { isPending: true, error: undefined },\n ]),\n ),\n },\n }));\n\n try {\n await adapter.save(payload);\n if (syncSeqRef.current === seq) {\n hasPendingLocalChangeRef.current = false;\n setState((prev) => {\n const persistence = { ...prev.persistence };\n for (const id of dirtyIds) delete persistence[id];\n return { ...prev, persistence };\n });\n }\n } catch (e) {\n if (syncSeqRef.current === seq) {\n hasPendingLocalChangeRef.current = false;\n setState((prev) => ({\n ...prev,\n persistence: {\n ...prev.persistence,\n ...Object.fromEntries(\n [...dirtyIds].map((id) => [id, { isPending: false, error: e }]),\n ),\n },\n }));\n }\n } finally {\n if (dirtyIdsRef.current.size > 0 && adapterRef.current) {\n runPersistence();\n } else {\n for (const resolve of flushResolversRef.current) resolve();\n flushResolversRef.current = [];\n }\n }\n }, []);\n\n const schedulePersistence = useCallback(\n (id: string) => {\n if (!adapterRef.current) return;\n dirtyIdsRef.current.add(id);\n if (debounceTimerRef.current !== undefined) {\n clearTimeout(debounceTimerRef.current);\n }\n debounceTimerRef.current = setTimeout(() => {\n debounceTimerRef.current = undefined;\n if (!hasPendingLocalChangeRef.current) {\n runPersistence();\n } else {\n debounceTimerRef.current = setTimeout(() => {\n debounceTimerRef.current = undefined;\n runPersistence();\n }, PERSISTENCE_DEBOUNCE_MS);\n }\n }, PERSISTENCE_DEBOUNCE_MS);\n },\n [runPersistence],\n );\n\n const exportState = useCallback((): InteractablePersistedState => {\n const result: InteractablePersistedState = {};\n for (const [id, def] of Object.entries(stateRef.current.definitions)) {\n result[id] = { name: def.name, state: def.state };\n }\n return result;\n }, []);\n\n const importState = useCallback((saved: InteractablePersistedState) => {\n for (const [id, entry] of Object.entries(saved)) {\n detachedStateRef.current.set(id, entry.state);\n }\n setState((prev) => {\n let changed = false;\n const definitions = { ...prev.definitions };\n for (const [id, entry] of Object.entries(saved)) {\n if (definitions[id]) {\n definitions[id] = { ...definitions[id], state: entry.state };\n changed = true;\n }\n }\n return changed ? { ...prev, definitions } : prev;\n });\n }, []);\n\n const setPersistenceAdapter = useCallback(\n (adapter: InteractablePersistenceAdapter | undefined) => {\n adapterRef.current = adapter;\n },\n [],\n );\n\n const flush = useCallback(async () => {\n if (debounceTimerRef.current !== undefined) {\n clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = undefined;\n }\n if (!adapterRef.current) return;\n if (!hasPendingLocalChangeRef.current && dirtyIdsRef.current.size === 0)\n return;\n const p = new Promise<void>((resolve) => {\n flushResolversRef.current.push(resolve);\n });\n if (!hasPendingLocalChangeRef.current) {\n runPersistence();\n }\n return p;\n }, [runPersistence]);\n\n const flushIfPending = useCallback(() => {\n if (adapterRef.current && debounceTimerRef.current !== undefined) {\n clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = undefined;\n runPersistence();\n }\n }, [runPersistence]);\n\n const setDefState = useCallback(\n (id: string, updater: (prev: unknown) => unknown) => {\n setState((prev) => {\n const existing = prev.definitions[id];\n if (!existing) return prev;\n return {\n ...prev,\n definitions: {\n ...prev.definitions,\n [id]: { ...existing, state: updater(existing.state) },\n },\n };\n });\n if (stateRef.current.definitions[id]) schedulePersistence(id);\n },\n [schedulePersistence],\n );\n\n const setDefSelected = useCallback((id: string, selected: boolean) => {\n setState((prev) => {\n const existing = prev.definitions[id];\n if (!existing) return prev;\n return {\n ...prev,\n definitions: {\n ...prev.definitions,\n [id]: { ...existing, selected },\n },\n };\n });\n }, []);\n\n const provider = useMemo(\n () => ({\n getModelContext: () => {\n const defs = stateRef.current.definitions;\n return (\n buildInteractableModelContext(\n defs,\n partialSchemaCacheRef.current,\n setDefState,\n ) ?? {}\n );\n },\n subscribe: (callback: () => void) => {\n subscribersRef.current.add(callback);\n return () => {\n subscribersRef.current.delete(callback);\n };\n },\n }),\n [setDefState],\n );\n\n useEffect(() => {\n for (const cb of subscribersRef.current) cb();\n }, [state]);\n\n useEffect(() => {\n return clientRef.current!.modelContext().register(provider);\n }, [clientRef, provider]);\n\n const register = useCallback(\n (def: InteractableRegistration) => {\n try {\n const jsonSchema = toJSONSchema(def.stateSchema);\n partialSchemaCacheRef.current.set(\n def.id,\n toPartialJSONSchema(jsonSchema),\n );\n } catch (e) {\n console.warn(\n `[Interactables] Failed to create partial schema for \"${def.name}\". The update tool will require all fields.`,\n e,\n );\n }\n\n const detached = detachedStateRef.current.get(def.id);\n detachedStateRef.current.delete(def.id);\n\n setState((prev) => ({\n ...prev,\n definitions: {\n ...prev.definitions,\n [def.id]: {\n id: def.id,\n name: def.name,\n description: def.description,\n stateSchema: def.stateSchema,\n state:\n prev.definitions[def.id]?.state ?? detached ?? def.initialState,\n selected: def.selected,\n },\n },\n }));\n\n return () => {\n flushIfPending();\n setState((prev) => {\n const existing = prev.definitions[def.id];\n if (existing) {\n detachedStateRef.current.set(def.id, existing.state);\n }\n partialSchemaCacheRef.current.delete(def.id);\n const { [def.id]: _, ...rest } = prev.definitions;\n const { [def.id]: __, ...restPersistence } = prev.persistence;\n return { ...prev, definitions: rest, persistence: restPersistence };\n });\n };\n },\n [flushIfPending],\n );\n\n return {\n getState: () => state,\n register,\n setState: setDefState,\n setSelected: setDefSelected,\n exportState,\n importState,\n setPersistenceAdapter,\n flush,\n };\n },\n);\n\nattachTransformScopes(Interactables, (scopes, parent) => {\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Interactables.js","names":[],"sources":["../../../src/react/client/Interactables.ts"],"sourcesContent":["import { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport { resource } from \"@assistant-ui/tap\";\nimport {\n useAssistantClientRef,\n type ClientOutput,\n attachTransformScopes,\n} from \"@assistant-ui/store\";\nimport type {\n InteractablesState,\n InteractableRegistration,\n InteractableStateSchema,\n InteractablePersistedState,\n InteractablePersistenceAdapter,\n} from \"../types/scopes/interactables\";\nimport { toJSONSchema, toPartialJSONSchema } from \"assistant-stream\";\nimport { ModelContext } from \"../../store\";\nimport { buildInteractableModelContext } from \"./interactable-model-context\";\n\nconst PERSISTENCE_DEBOUNCE_MS = 500;\n\nconst useInteractables = (): ClientOutput<\"interactables\"> => {\n const [state, setState] = useState<InteractablesState>(() => ({\n definitions: {},\n persistence: {},\n }));\n\n const clientRef = useAssistantClientRef();\n\n const stateRef = useRef(state);\n useEffect(() => {\n stateRef.current = state;\n }, [state]);\n\n const subscribersRef = useRef(new Set<() => void>());\n const partialSchemaCacheRef = useRef(\n new Map<string, InteractableStateSchema>(),\n );\n const detachedStateRef = useRef(new Map<string, unknown>());\n\n const adapterRef = useRef<InteractablePersistenceAdapter | undefined>(\n undefined,\n );\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(\n undefined,\n );\n const syncSeqRef = useRef(0);\n const hasPendingLocalChangeRef = useRef(false);\n const flushResolversRef = useRef<Array<() => void>>([]);\n const dirtyIdsRef = useRef(new Set<string>());\n\n const runPersistence = useCallback(async () => {\n const adapter = adapterRef.current;\n if (!adapter) {\n for (const resolve of flushResolversRef.current) resolve();\n flushResolversRef.current = [];\n return;\n }\n\n const seq = ++syncSeqRef.current;\n const dirtyIds = new Set(dirtyIdsRef.current);\n dirtyIdsRef.current.clear();\n hasPendingLocalChangeRef.current = true;\n\n // Snapshot before any await so unregistered definitions are still included.\n const exported = stateRef.current.definitions;\n const payload: InteractablePersistedState = {};\n for (const [id, def] of Object.entries(exported)) {\n payload[id] = { name: def.name, state: def.state };\n }\n\n setState((prev) => ({\n ...prev,\n persistence: {\n ...prev.persistence,\n ...Object.fromEntries(\n [...dirtyIds].map((id) => [\n id,\n { isPending: true, error: undefined },\n ]),\n ),\n },\n }));\n\n try {\n await adapter.save(payload);\n if (syncSeqRef.current === seq) {\n hasPendingLocalChangeRef.current = false;\n setState((prev) => {\n const persistence = { ...prev.persistence };\n for (const id of dirtyIds) delete persistence[id];\n return { ...prev, persistence };\n });\n }\n } catch (e) {\n if (syncSeqRef.current === seq) {\n hasPendingLocalChangeRef.current = false;\n setState((prev) => ({\n ...prev,\n persistence: {\n ...prev.persistence,\n ...Object.fromEntries(\n [...dirtyIds].map((id) => [id, { isPending: false, error: e }]),\n ),\n },\n }));\n }\n } finally {\n if (dirtyIdsRef.current.size > 0 && adapterRef.current) {\n runPersistence();\n } else {\n for (const resolve of flushResolversRef.current) resolve();\n flushResolversRef.current = [];\n }\n }\n }, []);\n\n const schedulePersistence = useCallback(\n (id: string) => {\n if (!adapterRef.current) return;\n dirtyIdsRef.current.add(id);\n if (debounceTimerRef.current !== undefined) {\n clearTimeout(debounceTimerRef.current);\n }\n debounceTimerRef.current = setTimeout(() => {\n debounceTimerRef.current = undefined;\n if (!hasPendingLocalChangeRef.current) {\n runPersistence();\n } else {\n debounceTimerRef.current = setTimeout(() => {\n debounceTimerRef.current = undefined;\n runPersistence();\n }, PERSISTENCE_DEBOUNCE_MS);\n }\n }, PERSISTENCE_DEBOUNCE_MS);\n },\n [runPersistence],\n );\n\n const exportState = useCallback((): InteractablePersistedState => {\n const result: InteractablePersistedState = {};\n for (const [id, def] of Object.entries(stateRef.current.definitions)) {\n result[id] = { name: def.name, state: def.state };\n }\n return result;\n }, []);\n\n const importState = useCallback((saved: InteractablePersistedState) => {\n for (const [id, entry] of Object.entries(saved)) {\n detachedStateRef.current.set(id, entry.state);\n }\n setState((prev) => {\n let changed = false;\n const definitions = { ...prev.definitions };\n for (const [id, entry] of Object.entries(saved)) {\n if (definitions[id]) {\n definitions[id] = { ...definitions[id], state: entry.state };\n changed = true;\n }\n }\n return changed ? { ...prev, definitions } : prev;\n });\n }, []);\n\n const setPersistenceAdapter = useCallback(\n (adapter: InteractablePersistenceAdapter | undefined) => {\n adapterRef.current = adapter;\n },\n [],\n );\n\n const flush = useCallback(async () => {\n if (debounceTimerRef.current !== undefined) {\n clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = undefined;\n }\n if (!adapterRef.current) return;\n if (!hasPendingLocalChangeRef.current && dirtyIdsRef.current.size === 0)\n return;\n const p = new Promise<void>((resolve) => {\n flushResolversRef.current.push(resolve);\n });\n if (!hasPendingLocalChangeRef.current) {\n runPersistence();\n }\n return p;\n }, [runPersistence]);\n\n const flushIfPending = useCallback(() => {\n if (adapterRef.current && debounceTimerRef.current !== undefined) {\n clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = undefined;\n runPersistence();\n }\n }, [runPersistence]);\n\n const setDefState = useCallback(\n (id: string, updater: (prev: unknown) => unknown) => {\n setState((prev) => {\n const existing = prev.definitions[id];\n if (!existing) return prev;\n return {\n ...prev,\n definitions: {\n ...prev.definitions,\n [id]: { ...existing, state: updater(existing.state) },\n },\n };\n });\n if (stateRef.current.definitions[id]) schedulePersistence(id);\n },\n [schedulePersistence],\n );\n\n const setDefSelected = useCallback((id: string, selected: boolean) => {\n setState((prev) => {\n const existing = prev.definitions[id];\n if (!existing) return prev;\n return {\n ...prev,\n definitions: {\n ...prev.definitions,\n [id]: { ...existing, selected },\n },\n };\n });\n }, []);\n\n const provider = useMemo(\n () => ({\n getModelContext: () => {\n const defs = stateRef.current.definitions;\n return (\n buildInteractableModelContext(\n defs,\n partialSchemaCacheRef.current,\n setDefState,\n ) ?? {}\n );\n },\n subscribe: (callback: () => void) => {\n subscribersRef.current.add(callback);\n return () => {\n subscribersRef.current.delete(callback);\n };\n },\n }),\n [setDefState],\n );\n\n useEffect(() => {\n for (const cb of subscribersRef.current) cb();\n }, [state]);\n\n useEffect(() => {\n return clientRef.current!.modelContext().register(provider);\n }, [clientRef, provider]);\n\n const register = useCallback(\n (def: InteractableRegistration) => {\n try {\n const jsonSchema = toJSONSchema(def.stateSchema);\n partialSchemaCacheRef.current.set(\n def.id,\n toPartialJSONSchema(jsonSchema),\n );\n } catch (e) {\n console.warn(\n `[Interactables] Failed to create partial schema for \"${def.name}\". The update tool will require all fields.`,\n e,\n );\n }\n\n const detached = detachedStateRef.current.get(def.id);\n detachedStateRef.current.delete(def.id);\n\n setState((prev) => ({\n ...prev,\n definitions: {\n ...prev.definitions,\n [def.id]: {\n id: def.id,\n name: def.name,\n description: def.description,\n stateSchema: def.stateSchema,\n state:\n prev.definitions[def.id]?.state ?? detached ?? def.initialState,\n selected: def.selected,\n },\n },\n }));\n\n return () => {\n flushIfPending();\n setState((prev) => {\n const existing = prev.definitions[def.id];\n if (existing) {\n detachedStateRef.current.set(def.id, existing.state);\n }\n partialSchemaCacheRef.current.delete(def.id);\n const { [def.id]: _, ...rest } = prev.definitions;\n const { [def.id]: __, ...restPersistence } = prev.persistence;\n return { ...prev, definitions: rest, persistence: restPersistence };\n });\n };\n },\n [flushIfPending],\n );\n\n return {\n getState: () => state,\n register,\n setState: setDefState,\n setSelected: setDefSelected,\n exportState,\n importState,\n setPersistenceAdapter,\n flush,\n };\n};\n\nexport const Interactables = resource(useInteractables);\n\nattachTransformScopes(useInteractables, (scopes, parent) => {\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n});\n"],"mappings":"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"}
|
|
@@ -4,21 +4,10 @@ import { ClientOutput } from "@assistant-ui/store";
|
|
|
4
4
|
import { ResourceElement } from "@assistant-ui/tap";
|
|
5
5
|
|
|
6
6
|
//#region src/react/client/Tools.d.ts
|
|
7
|
-
|
|
8
|
-
* Registers tools with model context and installs tool-call renderers.
|
|
9
|
-
*
|
|
10
|
-
* Mount this resource near an assistant subtree when you want to expose a
|
|
11
|
-
* group of tools declaratively. Tool definitions are registered with model
|
|
12
|
-
* context, while each tool renderer is registered with the tools scope for
|
|
13
|
-
* message rendering.
|
|
14
|
-
*/
|
|
15
|
-
declare const Tools: (props: {
|
|
7
|
+
declare const Tools: import("@assistant-ui/tap").Resource<ClientOutput<"tools">, [{
|
|
16
8
|
/** Tools to expose to the model and optional renderers to install. */toolkit?: Toolkit; /** Optional MCP app resource whose tools should be merged into context. */
|
|
17
9
|
mcpApp?: ResourceElement<McpAppResourceOutput> | undefined;
|
|
18
|
-
}
|
|
19
|
-
/** Tools to expose to the model and optional renderers to install. */toolkit?: Toolkit; /** Optional MCP app resource whose tools should be merged into context. */
|
|
20
|
-
mcpApp?: ResourceElement<McpAppResourceOutput> | undefined;
|
|
21
|
-
}>;
|
|
10
|
+
}]>;
|
|
22
11
|
//#endregion
|
|
23
12
|
export { type McpAppResourceOutput, Tools };
|
|
24
13
|
//# sourceMappingURL=Tools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tools.d.ts","names":[],"sources":["../../../src/react/client/Tools.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Tools.d.ts","names":[],"sources":["../../../src/react/client/Tools.ts"],"mappings":";;;;;;cA+Ja,KAAA,8BAAK,QAAA,CAAA,YAAA;EAAL,gFA1HD,OAAA;WAED,eAAA,CAAgB,oBAAA;AAAA"}
|
|
@@ -12,7 +12,7 @@ import { resource, useResources, withKey } from "@assistant-ui/tap";
|
|
|
12
12
|
* context, while each tool renderer is registered with the tools scope for
|
|
13
13
|
* message rendering.
|
|
14
14
|
*/
|
|
15
|
-
const
|
|
15
|
+
const useTools = ({ toolkit, mcpApp }) => {
|
|
16
16
|
const mcpAppOutput = useResources(() => mcpApp ? [withKey("mcpApp", mcpApp)] : [], [mcpApp])[0];
|
|
17
17
|
const [toolUIs, setToolUIs] = useState(() => ({}));
|
|
18
18
|
const state = useMemo(() => ({
|
|
@@ -70,8 +70,9 @@ const Tools = resource(function Tools({ toolkit, mcpApp }) {
|
|
|
70
70
|
getState: () => state,
|
|
71
71
|
setToolUI
|
|
72
72
|
};
|
|
73
|
-
}
|
|
74
|
-
|
|
73
|
+
};
|
|
74
|
+
const Tools = resource(useTools);
|
|
75
|
+
attachTransformScopes(useTools, (scopes, parent) => {
|
|
75
76
|
if (!scopes.modelContext && parent.modelContext.source === null) scopes.modelContext = ModelContext();
|
|
76
77
|
});
|
|
77
78
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tools.js","names":[],"sources":["../../../src/react/client/Tools.ts"],"sourcesContent":["import { useState, useEffect, useCallback, useMemo } from \"react\";\nimport {\n useResources,\n resource,\n withKey,\n type ResourceElement,\n} from \"@assistant-ui/tap\";\nimport {\n useAssistantClientRef,\n type ClientOutput,\n attachTransformScopes,\n} from \"@assistant-ui/store\";\nimport type { McpAppResourceOutput, ToolsState } from \"../types/scopes/tools\";\nimport type { Tool } from \"assistant-stream\";\nimport {\n isStandaloneToolDisplay,\n makeToolCallTextComponent,\n type Toolkit,\n} from \"../model-context/toolbox\";\nimport type { ToolCallMessagePartComponent } from \"../types/MessagePartComponentTypes\";\nimport { ModelContext } from \"../../store\";\n\nexport type { McpAppResourceOutput };\n\n/**\n * Registers tools with model context and installs tool-call renderers.\n *\n * Mount this resource near an assistant subtree when you want to expose a\n * group of tools declaratively. Tool definitions are registered with model\n * context, while each tool renderer is registered with the tools scope for\n * message rendering.\n */\
|
|
1
|
+
{"version":3,"file":"Tools.js","names":[],"sources":["../../../src/react/client/Tools.ts"],"sourcesContent":["import { useState, useEffect, useCallback, useMemo } from \"react\";\nimport {\n useResources,\n resource,\n withKey,\n type ResourceElement,\n} from \"@assistant-ui/tap\";\nimport {\n useAssistantClientRef,\n type ClientOutput,\n attachTransformScopes,\n} from \"@assistant-ui/store\";\nimport type { McpAppResourceOutput, ToolsState } from \"../types/scopes/tools\";\nimport type { Tool } from \"assistant-stream\";\nimport {\n isStandaloneToolDisplay,\n makeToolCallTextComponent,\n type Toolkit,\n} from \"../model-context/toolbox\";\nimport type { ToolCallMessagePartComponent } from \"../types/MessagePartComponentTypes\";\nimport { ModelContext } from \"../../store\";\n\nexport type { McpAppResourceOutput };\n\n/**\n * Registers tools with model context and installs tool-call renderers.\n *\n * Mount this resource near an assistant subtree when you want to expose a\n * group of tools declaratively. Tool definitions are registered with model\n * context, while each tool renderer is registered with the tools scope for\n * message rendering.\n */\nconst useTools = ({\n toolkit,\n mcpApp,\n}: {\n /** Tools to expose to the model and optional renderers to install. */\n toolkit?: Toolkit;\n /** Optional MCP app resource whose tools should be merged into context. */\n mcpApp?: ResourceElement<McpAppResourceOutput> | undefined;\n}): ClientOutput<\"tools\"> => {\n const mcpAppOutputs = useResources(\n () => (mcpApp ? [withKey(\"mcpApp\", mcpApp)] : []),\n [mcpApp],\n );\n const mcpAppOutput = mcpAppOutputs[0];\n\n const [toolUIs, setToolUIs] = useState<ToolsState[\"toolUIs\"]>(() => ({}));\n\n const state = useMemo(\n (): ToolsState => ({\n toolUIs,\n mcpApp: mcpAppOutput,\n // Deprecated component-only view, derived from `toolUIs`. Removed in v0.15.\n tools: Object.fromEntries(\n Object.entries(toolUIs).map(([name, regs]) => [\n name,\n regs.map((r) => r.render),\n ]),\n ),\n }),\n [toolUIs, mcpAppOutput],\n );\n\n const clientRef = useAssistantClientRef();\n\n const setToolUI = useCallback(\n (\n toolName: string,\n render: ToolCallMessagePartComponent,\n options?: { standalone?: boolean },\n ) => {\n // One registration object per call; identity is the removal key, so\n // the per-name list stays correctly ref-counted across re-registers.\n const registration = {\n render,\n standalone: options?.standalone ?? false,\n };\n\n setToolUIs((prev) => ({\n ...prev,\n [toolName]: [...(prev[toolName] ?? []), registration],\n }));\n\n return () => {\n setToolUIs((prev) => {\n const next = prev[toolName]?.filter((r) => r !== registration) ?? [];\n if (next.length > 0) return { ...prev, [toolName]: next };\n // Drop the key entirely so repeatedly mounted/unmounted tools\n // don't leave empty arrays accumulating across a long session.\n const { [toolName]: _removed, ...rest } = prev;\n return rest;\n });\n };\n },\n [],\n );\n\n useEffect(() => {\n if (!toolkit) return;\n const unsubscribes: (() => void)[] = [];\n\n // Register tool UIs (exclude symbols)\n for (const [toolName, tool] of Object.entries(toolkit)) {\n const toolRender = \"render\" in tool ? tool.render : undefined;\n const toolRenderText = \"renderText\" in tool ? tool.renderText : undefined;\n const render =\n toolRender ??\n (toolRenderText\n ? makeToolCallTextComponent(toolRenderText)\n : undefined);\n if (render) {\n unsubscribes.push(\n setToolUI(toolName, render, {\n standalone: isStandaloneToolDisplay(tool),\n }),\n );\n }\n }\n\n // Register tools with model context (exclude symbols). `render`,\n // `renderText`, and `display` are client-only presentation concerns and\n // never reach the model.\n const toolsWithoutRender = Object.entries(toolkit).reduce(\n (acc, [name, tool]) => {\n if (tool.type === \"mcp\") return acc;\n const {\n display: _display,\n render: _render,\n renderText: _renderText,\n ...rest\n } = tool as typeof tool & { renderText?: unknown };\n acc[name] = rest as Tool<any, any>;\n return acc;\n },\n {} as Record<string, Tool<any, any>>,\n );\n\n const modelContextProvider = {\n getModelContext: () => ({\n tools: toolsWithoutRender,\n }),\n };\n\n unsubscribes.push(\n clientRef.current!.modelContext().register(modelContextProvider),\n );\n\n return () => {\n unsubscribes.forEach((fn) => fn());\n };\n }, [toolkit, setToolUI, clientRef]);\n\n return {\n getState: () => state,\n setToolUI,\n };\n};\n\nexport const Tools = resource(useTools);\n\nattachTransformScopes(useTools, (scopes, parent) => {\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n});\n"],"mappings":";;;;;;;;;;;;;;AAgCA,MAAM,YAAY,EAChB,SACA,aAM2B;CAK3B,MAAM,eAJgB,mBACb,SAAS,CAAC,QAAQ,UAAU,MAAM,CAAC,IAAI,CAAC,GAC/C,CAAC,MAAM,CAEwB,CAAC,CAAC;CAEnC,MAAM,CAAC,SAAS,cAAc,gBAAuC,CAAC,EAAE;CAExE,MAAM,QAAQ,eACO;EACjB;EACA,QAAQ;EAER,OAAO,OAAO,YACZ,OAAO,QAAQ,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM,UAAU,CAC5C,MACA,KAAK,KAAK,MAAM,EAAE,MAAM,CAC1B,CAAC,CACH;CACF,IACA,CAAC,SAAS,YAAY,CACxB;CAEA,MAAM,YAAY,sBAAsB;CAExC,MAAM,YAAY,aAEd,UACA,QACA,YACG;EAGH,MAAM,eAAe;GACnB;GACA,YAAY,SAAS,cAAc;EACrC;EAEA,YAAY,UAAU;GACpB,GAAG;IACF,WAAW,CAAC,GAAI,KAAK,aAAa,CAAC,GAAI,YAAY;EACtD,EAAE;EAEF,aAAa;GACX,YAAY,SAAS;IACnB,MAAM,OAAO,KAAK,SAAS,EAAE,QAAQ,MAAM,MAAM,YAAY,KAAK,CAAC;IACnE,IAAI,KAAK,SAAS,GAAG,OAAO;KAAE,GAAG;MAAO,WAAW;IAAK;IAGxD,MAAM,GAAG,WAAW,UAAU,GAAG,SAAS;IAC1C,OAAO;GACT,CAAC;EACH;CACF,GACA,CAAC,CACH;CAEA,gBAAgB;EACd,IAAI,CAAC,SAAS;EACd,MAAM,eAA+B,CAAC;EAGtC,KAAK,MAAM,CAAC,UAAU,SAAS,OAAO,QAAQ,OAAO,GAAG;GACtD,MAAM,aAAa,YAAY,OAAO,KAAK,SAAS,KAAA;GACpD,MAAM,iBAAiB,gBAAgB,OAAO,KAAK,aAAa,KAAA;GAChE,MAAM,SACJ,eACC,iBACG,0BAA0B,cAAc,IACxC,KAAA;GACN,IAAI,QACF,aAAa,KACX,UAAU,UAAU,QAAQ,EAC1B,YAAY,wBAAwB,IAAI,EAC1C,CAAC,CACH;EAEJ;EAKA,MAAM,qBAAqB,OAAO,QAAQ,OAAO,CAAC,CAAC,QAChD,KAAK,CAAC,MAAM,UAAU;GACrB,IAAI,KAAK,SAAS,OAAO,OAAO;GAChC,MAAM,EACJ,SAAS,UACT,QAAQ,SACR,YAAY,aACZ,GAAG,SACD;GACJ,IAAI,QAAQ;GACZ,OAAO;EACT,GACA,CAAC,CACH;EAQA,aAAa,KACX,UAAU,QAAS,aAAa,CAAC,CAAC,SAAS,EAN3C,wBAAwB,EACtB,OAAO,mBACT,GAI8D,CAAC,CACjE;EAEA,aAAa;GACX,aAAa,SAAS,OAAO,GAAG,CAAC;EACnC;CACF,GAAG;EAAC;EAAS;EAAW;CAAS,CAAC;CAElC,OAAO;EACL,gBAAgB;EAChB;CACF;AACF;AAEA,MAAa,QAAQ,SAAS,QAAQ;AAEtC,sBAAsB,WAAW,QAAQ,WAAW;CAClD,IAAI,CAAC,OAAO,gBAAgB,OAAO,aAAa,WAAW,MACzD,OAAO,eAAe,aAAa;AAEvC,CAAC"}
|
|
@@ -36,8 +36,9 @@ declare namespace MessagePrimitiveGroupedParts {
|
|
|
36
36
|
* which running states qualify:
|
|
37
37
|
* - `"never"` — never.
|
|
38
38
|
* - `"empty"` — only when the message has no parts yet.
|
|
39
|
-
* - `"no-text"` (default) — when the
|
|
40
|
-
* (e.g. it ended on a tool call, so the
|
|
39
|
+
* - `"no-text"` (default) — when the message has no parts yet or the last
|
|
40
|
+
* part isn't `text`/`reasoning` (e.g. it ended on a tool call, so the
|
|
41
|
+
* assistant likely isn't done).
|
|
41
42
|
* - `"always"` — whenever the message is running, regardless of parts.
|
|
42
43
|
*/
|
|
43
44
|
type IndicatorMode = "never" | "empty" | "no-text" | "always";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageGroupedParts.d.ts","names":[],"sources":["../../../../src/react/primitives/message/MessageGroupedParts.tsx"],"mappings":";;;;;;;kBAkBiB,4BAAA;;AAAjB;;;;;OAOc,SAAA;IAAA,SACD,IAAA,EAAM,IAAA;IAAA,SACN,MAAA,EAAQ,iBAAA,GAAoB,yBAAA;IAAA,SAC5B,OAAA;EAAA;
|
|
1
|
+
{"version":3,"file":"MessageGroupedParts.d.ts","names":[],"sources":["../../../../src/react/primitives/message/MessageGroupedParts.tsx"],"mappings":";;;;;;;kBAkBiB,4BAAA;;AAAjB;;;;;OAOc,SAAA;IAAA,SACD,IAAA,EAAM,IAAA;IAAA,SACN,MAAA,EAAQ,iBAAA,GAAoB,yBAAA;IAAA,SAC5B,OAAA;EAAA;EA4CU;;;;;;;;;;EAAA,KA/BT,aAAA;IAAA,SACD,IAAA;EAAA;EAhBM;;;;;;;;;;;EAAA,KA8BL,aAAA;EAAA,KAEA,UAAA;IAOuB;;;;;;IAAA,SAAxB,IAAA,EAAM,SAAA,CAAU,IAAA,IAAQ,iBAAA,GAAoB,aAAA;IAyC7C;;;;;;IAAA,SAlCC,QAAA,EAAU,SAAA;EAAA;EAAA,KAGT,KAAA;IAwD2B;;;;AAAmB;AAqH5D;;;;;;;;;;;;;;;;;;;;;;;;IArHyC,SA1B5B,OAAA,GACP,IAAA,EAAM,SAAA,EACN,OAAA,EAAS,cAAA,cACG,IAAA;;;;;;;;;aAUL,SAAA,GAAY,aAAA;;;;;;;;;;;;aAaZ,QAAA,GAAW,IAAA,EAAM,UAAA,CAAW,IAAA,MAAU,SAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAqHtC,4BAAA;EAAA;IAA8D,OAAA;IAAA,SAAA;IAAA;EAAA,GAIxE,4BAAA,CAA6B,KAAA,CAAM,IAAA,IAAQ,SAAA"}
|
|
@@ -15,7 +15,7 @@ const shouldShowIndicator = (mode, parts, isRunning) => {
|
|
|
15
15
|
case "empty": return parts.length === 0;
|
|
16
16
|
case "no-text": {
|
|
17
17
|
const last = parts[parts.length - 1];
|
|
18
|
-
return last
|
|
18
|
+
return last === void 0 || last.type !== "text" && last.type !== "reasoning";
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
};
|
|
@@ -35,7 +35,7 @@ const renderNode = (node, parts, render) => {
|
|
|
35
35
|
part,
|
|
36
36
|
children: /* @__PURE__ */ jsx(PartChildrenSentinel, {})
|
|
37
37
|
})
|
|
38
|
-
}, `part-${node.index}`);
|
|
38
|
+
}, node.idKey ? `part-${node.idKey}` : `part-${node.index}`);
|
|
39
39
|
const status = parts[node.indices.at(-1)]?.status ?? COMPLETE_STATUS;
|
|
40
40
|
return /* @__PURE__ */ jsx(Fragment, { children: render({
|
|
41
41
|
part: {
|
|
@@ -44,7 +44,7 @@ const renderNode = (node, parts, render) => {
|
|
|
44
44
|
indices: node.indices
|
|
45
45
|
},
|
|
46
46
|
children: /* @__PURE__ */ jsx(Fragment$1, { children: node.children.map((child) => renderNode(child, parts, render)) })
|
|
47
|
-
}) }, node.nodeKey);
|
|
47
|
+
}) }, node.idKey ?? node.nodeKey);
|
|
48
48
|
};
|
|
49
49
|
/**
|
|
50
50
|
* Groups adjacent message parts into a tree of coalesced runs and
|
|
@@ -85,7 +85,7 @@ const MessagePrimitiveGroupedParts = ({ groupBy, indicator = "no-text", children
|
|
|
85
85
|
const isRunning = useAuiState((s) => indicator === "never" ? false : s.message.status?.type === "running");
|
|
86
86
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [useMemo(() => {
|
|
87
87
|
const context = { toolUIs };
|
|
88
|
-
return buildGroupTree(parts.map((part) => groupBy(part, context) ?? []));
|
|
88
|
+
return buildGroupTree(parts.map((part) => groupBy(part, context) ?? []), parts.map((part) => part.type === "tool-call" ? part.toolCallId : void 0));
|
|
89
89
|
}, [
|
|
90
90
|
parts,
|
|
91
91
|
groupBy[GROUPBY_MEMO_KEY] ?? groupBy,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageGroupedParts.js","names":[],"sources":["../../../../src/react/primitives/message/MessageGroupedParts.tsx"],"sourcesContent":["\"use client\";\n\nimport { Fragment, type FC, type ReactNode, useMemo } from \"react\";\nimport { useAuiState } from \"@assistant-ui/store\";\nimport { useShallow } from \"zustand/shallow\";\nimport type { PartState } from \"../../../store/scopes/part\";\nimport type {\n MessagePartStatus,\n ToolCallMessagePartStatus,\n} from \"../../../types/message\";\nimport {\n buildGroupTree,\n GROUPBY_MEMO_KEY,\n type GroupByContext,\n type GroupNode,\n} from \"../../utils/groupParts\";\nimport { MessagePartChildren, type EnrichedPartState } from \"./MessageParts\";\n\nexport namespace MessagePrimitiveGroupedParts {\n /**\n * A coalesced group of adjacent parts. Surfaced through the same\n * `{ part }` channel as a leaf {@link EnrichedPartState} so consumers\n * dispatch on a single `switch (part.type)`. `type` is the group key\n * (always `\"group-…\"`); `status` mirrors the last contained part.\n */\n export type GroupPart<TKey extends `group-${string}` = `group-${string}`> = {\n readonly type: TKey;\n readonly status: MessagePartStatus | ToolCallMessagePartStatus;\n readonly indices: readonly number[];\n };\n\n /**\n * Synthetic trailing slot for a streaming/loading affordance (a\n * \"thinking…\" dot, etc.). Surfaced through the same `{ part }` channel\n * as groups and leaf parts so a single `switch (part.type)` renders it\n * via `case \"indicator\"`.\n *\n * It is only ever emitted while the message is running, so its presence\n * alone means \"render your loading UI here\" — there's no `status` to\n * branch on.\n */\n export type IndicatorPart = {\n readonly type: \"indicator\";\n };\n\n /**\n * When to emit the synthetic {@link IndicatorPart}. It is **only** emitted\n * while the message is running (streaming); the mode further restricts\n * which running states qualify:\n * - `\"never\"` — never.\n * - `\"empty\"` — only when the message has no parts yet.\n * - `\"no-text\"` (default) — when the last part isn't `text`/`reasoning`\n * (e.g. it ended on a tool call, so the assistant likely isn't done).\n * - `\"always\"` — whenever the message is running, regardless of parts.\n */\n export type IndicatorMode = \"never\" | \"empty\" | \"no-text\" | \"always\";\n\n export type RenderInfo<TKey extends `group-${string}` = `group-${string}`> = {\n /**\n * Either a coalesced group ({@link GroupPart}, identified by a\n * `group-…` `type`), a single enriched leaf part, or the synthetic\n * {@link IndicatorPart} (`type: \"indicator\"`). Use one switch over\n * `part.type` to handle all three.\n */\n readonly part: GroupPart<TKey> | EnrichedPartState | IndicatorPart;\n /**\n * For group nodes: the recursively-rendered subtree (subgroups +\n * leaf parts). For leaf parts: a sentinel that throws when rendered\n * — accidental fall-through (`default: return children;`) errors\n * loudly instead of silently rendering nothing.\n */\n readonly children: ReactNode;\n };\n\n export type Props<TKey extends `group-${string}` = `group-${string}`> = {\n /**\n * Maps each part to a group-key path. Adjacent parts that share a\n * prefix coalesce into the same group. Return `[]` (or `null`) to\n * leave a part ungrouped.\n *\n * Group keys must start with `\"group-\"` so the renderer's\n * `switch (part.type)` can tell groups apart from real part types.\n *\n * **Prefer {@link groupPartByType}** for the common case of mapping by\n * `part.type` — it ships a stable memo fingerprint so the tree\n * survives unrelated re-renders. Use an inline function only when\n * the helper isn't expressive enough (e.g. branching on\n * `part.toolName` or part metadata).\n *\n * The second argument is a {@link GroupByContext} carrying the tool-UI\n * registry, for grouping that depends on it (e.g. standalone tool calls).\n *\n * @example\n * ```tsx\n * import { groupPartByType } from \"@assistant-ui/react\";\n *\n * <MessagePrimitive.GroupedParts\n * groupBy={groupPartByType({\n * reasoning: [\"group-thought\", \"group-reasoning\"],\n * \"tool-call\": [\"group-thought\", \"group-tool\"],\n * })}\n * >\n * ```\n */\n readonly groupBy: (\n part: PartState,\n context: GroupByContext,\n ) => readonly TKey[] | null;\n\n /**\n * Controls emission of the synthetic {@link IndicatorPart} — a\n * trailing `{ part: { type: \"indicator\", status } }` render call you\n * handle with `case \"indicator\"` to show loading/status UI.\n *\n * @default \"no-text\"\n * @see IndicatorMode\n */\n readonly indicator?: IndicatorMode;\n\n /**\n * Render function called once per group node, once per leaf part, and\n * (when the `indicator` condition is met) once for the trailing\n * {@link IndicatorPart}. Switch on `part.type`: `\"group-…\"` cases wrap\n * `children`; real part types (`\"text\"`, `\"tool-call\"`, …) render the\n * part directly; `\"indicator\"` renders status/loading UI.\n *\n * Leaf parts receive the same {@link EnrichedPartState} that\n * `<MessagePrimitive.Parts>` would produce (`toolUI`, `addResult`,\n * `resume`, `respondToApproval`, `dataRendererUI`).\n */\n readonly children: (info: RenderInfo<TKey>) => ReactNode;\n };\n}\n\nconst COMPLETE_STATUS: MessagePartStatus = Object.freeze({ type: \"complete\" });\n\nconst shouldShowIndicator = (\n mode: MessagePrimitiveGroupedParts.IndicatorMode,\n parts: readonly PartState[],\n isRunning: boolean,\n): boolean => {\n // The indicator is a streaming affordance — never show it on a settled\n // message, whatever the mode.\n if (!isRunning) return false;\n\n switch (mode) {\n case \"never\":\n return false;\n case \"always\":\n return true;\n case \"empty\":\n return parts.length === 0;\n case \"no-text\": {\n const last = parts[parts.length - 1];\n return (\n last !== undefined && last.type !== \"text\" && last.type !== \"reasoning\"\n );\n }\n }\n};\n\n/**\n * `children` placeholder passed for leaf-part renders. Leaf parts have no\n * inner subtree; rendering this sentinel signals the consumer wrote\n * `default: return children;` and accidentally fell through for a part —\n * surface the bug loudly instead of silently rendering nothing.\n */\nconst PartChildrenSentinel: FC = () => {\n throw new Error(\n \"MessagePrimitive.GroupedParts: rendered `children` under a leaf \" +\n \"part. `children` is only meaningful for `group-…` cases — add a \" +\n \"matching case for the part type or return `null` to skip it.\",\n );\n};\n\nconst renderNode = <TKey extends `group-${string}`>(\n node: GroupNode,\n parts: readonly PartState[],\n render: (info: MessagePrimitiveGroupedParts.RenderInfo<TKey>) => ReactNode,\n): ReactNode => {\n if (node.type === \"part\") {\n // Key by absolute part index, not structural nodeKey — prevents zombie fiber subscriptions when parts reshape (#4051).\n return (\n <MessagePartChildren key={`part-${node.index}`} index={node.index}>\n {({ part }) => render({ part, children: <PartChildrenSentinel /> })}\n </MessagePartChildren>\n );\n }\n\n const status = parts[node.indices.at(-1)!]?.status ?? COMPLETE_STATUS;\n const groupPart: MessagePrimitiveGroupedParts.GroupPart<TKey> = {\n type: node.key as TKey,\n status,\n indices: node.indices,\n };\n\n return (\n <Fragment key={node.nodeKey}>\n {render({\n part: groupPart,\n children: (\n <>{node.children.map((child) => renderNode(child, parts, render))}</>\n ),\n })}\n </Fragment>\n );\n};\n\n/**\n * Groups adjacent message parts into a tree of coalesced runs and\n * renders each node — group or part — through a single `children`\n * function.\n *\n * The render function receives `{ part, children }` where `part.type`\n * is either a `\"group-…\"` literal (for a group, `children` is the\n * recursively-rendered subtree) or a real part type (`\"text\"`,\n * `\"tool-call\"`, …) for a leaf (`children` is a sentinel that throws\n * if rendered — use `part.type` to distinguish).\n *\n * @example\n * ```tsx\n * <MessagePrimitive.GroupedParts\n * groupBy={groupPartByType({\n * reasoning: [\"group-thought\", \"group-reasoning\"],\n * \"tool-call\": [\"group-thought\", \"group-tool\"],\n * })}\n * >\n * {({ part, children }) => {\n * switch (part.type) {\n * case \"group-thought\": return <Thought>{children}</Thought>;\n * case \"group-reasoning\": return <Reasoning>{children}</Reasoning>;\n * case \"group-tool\": return <ToolStack>{children}</ToolStack>;\n * case \"text\": return <MarkdownText />;\n * case \"tool-call\": return part.toolUI ?? <ToolFallback {...part} />;\n * case \"indicator\": return <LoadingDots />;\n * default: return null;\n * }\n * }}\n * </MessagePrimitive.GroupedParts>\n * ```\n */\nexport const MessagePrimitiveGroupedParts = <TKey extends `group-${string}`>({\n groupBy,\n indicator = \"no-text\",\n children,\n}: MessagePrimitiveGroupedParts.Props<TKey>): ReactNode => {\n const parts = useAuiState(useShallow((s) => s.message.parts));\n // Handed to `groupBy` as its `context` argument (see GroupByContext).\n const toolUIs = useAuiState((s) => s.tools.toolUIs);\n // Subscribe to a boolean, not the status object: the tree only needs to\n // re-render when running-ness flips, and `\"never\"` opts out entirely.\n const isRunning = useAuiState((s) =>\n indicator === \"never\" ? false : s.message.status?.type === \"running\",\n );\n\n // Helpers like `groupPartByType` tag the function with `GROUPBY_MEMO_KEY`\n // (a stable string fingerprint of the helper config). When present,\n // memo on `[parts, memoKey]` so the tree survives unrelated renders.\n // For inline `groupBy`, fall back to recomputing each render — O(n)\n // and cheap.\n const memoKey = (groupBy as { [GROUPBY_MEMO_KEY]?: string })[\n GROUPBY_MEMO_KEY\n ];\n const memoDep = memoKey ?? groupBy;\n const tree = useMemo(() => {\n const context: GroupByContext = { toolUIs };\n return buildGroupTree(parts.map((part) => groupBy(part, context) ?? []));\n // oxlint-disable-next-line react/exhaustive-deps -- groupBy is captured via memoDep (either its identity or the helper's memoKey fingerprint); listing it directly would defeat the helper-tagged memo path\n }, [parts, memoDep, toolUIs]);\n\n return (\n <>\n {tree.map((node) => renderNode(node, parts, children))}\n {shouldShowIndicator(indicator, parts, isRunning) &&\n children({\n part: { type: \"indicator\" },\n children: <PartChildrenSentinel />,\n })}\n </>\n );\n};\n\nMessagePrimitiveGroupedParts.displayName = \"MessagePrimitive.GroupedParts\";\n"],"mappings":";;;;;;;;AAsIA,MAAM,kBAAqC,OAAO,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7E,MAAM,uBACJ,MACA,OACA,cACY;CAGZ,IAAI,CAAC,WAAW,OAAO;CAEvB,QAAQ,MAAR;EACE,KAAK,SACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,SACH,OAAO,MAAM,WAAW;EAC1B,KAAK,WAAW;GACd,MAAM,OAAO,MAAM,MAAM,SAAS;GAClC,OACE,SAAS,KAAA,KAAa,KAAK,SAAS,UAAU,KAAK,SAAS;EAEhE;CACF;AACF;;;;;;;AAQA,MAAM,6BAAiC;CACrC,MAAM,IAAI,MACR,8LAGF;AACF;AAEA,MAAM,cACJ,MACA,OACA,WACc;CACd,IAAI,KAAK,SAAS,QAEhB,OACE,oBAAC,qBAAD;EAAgD,OAAO,KAAK;aACxD,EAAE,WAAW,OAAO;GAAE;GAAM,UAAU,oBAAC,sBAAD,CAAuB,CAAA;EAAE,CAAC;CAC/C,GAFK,QAAQ,KAAK,OAElB;CAIzB,MAAM,SAAS,MAAM,KAAK,QAAQ,GAAG,EAAE,EAAG,EAAE,UAAU;CAOtD,OACE,oBAAC,UAAD,EAAA,UACG,OAAO;EACN,MAAM;GARV,MAAM,KAAK;GACX;GACA,SAAS,KAAK;EAMI;EACd,UACE,oBAAA,YAAA,EAAA,UAAG,KAAK,SAAS,KAAK,UAAU,WAAW,OAAO,OAAO,MAAM,CAAC,EAAI,CAAA;CAExE,CAAC,EACO,GAPK,KAAK,OAOV;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAa,gCAAgE,EAC3E,SACA,YAAY,WACZ,eACyD;CACzD,MAAM,QAAQ,YAAY,YAAY,MAAM,EAAE,QAAQ,KAAK,CAAC;CAE5D,MAAM,UAAU,aAAa,MAAM,EAAE,MAAM,OAAO;CAGlD,MAAM,YAAY,aAAa,MAC7B,cAAc,UAAU,QAAQ,EAAE,QAAQ,QAAQ,SAAS,SAC7D;CAiBA,OACE,qBAAA,YAAA,EAAA,UAAA,CAPW,cAAc;EACzB,MAAM,UAA0B,EAAE,QAAQ;EAC1C,OAAO,eAAe,MAAM,KAAK,SAAS,QAAQ,MAAM,OAAO,KAAK,CAAC,CAAC,CAAC;CAEzE,GAAG;EAAC;EARa,QACf,qBAEyB;EAKP;CAAO,CAInB,CAAC,CAAC,KAAK,SAAS,WAAW,MAAM,OAAO,QAAQ,CAAC,GACpD,oBAAoB,WAAW,OAAO,SAAS,KAC9C,SAAS;EACP,MAAM,EAAE,MAAM,YAAY;EAC1B,UAAU,oBAAC,sBAAD,CAAuB,CAAA;CACnC,CAAC,CACH,EAAA,CAAA;AAEN;AAEA,6BAA6B,cAAc"}
|
|
1
|
+
{"version":3,"file":"MessageGroupedParts.js","names":[],"sources":["../../../../src/react/primitives/message/MessageGroupedParts.tsx"],"sourcesContent":["\"use client\";\n\nimport { Fragment, type FC, type ReactNode, useMemo } from \"react\";\nimport { useAuiState } from \"@assistant-ui/store\";\nimport { useShallow } from \"zustand/shallow\";\nimport type { PartState } from \"../../../store/scopes/part\";\nimport type {\n MessagePartStatus,\n ToolCallMessagePartStatus,\n} from \"../../../types/message\";\nimport {\n buildGroupTree,\n GROUPBY_MEMO_KEY,\n type GroupByContext,\n type GroupNode,\n} from \"../../utils/groupParts\";\nimport { MessagePartChildren, type EnrichedPartState } from \"./MessageParts\";\n\nexport namespace MessagePrimitiveGroupedParts {\n /**\n * A coalesced group of adjacent parts. Surfaced through the same\n * `{ part }` channel as a leaf {@link EnrichedPartState} so consumers\n * dispatch on a single `switch (part.type)`. `type` is the group key\n * (always `\"group-…\"`); `status` mirrors the last contained part.\n */\n export type GroupPart<TKey extends `group-${string}` = `group-${string}`> = {\n readonly type: TKey;\n readonly status: MessagePartStatus | ToolCallMessagePartStatus;\n readonly indices: readonly number[];\n };\n\n /**\n * Synthetic trailing slot for a streaming/loading affordance (a\n * \"thinking…\" dot, etc.). Surfaced through the same `{ part }` channel\n * as groups and leaf parts so a single `switch (part.type)` renders it\n * via `case \"indicator\"`.\n *\n * It is only ever emitted while the message is running, so its presence\n * alone means \"render your loading UI here\" — there's no `status` to\n * branch on.\n */\n export type IndicatorPart = {\n readonly type: \"indicator\";\n };\n\n /**\n * When to emit the synthetic {@link IndicatorPart}. It is **only** emitted\n * while the message is running (streaming); the mode further restricts\n * which running states qualify:\n * - `\"never\"` — never.\n * - `\"empty\"` — only when the message has no parts yet.\n * - `\"no-text\"` (default) — when the message has no parts yet or the last\n * part isn't `text`/`reasoning` (e.g. it ended on a tool call, so the\n * assistant likely isn't done).\n * - `\"always\"` — whenever the message is running, regardless of parts.\n */\n export type IndicatorMode = \"never\" | \"empty\" | \"no-text\" | \"always\";\n\n export type RenderInfo<TKey extends `group-${string}` = `group-${string}`> = {\n /**\n * Either a coalesced group ({@link GroupPart}, identified by a\n * `group-…` `type`), a single enriched leaf part, or the synthetic\n * {@link IndicatorPart} (`type: \"indicator\"`). Use one switch over\n * `part.type` to handle all three.\n */\n readonly part: GroupPart<TKey> | EnrichedPartState | IndicatorPart;\n /**\n * For group nodes: the recursively-rendered subtree (subgroups +\n * leaf parts). For leaf parts: a sentinel that throws when rendered\n * — accidental fall-through (`default: return children;`) errors\n * loudly instead of silently rendering nothing.\n */\n readonly children: ReactNode;\n };\n\n export type Props<TKey extends `group-${string}` = `group-${string}`> = {\n /**\n * Maps each part to a group-key path. Adjacent parts that share a\n * prefix coalesce into the same group. Return `[]` (or `null`) to\n * leave a part ungrouped.\n *\n * Group keys must start with `\"group-\"` so the renderer's\n * `switch (part.type)` can tell groups apart from real part types.\n *\n * **Prefer {@link groupPartByType}** for the common case of mapping by\n * `part.type` — it ships a stable memo fingerprint so the tree\n * survives unrelated re-renders. Use an inline function only when\n * the helper isn't expressive enough (e.g. branching on\n * `part.toolName` or part metadata).\n *\n * The second argument is a {@link GroupByContext} carrying the tool-UI\n * registry, for grouping that depends on it (e.g. standalone tool calls).\n *\n * @example\n * ```tsx\n * import { groupPartByType } from \"@assistant-ui/react\";\n *\n * <MessagePrimitive.GroupedParts\n * groupBy={groupPartByType({\n * reasoning: [\"group-thought\", \"group-reasoning\"],\n * \"tool-call\": [\"group-thought\", \"group-tool\"],\n * })}\n * >\n * ```\n */\n readonly groupBy: (\n part: PartState,\n context: GroupByContext,\n ) => readonly TKey[] | null;\n\n /**\n * Controls emission of the synthetic {@link IndicatorPart} — a\n * trailing `{ part: { type: \"indicator\", status } }` render call you\n * handle with `case \"indicator\"` to show loading/status UI.\n *\n * @default \"no-text\"\n * @see IndicatorMode\n */\n readonly indicator?: IndicatorMode;\n\n /**\n * Render function called once per group node, once per leaf part, and\n * (when the `indicator` condition is met) once for the trailing\n * {@link IndicatorPart}. Switch on `part.type`: `\"group-…\"` cases wrap\n * `children`; real part types (`\"text\"`, `\"tool-call\"`, …) render the\n * part directly; `\"indicator\"` renders status/loading UI.\n *\n * Leaf parts receive the same {@link EnrichedPartState} that\n * `<MessagePrimitive.Parts>` would produce (`toolUI`, `addResult`,\n * `resume`, `respondToApproval`, `dataRendererUI`).\n */\n readonly children: (info: RenderInfo<TKey>) => ReactNode;\n };\n}\n\nconst COMPLETE_STATUS: MessagePartStatus = Object.freeze({ type: \"complete\" });\n\nconst shouldShowIndicator = (\n mode: MessagePrimitiveGroupedParts.IndicatorMode,\n parts: readonly PartState[],\n isRunning: boolean,\n): boolean => {\n // The indicator is a streaming affordance — never show it on a settled\n // message, whatever the mode.\n if (!isRunning) return false;\n\n switch (mode) {\n case \"never\":\n return false;\n case \"always\":\n return true;\n case \"empty\":\n return parts.length === 0;\n case \"no-text\": {\n const last = parts[parts.length - 1];\n return (\n last === undefined ||\n (last.type !== \"text\" && last.type !== \"reasoning\")\n );\n }\n }\n};\n\n/**\n * `children` placeholder passed for leaf-part renders. Leaf parts have no\n * inner subtree; rendering this sentinel signals the consumer wrote\n * `default: return children;` and accidentally fell through for a part —\n * surface the bug loudly instead of silently rendering nothing.\n */\nconst PartChildrenSentinel: FC = () => {\n throw new Error(\n \"MessagePrimitive.GroupedParts: rendered `children` under a leaf \" +\n \"part. `children` is only meaningful for `group-…` cases — add a \" +\n \"matching case for the part type or return `null` to skip it.\",\n );\n};\n\nconst renderNode = <TKey extends `group-${string}`>(\n node: GroupNode,\n parts: readonly PartState[],\n render: (info: MessagePrimitiveGroupedParts.RenderInfo<TKey>) => ReactNode,\n): ReactNode => {\n if (node.type === \"part\") {\n // Key by part identity when available, else absolute part index — never\n // the structural nodeKey, which leaves zombie fiber subscriptions when\n // parts reshape (#4051).\n return (\n <MessagePartChildren\n key={node.idKey ? `part-${node.idKey}` : `part-${node.index}`}\n index={node.index}\n >\n {({ part }) => render({ part, children: <PartChildrenSentinel /> })}\n </MessagePartChildren>\n );\n }\n\n const status = parts[node.indices.at(-1)!]?.status ?? COMPLETE_STATUS;\n const groupPart: MessagePrimitiveGroupedParts.GroupPart<TKey> = {\n type: node.key as TKey,\n status,\n indices: node.indices,\n };\n\n return (\n <Fragment key={node.idKey ?? node.nodeKey}>\n {render({\n part: groupPart,\n children: (\n <>{node.children.map((child) => renderNode(child, parts, render))}</>\n ),\n })}\n </Fragment>\n );\n};\n\n/**\n * Groups adjacent message parts into a tree of coalesced runs and\n * renders each node — group or part — through a single `children`\n * function.\n *\n * The render function receives `{ part, children }` where `part.type`\n * is either a `\"group-…\"` literal (for a group, `children` is the\n * recursively-rendered subtree) or a real part type (`\"text\"`,\n * `\"tool-call\"`, …) for a leaf (`children` is a sentinel that throws\n * if rendered — use `part.type` to distinguish).\n *\n * @example\n * ```tsx\n * <MessagePrimitive.GroupedParts\n * groupBy={groupPartByType({\n * reasoning: [\"group-thought\", \"group-reasoning\"],\n * \"tool-call\": [\"group-thought\", \"group-tool\"],\n * })}\n * >\n * {({ part, children }) => {\n * switch (part.type) {\n * case \"group-thought\": return <Thought>{children}</Thought>;\n * case \"group-reasoning\": return <Reasoning>{children}</Reasoning>;\n * case \"group-tool\": return <ToolStack>{children}</ToolStack>;\n * case \"text\": return <MarkdownText />;\n * case \"tool-call\": return part.toolUI ?? <ToolFallback {...part} />;\n * case \"indicator\": return <LoadingDots />;\n * default: return null;\n * }\n * }}\n * </MessagePrimitive.GroupedParts>\n * ```\n */\nexport const MessagePrimitiveGroupedParts = <TKey extends `group-${string}`>({\n groupBy,\n indicator = \"no-text\",\n children,\n}: MessagePrimitiveGroupedParts.Props<TKey>): ReactNode => {\n const parts = useAuiState(useShallow((s) => s.message.parts));\n // Handed to `groupBy` as its `context` argument (see GroupByContext).\n const toolUIs = useAuiState((s) => s.tools.toolUIs);\n // Subscribe to a boolean, not the status object: the tree only needs to\n // re-render when running-ness flips, and `\"never\"` opts out entirely.\n const isRunning = useAuiState((s) =>\n indicator === \"never\" ? false : s.message.status?.type === \"running\",\n );\n\n // Helpers like `groupPartByType` tag the function with `GROUPBY_MEMO_KEY`\n // (a stable string fingerprint of the helper config). When present,\n // memo on `[parts, memoKey]` so the tree survives unrelated renders.\n // For inline `groupBy`, fall back to recomputing each render — O(n)\n // and cheap.\n const memoKey = (groupBy as { [GROUPBY_MEMO_KEY]?: string })[\n GROUPBY_MEMO_KEY\n ];\n const memoDep = memoKey ?? groupBy;\n const tree = useMemo(() => {\n const context: GroupByContext = { toolUIs };\n return buildGroupTree(\n parts.map((part) => groupBy(part, context) ?? []),\n parts.map((part) =>\n part.type === \"tool-call\" ? part.toolCallId : undefined,\n ),\n );\n // oxlint-disable-next-line react/exhaustive-deps -- groupBy is captured via memoDep (either its identity or the helper's memoKey fingerprint); listing it directly would defeat the helper-tagged memo path\n }, [parts, memoDep, toolUIs]);\n\n return (\n <>\n {tree.map((node) => renderNode(node, parts, children))}\n {shouldShowIndicator(indicator, parts, isRunning) &&\n children({\n part: { type: \"indicator\" },\n children: <PartChildrenSentinel />,\n })}\n </>\n );\n};\n\nMessagePrimitiveGroupedParts.displayName = \"MessagePrimitive.GroupedParts\";\n"],"mappings":";;;;;;;;AAuIA,MAAM,kBAAqC,OAAO,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7E,MAAM,uBACJ,MACA,OACA,cACY;CAGZ,IAAI,CAAC,WAAW,OAAO;CAEvB,QAAQ,MAAR;EACE,KAAK,SACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,SACH,OAAO,MAAM,WAAW;EAC1B,KAAK,WAAW;GACd,MAAM,OAAO,MAAM,MAAM,SAAS;GAClC,OACE,SAAS,KAAA,KACR,KAAK,SAAS,UAAU,KAAK,SAAS;EAE3C;CACF;AACF;;;;;;;AAQA,MAAM,6BAAiC;CACrC,MAAM,IAAI,MACR,8LAGF;AACF;AAEA,MAAM,cACJ,MACA,OACA,WACc;CACd,IAAI,KAAK,SAAS,QAIhB,OACE,oBAAC,qBAAD;EAEE,OAAO,KAAK;aAEV,EAAE,WAAW,OAAO;GAAE;GAAM,UAAU,oBAAC,sBAAD,CAAuB,CAAA;EAAE,CAAC;CAC/C,GAJd,KAAK,QAAQ,QAAQ,KAAK,UAAU,QAAQ,KAAK,OAInC;CAIzB,MAAM,SAAS,MAAM,KAAK,QAAQ,GAAG,EAAE,EAAG,EAAE,UAAU;CAOtD,OACE,oBAAC,UAAD,EAAA,UACG,OAAO;EACN,MAAM;GARV,MAAM,KAAK;GACX;GACA,SAAS,KAAK;EAMI;EACd,UACE,oBAAA,YAAA,EAAA,UAAG,KAAK,SAAS,KAAK,UAAU,WAAW,OAAO,OAAO,MAAM,CAAC,EAAI,CAAA;CAExE,CAAC,EACO,GAPK,KAAK,SAAS,KAAK,OAOxB;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAa,gCAAgE,EAC3E,SACA,YAAY,WACZ,eACyD;CACzD,MAAM,QAAQ,YAAY,YAAY,MAAM,EAAE,QAAQ,KAAK,CAAC;CAE5D,MAAM,UAAU,aAAa,MAAM,EAAE,MAAM,OAAO;CAGlD,MAAM,YAAY,aAAa,MAC7B,cAAc,UAAU,QAAQ,EAAE,QAAQ,QAAQ,SAAS,SAC7D;CAsBA,OACE,qBAAA,YAAA,EAAA,UAAA,CAZW,cAAc;EACzB,MAAM,UAA0B,EAAE,QAAQ;EAC1C,OAAO,eACL,MAAM,KAAK,SAAS,QAAQ,MAAM,OAAO,KAAK,CAAC,CAAC,GAChD,MAAM,KAAK,SACT,KAAK,SAAS,cAAc,KAAK,aAAa,KAAA,CAChD,CACF;CAEF,GAAG;EAAC;EAba,QACf,qBAEyB;EAUP;CAAO,CAInB,CAAC,CAAC,KAAK,SAAS,WAAW,MAAM,OAAO,QAAQ,CAAC,GACpD,oBAAoB,WAAW,OAAO,SAAS,KAC9C,SAAS;EACP,MAAM,EAAE,MAAM,YAAY;EAC1B,UAAU,oBAAC,sBAAD,CAAuB,CAAA;CACnC,CAAC,CACH,EAAA,CAAA;AAEN;AAEA,6BAA6B,cAAc"}
|