@assistant-ui/core 0.3.12 → 0.3.13

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.
Files changed (107) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.js +2 -2
  3. package/dist/index.js.map +1 -1
  4. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  5. package/dist/react/client/interactable-model-context.js +5 -1
  6. package/dist/react/client/interactable-model-context.js.map +1 -1
  7. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  8. package/dist/runtime/api/thread-runtime.js +5 -1
  9. package/dist/runtime/api/thread-runtime.js.map +1 -1
  10. package/dist/runtime/base/base-composer-runtime-core.d.ts +25 -0
  11. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  12. package/dist/runtime/base/base-composer-runtime-core.js +64 -11
  13. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  14. package/dist/runtime/base/base-thread-runtime-core.d.ts +14 -0
  15. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  16. package/dist/runtime/base/base-thread-runtime-core.js +31 -0
  17. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  18. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  19. package/dist/runtime/base/default-edit-composer-runtime-core.js +1 -6
  20. package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
  21. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  22. package/dist/runtime/base/default-thread-composer-runtime-core.js +1 -4
  23. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  24. package/dist/runtime/queue/external-thread-queue-adapter.d.ts +15 -0
  25. package/dist/runtime/queue/external-thread-queue-adapter.d.ts.map +1 -1
  26. package/dist/runtime/queue/message-queue.js +23 -10
  27. package/dist/runtime/queue/message-queue.js.map +1 -1
  28. package/dist/runtimes/external-store/external-store-adapter.d.ts +7 -0
  29. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  30. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +3 -1
  31. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  32. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +49 -13
  33. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  34. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  35. package/dist/runtimes/local/local-thread-runtime-core.js +2 -1
  36. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  37. package/dist/store/clients/external-thread.d.ts +7 -0
  38. package/dist/store/clients/external-thread.d.ts.map +1 -1
  39. package/dist/store/clients/external-thread.js +460 -369
  40. package/dist/store/clients/external-thread.js.map +1 -1
  41. package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
  42. package/dist/store/clients/runtime-adapter.js +5 -2
  43. package/dist/store/clients/runtime-adapter.js.map +1 -1
  44. package/dist/store/clients/single-thread-list.d.ts.map +1 -1
  45. package/dist/store/clients/single-thread-list.js +31 -27
  46. package/dist/store/clients/single-thread-list.js.map +1 -1
  47. package/dist/store/clients/suggestions.d.ts +3 -1
  48. package/dist/store/clients/suggestions.d.ts.map +1 -1
  49. package/dist/store/clients/suggestions.js +65 -37
  50. package/dist/store/clients/suggestions.js.map +1 -1
  51. package/dist/store/index.d.ts +2 -2
  52. package/dist/store/index.js +1 -1
  53. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  54. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +64 -50
  55. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  56. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  57. package/dist/store/runtime-clients/thread-runtime-client.js +98 -82
  58. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  59. package/dist/store/scope-registration.d.ts +2 -2
  60. package/dist/store/scopes/suggestions.d.ts +6 -1
  61. package/dist/store/scopes/suggestions.d.ts.map +1 -1
  62. package/dist/store/scopes/thread.d.ts +17 -0
  63. package/dist/store/scopes/thread.d.ts.map +1 -1
  64. package/dist/types/error.d.ts +15 -1
  65. package/dist/types/error.d.ts.map +1 -1
  66. package/dist/types/error.js +18 -1
  67. package/dist/types/error.js.map +1 -1
  68. package/dist/types/message.d.ts +2 -0
  69. package/dist/types/message.d.ts.map +1 -1
  70. package/dist/types/message.js.map +1 -1
  71. package/package.json +5 -5
  72. package/src/index.ts +1 -0
  73. package/src/react/client/interactable-model-context.ts +6 -1
  74. package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +114 -0
  75. package/src/runtime/api/thread-runtime.ts +8 -1
  76. package/src/runtime/base/base-composer-runtime-core.ts +100 -8
  77. package/src/runtime/base/base-thread-runtime-core.ts +36 -0
  78. package/src/runtime/base/default-edit-composer-runtime-core.ts +1 -15
  79. package/src/runtime/base/default-thread-composer-runtime-core.ts +1 -11
  80. package/src/runtime/queue/external-thread-queue-adapter.ts +17 -0
  81. package/src/runtime/queue/message-queue.ts +26 -9
  82. package/src/runtimes/external-store/external-store-adapter.ts +7 -0
  83. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +100 -26
  84. package/src/runtimes/local/local-thread-runtime-core.ts +4 -1
  85. package/src/store/clients/external-thread.ts +119 -16
  86. package/src/store/clients/runtime-adapter.ts +5 -2
  87. package/src/store/clients/single-thread-list.ts +2 -1
  88. package/src/store/clients/suggestions.ts +39 -13
  89. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +13 -28
  90. package/src/store/runtime-clients/thread-runtime-client.ts +5 -0
  91. package/src/store/scopes/suggestions.ts +6 -0
  92. package/src/store/scopes/thread.ts +17 -0
  93. package/src/tests/append-interactable-snapshots.test.ts +350 -0
  94. package/src/tests/base-composer-runtime-core-send.test.ts +126 -0
  95. package/src/tests/base-composer-runtime-core.test.ts +108 -1
  96. package/src/tests/default-edit-composer-runtime-core.test.ts +0 -68
  97. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +300 -0
  98. package/src/tests/external-thread-attachments.test.tsx +214 -0
  99. package/src/tests/external-thread-parity.test.tsx +54 -0
  100. package/src/tests/external-thread-refetch.test.tsx +117 -0
  101. package/src/tests/external-thread-suggestions.test.tsx +59 -0
  102. package/src/tests/message-queue.test.ts +26 -0
  103. package/src/tests/thread-message-like.test.ts +39 -0
  104. package/src/tests/thread-switch-events.test.tsx +136 -0
  105. package/src/types/error.ts +24 -0
  106. package/src/types/message.ts +2 -0
  107. package/src/tests/default-thread-composer-runtime-core.test.ts +0 -82
@@ -1 +1 @@
1
- {"version":3,"file":"thread-runtime-client.js","names":["Unsubscribe","ThreadRuntimeEventType","ThreadRuntime","useMemo","useEffect","RefObject","useResource","resource","withKey","liveRef","ClientOutput","useAssistantEmit","useClientLookup","useClientResource","ComposerClient","MessageClient","useSubscribable","ThreadState","useMessageClientById","t0","$","_c","runtime","id","threadIdRef","t1","getMessageById","messageRuntime","t2","MessageClientById","useThreadClient","runtimeState","emit","unsubscribers","threadEvents","event","unsubscribe","unstable_on","threadId","getState","push","unsub","t3","t4","composer","t5","messages","t6","m","map","state","length","isLoading","t7","capabilities","extras","isDisabled","isRunning","speech","suggestions","voice","isEmpty","t8","t9","methods","t10","selector","get","key","t11","t12","append","cancelRun","connectVoice","deleteMessage","disconnectVoice","export","getModelContext","getVoiceVolume","import","importExternalState","muteVoice","reset","resumeRun","startRun","stopSpeaking","subscribeVoiceVolume","unmuteVoice","message","__internal_getRuntime","ThreadClient"],"sources":["../../../src/store/runtime-clients/thread-runtime-client.ts"],"sourcesContent":["import type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { ThreadRuntimeEventType } from \"../../runtime/interfaces/thread-runtime-core\";\nimport type { ThreadRuntime } from \"../../runtime/api/thread-runtime\";\nimport { useMemo, useEffect, type RefObject } from \"react\";\nimport { useResource, resource, withKey } from \"@assistant-ui/tap\";\nimport { liveRef } from \"./liveRef\";\nimport type { ClientOutput } from \"@assistant-ui/store\";\nimport {\n useAssistantEmit,\n useClientLookup,\n useClientResource,\n} from \"@assistant-ui/store/client\";\nimport { ComposerClient } from \"./composer-runtime-client\";\nimport { MessageClient } from \"./message-runtime-client\";\nimport { useSubscribable } from \"./useSubscribable\";\nimport type { ThreadState } from \"../scopes/thread\";\n\nconst useMessageClientById = ({\n runtime,\n id,\n threadIdRef,\n}: {\n runtime: ThreadRuntime;\n id: string;\n threadIdRef: RefObject<string>;\n}) => {\n const messageRuntime = useMemo(\n () => runtime.getMessageById(id),\n [runtime, id],\n );\n\n return useResource(MessageClient({ runtime: messageRuntime, threadIdRef }));\n};\n\nconst MessageClientById = resource(useMessageClientById);\n\nconst useThreadClient = ({\n runtime,\n}: {\n runtime: ThreadRuntime;\n}): ClientOutput<\"thread\"> => {\n const runtimeState = useSubscribable(runtime);\n const emit = useAssistantEmit();\n\n useEffect(() => {\n const unsubscribers: Unsubscribe[] = [];\n\n const threadEvents: ThreadRuntimeEventType[] = [\n \"runStart\",\n \"runEnd\",\n \"initialize\",\n \"modelContextUpdate\",\n ];\n\n for (const event of threadEvents) {\n const unsubscribe = runtime.unstable_on(event, () => {\n const threadId = runtime.getState()?.threadId || \"unknown\";\n emit(`thread.${event}`, {\n threadId,\n });\n });\n unsubscribers.push(unsubscribe);\n }\n\n return () => {\n for (const unsub of unsubscribers) unsub();\n };\n }, [runtime, emit]);\n\n const threadIdRef = useMemo(\n () => liveRef(() => runtime.getState()!.threadId),\n [runtime],\n );\n\n const composer = useClientResource(\n ComposerClient({\n runtime: runtime.composer,\n threadIdRef,\n }),\n );\n const messages = useClientLookup(\n runtimeState.messages.map((m) =>\n withKey(m.id, MessageClientById({ runtime, id: m.id, threadIdRef }), [\n runtime,\n m.id,\n threadIdRef,\n ]),\n ),\n );\n\n const state = useMemo<ThreadState>(() => {\n return {\n isEmpty: messages.state.length === 0 && !runtimeState.isLoading,\n isDisabled: runtimeState.isDisabled,\n isLoading: runtimeState.isLoading,\n isRunning: runtimeState.isRunning,\n capabilities: runtimeState.capabilities,\n state: runtimeState.state,\n suggestions: runtimeState.suggestions,\n extras: runtimeState.extras,\n speech: runtimeState.speech,\n voice: runtimeState.voice,\n\n composer: composer.state,\n messages: messages.state,\n };\n }, [runtimeState, messages, composer.state]);\n\n return {\n getState: () => state,\n composer: () => composer.methods,\n append: runtime.append,\n deleteMessage: runtime.deleteMessage,\n startRun: runtime.startRun,\n resumeRun: runtime.resumeRun,\n importExternalState: runtime.importExternalState,\n cancelRun: runtime.cancelRun,\n getModelContext: runtime.getModelContext,\n export: runtime.export,\n import: runtime.import,\n reset: runtime.reset,\n stopSpeaking: runtime.stopSpeaking,\n connectVoice: runtime.connectVoice,\n disconnectVoice: runtime.disconnectVoice,\n getVoiceVolume: runtime.getVoiceVolume,\n subscribeVoiceVolume: runtime.subscribeVoiceVolume,\n muteVoice: runtime.muteVoice,\n unmuteVoice: runtime.unmuteVoice,\n message: (selector) => {\n if (\"id\" in selector) {\n return messages.get({ key: selector.id });\n } else {\n return messages.get(selector);\n }\n },\n __internal_getRuntime: () => runtime,\n };\n};\n\nexport const ThreadClient = resource(useThreadClient);\n"],"mappings":"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"}
1
+ {"version":3,"file":"thread-runtime-client.js","names":["Unsubscribe","ThreadRuntimeEventType","ThreadRuntime","useMemo","useEffect","RefObject","useResource","resource","withKey","liveRef","ClientOutput","useAssistantEmit","useClientLookup","useClientResource","ComposerClient","MessageClient","ThreadSuggestions","useSubscribable","ThreadState","useMessageClientById","t0","$","_c","runtime","id","threadIdRef","t1","getMessageById","messageRuntime","t2","MessageClientById","useThreadClient","runtimeState","emit","unsubscribers","threadEvents","event","unsubscribe","unstable_on","threadId","getState","push","unsub","t3","t4","composer","t5","suggestions","t6","messages","t7","m","map","state","length","isLoading","t8","capabilities","extras","isDisabled","isRunning","speech","voice","isEmpty","t9","t10","methods","t11","t12","selector","get","key","t13","t14","append","cancelRun","connectVoice","deleteMessage","disconnectVoice","export","getModelContext","getVoiceVolume","import","importExternalState","muteVoice","reset","resumeRun","startRun","stopSpeaking","subscribeVoiceVolume","unmuteVoice","message","__internal_getRuntime","ThreadClient"],"sources":["../../../src/store/runtime-clients/thread-runtime-client.ts"],"sourcesContent":["import type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { ThreadRuntimeEventType } from \"../../runtime/interfaces/thread-runtime-core\";\nimport type { ThreadRuntime } from \"../../runtime/api/thread-runtime\";\nimport { useMemo, useEffect, type RefObject } from \"react\";\nimport { useResource, resource, withKey } from \"@assistant-ui/tap\";\nimport { liveRef } from \"./liveRef\";\nimport type { ClientOutput } from \"@assistant-ui/store\";\nimport {\n useAssistantEmit,\n useClientLookup,\n useClientResource,\n} from \"@assistant-ui/store/client\";\nimport { ComposerClient } from \"./composer-runtime-client\";\nimport { MessageClient } from \"./message-runtime-client\";\nimport { ThreadSuggestions } from \"../clients/suggestions\";\nimport { useSubscribable } from \"./useSubscribable\";\nimport type { ThreadState } from \"../scopes/thread\";\n\nconst useMessageClientById = ({\n runtime,\n id,\n threadIdRef,\n}: {\n runtime: ThreadRuntime;\n id: string;\n threadIdRef: RefObject<string>;\n}) => {\n const messageRuntime = useMemo(\n () => runtime.getMessageById(id),\n [runtime, id],\n );\n\n return useResource(MessageClient({ runtime: messageRuntime, threadIdRef }));\n};\n\nconst MessageClientById = resource(useMessageClientById);\n\nconst useThreadClient = ({\n runtime,\n}: {\n runtime: ThreadRuntime;\n}): ClientOutput<\"thread\"> => {\n const runtimeState = useSubscribable(runtime);\n const emit = useAssistantEmit();\n\n useEffect(() => {\n const unsubscribers: Unsubscribe[] = [];\n\n const threadEvents: ThreadRuntimeEventType[] = [\n \"runStart\",\n \"runEnd\",\n \"initialize\",\n \"modelContextUpdate\",\n ];\n\n for (const event of threadEvents) {\n const unsubscribe = runtime.unstable_on(event, () => {\n const threadId = runtime.getState()?.threadId || \"unknown\";\n emit(`thread.${event}`, {\n threadId,\n });\n });\n unsubscribers.push(unsubscribe);\n }\n\n return () => {\n for (const unsub of unsubscribers) unsub();\n };\n }, [runtime, emit]);\n\n const threadIdRef = useMemo(\n () => liveRef(() => runtime.getState()!.threadId),\n [runtime],\n );\n\n const composer = useClientResource(\n ComposerClient({\n runtime: runtime.composer,\n threadIdRef,\n }),\n );\n const suggestions = useClientResource(\n ThreadSuggestions(runtimeState.suggestions),\n );\n const messages = useClientLookup(\n runtimeState.messages.map((m) =>\n withKey(m.id, MessageClientById({ runtime, id: m.id, threadIdRef }), [\n runtime,\n m.id,\n threadIdRef,\n ]),\n ),\n );\n\n const state = useMemo<ThreadState>(() => {\n return {\n isEmpty: messages.state.length === 0 && !runtimeState.isLoading,\n isDisabled: runtimeState.isDisabled,\n isLoading: runtimeState.isLoading,\n isRunning: runtimeState.isRunning,\n capabilities: runtimeState.capabilities,\n state: runtimeState.state,\n suggestions: runtimeState.suggestions,\n extras: runtimeState.extras,\n speech: runtimeState.speech,\n voice: runtimeState.voice,\n\n composer: composer.state,\n messages: messages.state,\n };\n }, [runtimeState, messages, composer.state]);\n\n return {\n getState: () => state,\n composer: () => composer.methods,\n suggestions: () => suggestions.methods,\n append: runtime.append,\n deleteMessage: runtime.deleteMessage,\n startRun: runtime.startRun,\n resumeRun: runtime.resumeRun,\n importExternalState: runtime.importExternalState,\n cancelRun: runtime.cancelRun,\n getModelContext: runtime.getModelContext,\n export: runtime.export,\n import: runtime.import,\n reset: runtime.reset,\n stopSpeaking: runtime.stopSpeaking,\n connectVoice: runtime.connectVoice,\n disconnectVoice: runtime.disconnectVoice,\n getVoiceVolume: runtime.getVoiceVolume,\n subscribeVoiceVolume: runtime.subscribeVoiceVolume,\n muteVoice: runtime.muteVoice,\n unmuteVoice: runtime.unmuteVoice,\n message: (selector) => {\n if (\"id\" in selector) {\n return messages.get({ key: selector.id });\n } else {\n return messages.get(selector);\n }\n },\n __internal_getRuntime: () => runtime,\n };\n};\n\nexport const ThreadClient = resource(useThreadClient);\n"],"mappings":"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"}
@@ -4,10 +4,10 @@ import { AttachmentClientSchema } from "./scopes/attachment.js";
4
4
  import { ComposerClientSchema } from "./scopes/composer.js";
5
5
  import { PartClientSchema } from "./scopes/part.js";
6
6
  import { MessageClientSchema } from "./scopes/message.js";
7
- import { ThreadClientSchema } from "./scopes/thread.js";
8
- import { ThreadsClientSchema } from "./scopes/threads.js";
9
7
  import { SuggestionClientSchema } from "./scopes/suggestion.js";
10
8
  import { SuggestionsClientSchema } from "./scopes/suggestions.js";
9
+ import { ThreadClientSchema } from "./scopes/thread.js";
10
+ import { ThreadsClientSchema } from "./scopes/threads.js";
11
11
  import { ModelContextClientSchema } from "./scopes/model-context.js";
12
12
  import { ChainOfThoughtClientSchema } from "./scopes/chain-of-thought.js";
13
13
  //#region src/store/scope-registration.d.ts
@@ -14,9 +14,14 @@ type SuggestionsMethods = {
14
14
  index: number;
15
15
  }): SuggestionMethods;
16
16
  };
17
+ type SuggestionsMeta = {
18
+ source: "thread";
19
+ query: Record<string, never>;
20
+ };
17
21
  type SuggestionsClientSchema = {
18
22
  methods: SuggestionsMethods;
23
+ meta: SuggestionsMeta;
19
24
  };
20
25
  //#endregion
21
- export { Suggestion, SuggestionsClientSchema, SuggestionsMethods, SuggestionsState };
26
+ export { Suggestion, SuggestionsClientSchema, SuggestionsMeta, SuggestionsMethods, SuggestionsState };
22
27
  //# sourceMappingURL=suggestions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"suggestions.d.ts","names":[],"sources":["../../../src/store/scopes/suggestions.ts"],"mappings":";;KAEY;EACV;EACA;EACA;;KAGU;EACV,aAAa;;KAGH;EACV,YAAY;EACZ,WAAW;IAAS;MAAkB;;KAG5B;EACV,SAAS"}
1
+ {"version":3,"file":"suggestions.d.ts","names":[],"sources":["../../../src/store/scopes/suggestions.ts"],"mappings":";;KAEY;EACV;EACA;EACA;;KAGU;EACV,aAAa;;KAGH;EACV,YAAY;EACZ,WAAW;IAAS;MAAkB;;KAG5B;EACV;EACA,OAAO;;KAGG;EACV,SAAS;EACT,MAAM"}
@@ -5,6 +5,7 @@ import { ExportedMessageRepository } from "../../runtime/utils/message-repositor
5
5
  import { RuntimeCapabilities, SpeechState, ThreadSuggestion, VoiceSessionState } from "../../runtime/interfaces/thread-runtime-core.js";
6
6
  import { ComposerMethods, ComposerState } from "./composer.js";
7
7
  import { MessageMethods, MessageState } from "./message.js";
8
+ import { SuggestionsMethods } from "./suggestions.js";
8
9
  import { CreateAppendMessage, CreateResumeRunConfig, CreateStartRunConfig, ThreadRuntime } from "../../runtime/api/thread-runtime.js";
9
10
  import { ReadonlyJSONValue } from "assistant-stream/utils";
10
11
  //#region src/store/scopes/thread.d.ts
@@ -60,6 +61,10 @@ type ThreadMethods = {
60
61
  * The thread composer runtime.
61
62
  */
62
63
  composer(): ComposerMethods;
64
+ /**
65
+ * The suggestions shown for this thread.
66
+ */
67
+ suggestions(): SuggestionsMethods;
63
68
  /**
64
69
  * Append a new message to the thread.
65
70
  *
@@ -89,6 +94,18 @@ type ThreadMethods = {
89
94
  */
90
95
  resumeRun(config: CreateResumeRunConfig): void;
91
96
  cancelRun(): void;
97
+ /**
98
+ * Re-fetch this thread's state from its backing store, in place: the tap
99
+ * thread's refetch hook, which `threads.reloadMainThread()` prefers and
100
+ * whose rejection it propagates. `capabilities.refetchThread` is the
101
+ * portable feature-detection signal; a legacy-bridged thread reports it
102
+ * there while routing the refetch through its runtime, not this method.
103
+ * The method-shorthand optionality is load-bearing: an explicit
104
+ * `| undefined` stops `ThreadMethods` satisfying `ClientMethods` and
105
+ * collapses the client schema, which only a workspace-level app typecheck
106
+ * surfaces.
107
+ */
108
+ unstable_refetchThread?(): Promise<void>;
92
109
  getModelContext(): ModelContext;
93
110
  export(): ExportedMessageRepository;
94
111
  import(repository: ExportedMessageRepository): void;
@@ -1 +1 @@
1
- {"version":3,"file":"thread.d.ts","names":[],"sources":["../../../src/store/scopes/thread.ts"],"mappings":";;;;;;;;;;KAoBY;;;;WAID;;;;WAIA;;;;WAIA;;;;WAIA;;;;WAIA,cAAc;;;;WAId,mBAAmB;;;;;WAKnB,OAAO;;;;WAIP,sBAAsB;;;;WAItB;;WAEA,QAAQ;WACR,OAAO;WACP,UAAU;;KAGT;;;;EAIV,YAAY;;;;EAIZ,YAAY;;;;;;;;;;;;;;;;;EAiBZ,OAAO,SAAS;EAChB,cAAc,2BAA2B;;;;;EAKzC,SAAS,QAAQ;;;;;EAKjB,UAAU,QAAQ;EAClB;EACA,mBAAmB;EACnB,UAAU;EACV,OAAO,YAAY;;;;;EAKnB,MAAM,2BAA2B;EACjC,oBAAoB;EACpB,QAAQ;IAAY;;IAAiB;MAAkB;;EAEvD;EACA;EACA;EACA;EACA,qBAAqB,uBAAuB;EAC5C;EACA;EACA,0BAA0B;;KAGhB;EACV;EACA;IAAS;;;KAGC;;;;;EAKV;IAAqB;;;;;;EAKrB;IAAmB;;;;;;;EAMnB;IAAuB;;;;;;EAKvB;IAA+B;;;KAGrB;EACV,SAAS;EACT,MAAM;EACN,QAAQ"}
1
+ {"version":3,"file":"thread.d.ts","names":[],"sources":["../../../src/store/scopes/thread.ts"],"mappings":";;;;;;;;;;;KAqBY;;;;WAID;;;;WAIA;;;;WAIA;;;;WAIA;;;;WAIA,cAAc;;;;WAId,mBAAmB;;;;;WAKnB,OAAO;;;;WAIP,sBAAsB;;;;WAItB;;WAEA,QAAQ;WACR,OAAO;WACP,UAAU;;KAGT;;;;EAIV,YAAY;;;;EAIZ,YAAY;;;;EAIZ,eAAe;;;;;;;;;;;;;;;;;EAiBf,OAAO,SAAS;EAChB,cAAc,2BAA2B;;;;;EAKzC,SAAS,QAAQ;;;;;EAKjB,UAAU,QAAQ;EAClB;;;;;;;;;;;;EAYA,2BAA2B;EAC3B,mBAAmB;EACnB,UAAU;EACV,OAAO,YAAY;;;;;EAKnB,MAAM,2BAA2B;EACjC,oBAAoB;EACpB,QAAQ;IAAY;;IAAiB;MAAkB;;EAEvD;EACA;EACA;EACA;EACA,qBAAqB,uBAAuB;EAC5C;EACA;EACA,0BAA0B;;KAGhB;EACV;EACA;IAAS;;;KAGC;;;;;EAKV;IAAqB;;;;;;EAKrB;IAAmB;;;;;;;EAMnB;IAAuB;;;;;;EAKvB;IAA+B;;;KAGrB;EACV,SAAS;EACT,MAAM;EACN,QAAQ"}
@@ -9,7 +9,21 @@ type AssistantError = {
9
9
  readonly display?: ErrorDisplay;
10
10
  };
11
11
  declare const isAssistantError: (value: unknown) => value is AssistantError;
12
+ declare const MESSAGE_NOT_SENT: unique symbol;
13
+ /**
14
+ * Rejection reason for a send that never reached the backend, so nothing ran
15
+ * and nothing is recoverable from the thread. A runtime adapter throws it from
16
+ * `onNew` to hand the message back to the thread composer, which restores the
17
+ * draft it cleared at dispatch time when nothing has claimed the composer
18
+ * since. An edit composer closes at dispatch, so a rejected edit is not
19
+ * restored.
20
+ */
21
+ declare class MessageNotSentError extends Error {
22
+ readonly [MESSAGE_NOT_SENT] = true;
23
+ constructor(message?: string);
24
+ }
25
+ declare const isMessageNotSentError: (error: unknown) => error is MessageNotSentError;
12
26
  declare const toAssistantError: (error: unknown) => AssistantError;
13
27
  //#endregion
14
- export { AssistantError, AssistantErrorCode, ErrorDisplay, ErrorSeverity, isAssistantError, toAssistantError };
28
+ export { AssistantError, AssistantErrorCode, ErrorDisplay, ErrorSeverity, MessageNotSentError, isAssistantError, isMessageNotSentError, toAssistantError };
15
29
  //# sourceMappingURL=error.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","names":[],"sources":["../../src/types/error.ts"],"mappings":";KAAY;KAEA;KAEA;KAMA;WACD,MAAM;WACN;WACA,WAAW;WACX,UAAU;;cAYR,mBAAoB,mBAAiB,SAAS;cA4B9C,mBAAoB,mBAAiB"}
1
+ {"version":3,"file":"error.d.ts","names":[],"sources":["../../src/types/error.ts"],"mappings":";KAAY;KAEA;KAEA;KAMA;WACD,MAAM;WACN;WACA,WAAW;WACX,UAAU;;cAYR,mBAAoB,mBAAiB,SAAS;cA4BrD;;;;;;;;;cAUO,4BAA4B;YAC7B;EAEE,YAAA;;cAMD,wBACX,mBACC,SAAS;cAGC,mBAAoB,mBAAiB"}
@@ -18,6 +18,23 @@ const isAssistantError = (value) => {
18
18
  if ("display" in candidate && candidate.display !== void 0 && (typeof candidate.display !== "string" || !ERROR_DISPLAYS.includes(candidate.display))) return false;
19
19
  return true;
20
20
  };
21
+ const MESSAGE_NOT_SENT = Symbol.for("assistant-ui.message-not-sent");
22
+ /**
23
+ * Rejection reason for a send that never reached the backend, so nothing ran
24
+ * and nothing is recoverable from the thread. A runtime adapter throws it from
25
+ * `onNew` to hand the message back to the thread composer, which restores the
26
+ * draft it cleared at dispatch time when nothing has claimed the composer
27
+ * since. An edit composer closes at dispatch, so a rejected edit is not
28
+ * restored.
29
+ */
30
+ var MessageNotSentError = class extends Error {
31
+ [MESSAGE_NOT_SENT] = true;
32
+ constructor(message = "The message was not sent.") {
33
+ super(message);
34
+ this.name = "MessageNotSentError";
35
+ }
36
+ };
37
+ const isMessageNotSentError = (error) => typeof error === "object" && error !== null && MESSAGE_NOT_SENT in error;
21
38
  const toAssistantError = (error) => {
22
39
  if (isAssistantError(error)) return error;
23
40
  if (error instanceof Error) return {
@@ -41,6 +58,6 @@ const toAssistantError = (error) => {
41
58
  }
42
59
  };
43
60
  //#endregion
44
- export { isAssistantError, toAssistantError };
61
+ export { MessageNotSentError, isAssistantError, isMessageNotSentError, toAssistantError };
45
62
 
46
63
  //# sourceMappingURL=error.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","names":["ErrorSeverity","ErrorDisplay","AssistantErrorCode","AssistantError","code","message","severity","display","ERROR_SEVERITIES","ERROR_DISPLAYS","isAssistantError","value","candidate","Record","undefined","includes","toAssistantError","error","Error","String"],"sources":["../../src/types/error.ts"],"sourcesContent":["export type ErrorSeverity = \"critical\" | \"warning\" | \"info\";\n\nexport type ErrorDisplay = \"inline\" | \"toast\" | \"silent\" | \"dev-only\";\n\nexport type AssistantErrorCode =\n | \"unknown\"\n | \"network\"\n | \"provider\"\n | (string & {});\n\nexport type AssistantError = {\n readonly code: AssistantErrorCode;\n readonly message: string;\n readonly severity?: ErrorSeverity;\n readonly display?: ErrorDisplay;\n};\n\nconst ERROR_SEVERITIES: readonly string[] = [\"critical\", \"warning\", \"info\"];\n\nconst ERROR_DISPLAYS: readonly string[] = [\n \"inline\",\n \"toast\",\n \"silent\",\n \"dev-only\",\n];\n\nexport const isAssistantError = (value: unknown): value is AssistantError => {\n if (typeof value !== \"object\" || value === null) return false;\n const candidate = value as Record<string, unknown>;\n if (\n typeof candidate.code !== \"string\" ||\n typeof candidate.message !== \"string\"\n ) {\n return false;\n }\n if (\n \"severity\" in candidate &&\n candidate.severity !== undefined &&\n (typeof candidate.severity !== \"string\" ||\n !ERROR_SEVERITIES.includes(candidate.severity))\n ) {\n return false;\n }\n if (\n \"display\" in candidate &&\n candidate.display !== undefined &&\n (typeof candidate.display !== \"string\" ||\n !ERROR_DISPLAYS.includes(candidate.display))\n ) {\n return false;\n }\n return true;\n};\n\nexport const toAssistantError = (error: unknown): AssistantError => {\n if (isAssistantError(error)) return error;\n if (error instanceof Error) {\n return { code: \"unknown\", message: error.message };\n }\n if (typeof error === \"string\") {\n return { code: \"unknown\", message: error };\n }\n try {\n return {\n code: \"unknown\",\n message: `[${typeof error}] ${String(error)}`,\n };\n } catch {\n return {\n code: \"unknown\",\n message: `[${typeof error}]`,\n };\n }\n};\n"],"mappings":";AAiBA,MAAMQ,mBAAsC;CAAC;CAAY;CAAW;AAAM;AAE1E,MAAMC,iBAAoC;CACxC;CACA;CACA;CACA;AAAU;AAGZ,MAAaC,oBAAoBC,UAA4C;CAC3E,IAAI,OAAOA,UAAU,YAAYA,UAAU,MAAM,OAAO;CACxD,MAAMC,YAAYD;CAClB,IACE,OAAOC,UAAUR,SAAS,YAC1B,OAAOQ,UAAUP,YAAY,UAE7B,OAAO;CAET,IACE,cAAcO,aACdA,UAAUN,aAAaQ,KAAAA,MACtB,OAAOF,UAAUN,aAAa,YAC7B,CAACE,iBAAiBO,SAASH,UAAUN,QAAQ,IAE/C,OAAO;CAET,IACE,aAAaM,aACbA,UAAUL,YAAYO,KAAAA,MACrB,OAAOF,UAAUL,YAAY,YAC5B,CAACE,eAAeM,SAASH,UAAUL,OAAO,IAE5C,OAAO;CAET,OAAO;AACT;AAEA,MAAaS,oBAAoBC,UAAmC;CAClE,IAAIP,iBAAiBO,KAAK,GAAG,OAAOA;CACpC,IAAIA,iBAAiBC,OACnB,OAAO;EAAEd,MAAM;EAAWC,SAASY,MAAMZ;CAAQ;CAEnD,IAAI,OAAOY,UAAU,UACnB,OAAO;EAAEb,MAAM;EAAWC,SAASY;CAAM;CAE3C,IAAI;EACF,OAAO;GACLb,MAAM;GACNC,SAAS,IAAI,OAAOY,MAAK,IAAKE,OAAOF,KAAK;EAC5C;CACF,QAAQ;EACN,OAAO;GACLb,MAAM;GACNC,SAAS,IAAI,OAAOY,MAAK;EAC3B;CACF;AACF"}
1
+ {"version":3,"file":"error.js","names":["ErrorSeverity","ErrorDisplay","AssistantErrorCode","AssistantError","code","message","severity","display","ERROR_SEVERITIES","ERROR_DISPLAYS","isAssistantError","value","candidate","Record","undefined","includes","MESSAGE_NOT_SENT","Symbol","for","MessageNotSentError","Error","constructor","name","isMessageNotSentError","error","toAssistantError","String"],"sources":["../../src/types/error.ts"],"sourcesContent":["export type ErrorSeverity = \"critical\" | \"warning\" | \"info\";\n\nexport type ErrorDisplay = \"inline\" | \"toast\" | \"silent\" | \"dev-only\";\n\nexport type AssistantErrorCode =\n | \"unknown\"\n | \"network\"\n | \"provider\"\n | (string & {});\n\nexport type AssistantError = {\n readonly code: AssistantErrorCode;\n readonly message: string;\n readonly severity?: ErrorSeverity;\n readonly display?: ErrorDisplay;\n};\n\nconst ERROR_SEVERITIES: readonly string[] = [\"critical\", \"warning\", \"info\"];\n\nconst ERROR_DISPLAYS: readonly string[] = [\n \"inline\",\n \"toast\",\n \"silent\",\n \"dev-only\",\n];\n\nexport const isAssistantError = (value: unknown): value is AssistantError => {\n if (typeof value !== \"object\" || value === null) return false;\n const candidate = value as Record<string, unknown>;\n if (\n typeof candidate.code !== \"string\" ||\n typeof candidate.message !== \"string\"\n ) {\n return false;\n }\n if (\n \"severity\" in candidate &&\n candidate.severity !== undefined &&\n (typeof candidate.severity !== \"string\" ||\n !ERROR_SEVERITIES.includes(candidate.severity))\n ) {\n return false;\n }\n if (\n \"display\" in candidate &&\n candidate.display !== undefined &&\n (typeof candidate.display !== \"string\" ||\n !ERROR_DISPLAYS.includes(candidate.display))\n ) {\n return false;\n }\n return true;\n};\n\nconst MESSAGE_NOT_SENT = Symbol.for(\"assistant-ui.message-not-sent\");\n\n/**\n * Rejection reason for a send that never reached the backend, so nothing ran\n * and nothing is recoverable from the thread. A runtime adapter throws it from\n * `onNew` to hand the message back to the thread composer, which restores the\n * draft it cleared at dispatch time when nothing has claimed the composer\n * since. An edit composer closes at dispatch, so a rejected edit is not\n * restored.\n */\nexport class MessageNotSentError extends Error {\n readonly [MESSAGE_NOT_SENT] = true;\n\n constructor(message = \"The message was not sent.\") {\n super(message);\n this.name = \"MessageNotSentError\";\n }\n}\n\nexport const isMessageNotSentError = (\n error: unknown,\n): error is MessageNotSentError =>\n typeof error === \"object\" && error !== null && MESSAGE_NOT_SENT in error;\n\nexport const toAssistantError = (error: unknown): AssistantError => {\n if (isAssistantError(error)) return error;\n if (error instanceof Error) {\n return { code: \"unknown\", message: error.message };\n }\n if (typeof error === \"string\") {\n return { code: \"unknown\", message: error };\n }\n try {\n return {\n code: \"unknown\",\n message: `[${typeof error}] ${String(error)}`,\n };\n } catch {\n return {\n code: \"unknown\",\n message: `[${typeof error}]`,\n };\n }\n};\n"],"mappings":";AAiBA,MAAMQ,mBAAsC;CAAC;CAAY;CAAW;AAAM;AAE1E,MAAMC,iBAAoC;CACxC;CACA;CACA;CACA;AAAU;AAGZ,MAAaC,oBAAoBC,UAA4C;CAC3E,IAAI,OAAOA,UAAU,YAAYA,UAAU,MAAM,OAAO;CACxD,MAAMC,YAAYD;CAClB,IACE,OAAOC,UAAUR,SAAS,YAC1B,OAAOQ,UAAUP,YAAY,UAE7B,OAAO;CAET,IACE,cAAcO,aACdA,UAAUN,aAAaQ,KAAAA,MACtB,OAAOF,UAAUN,aAAa,YAC7B,CAACE,iBAAiBO,SAASH,UAAUN,QAAQ,IAE/C,OAAO;CAET,IACE,aAAaM,aACbA,UAAUL,YAAYO,KAAAA,MACrB,OAAOF,UAAUL,YAAY,YAC5B,CAACE,eAAeM,SAASH,UAAUL,OAAO,IAE5C,OAAO;CAET,OAAO;AACT;AAEA,MAAMS,mBAAmBC,OAAOC,IAAI,+BAA+B;;;;;;;;;AAUnE,IAAaC,sBAAb,cAAyCC,MAAM;CAC7C,CAAUJ,oBAAoB;CAE9BK,YAAYhB,UAAU,6BAA6B;EACjD,MAAMA,OAAO;EACb,KAAKiB,OAAO;CACd;AACF;AAEA,MAAaC,yBACXC,UAEA,OAAOA,UAAU,YAAYA,UAAU,QAAQR,oBAAoBQ;AAErE,MAAaC,oBAAoBD,UAAmC;CAClE,IAAId,iBAAiBc,KAAK,GAAG,OAAOA;CACpC,IAAIA,iBAAiBJ,OACnB,OAAO;EAAEhB,MAAM;EAAWC,SAASmB,MAAMnB;CAAQ;CAEnD,IAAI,OAAOmB,UAAU,UACnB,OAAO;EAAEpB,MAAM;EAAWC,SAASmB;CAAM;CAE3C,IAAI;EACF,OAAO;GACLpB,MAAM;GACNC,SAAS,IAAI,OAAOmB,MAAK,IAAKE,OAAOF,KAAK;EAC5C;CACF,QAAQ;EACN,OAAO;GACLpB,MAAM;GACNC,SAAS,IAAI,OAAOmB,MAAK;EAC3B;CACF;AACF"}
@@ -44,6 +44,7 @@ type ImageMessagePart = {
44
44
  readonly type: "image";
45
45
  readonly image: string;
46
46
  readonly filename?: string;
47
+ readonly providerMetadata?: PartProviderMetadata;
47
48
  };
48
49
  type FileMessagePart = {
49
50
  readonly type: "file";
@@ -52,6 +53,7 @@ type FileMessagePart = {
52
53
  readonly mimeType: string;
53
54
  /** How `data` goes on the wire: a url or id reference; omitted = inferred (http(s) → url, else base64). "url" is honored by the LangChain-family, A2A, AG-UI, and Google ADK runtimes; "id" by the LangChain family only. */
54
55
  readonly sourceType?: "url" | "id";
56
+ readonly providerMetadata?: PartProviderMetadata;
55
57
  readonly parentId?: string;
56
58
  };
57
59
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"message.d.ts","names":[],"sources":["../../src/types/message.ts"],"mappings":";;;;KASY;YACA,uBAAuB;;KAGvB;WACD;WACA;WACA,SAAS;WACT,mBAAmB;WACnB;;KAGC;WACD;WACA;WACA,SAAS;WACT;WACA,mBAAmB;WACnB;;KAGC,yBAAyB;KAEzB;WAEG;WACA;WACA;WACA;WACA;WACA,mBAAmB;WACnB;;WAGA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,mBAAmB;WACnB;;KAGH;WACD;WACA;WACA;;KAGC;WACD;WACA;WACA;WACA;;WAEA;WACA;;;;;;;;;;;KAYC;WACD;WACA;aACE;aACA;;;KAID,gBAAgB;WACjB;WACA;WACA,MAAM;;;;;;;;;;;KAYL;;WAIG;;WAEA,QAAQ;;WAER,oBAAoB;;WAEpB;;;;;KAMH;;WAED,MAAM,4BAA4B;;;;;;;;;;KAWjC;WACD;;WAEA,MAAM;;WAEN;WACA;;KAGC;WACD;WACA;WACA;;WAEA;;cAGE;cAEA,cAAe;KAGhB;WACD,MAAM;;KAGL;KAMA;;WAED;;;;;;;WAOA,MAAM;;WAEN;WACA;;WAEA;;WAEA;IAAsB;IAAgB;;;KAGrC;WACG;WAA4B;;WAC5B;WAA2B;;WAE3B;WACA;WACA;;KAGH,oBACV,QAAQ,oBACR;;WAGS;;WAEA;;WAEA;;;;;;WAMA,MAAM;;WAEN,SAAS;;WAET;;WAEA;;WAEA;;WAEA,SAAS;;WAET,MAAM;;WAEN,mBAAmB;;WAEnB,wBAAwB;;WAExB;IAAc;IAAe;;;WAE7B;aACE;aACA;aACA;aACA;;aAEA,mBAAmB;;aAEnB;;aAEA;;;WAGF;;;;;WAKA,oBAAoB;;KAGnB,wBACR,kBACA,mBACA,kBACA,kBACA;KAEQ,6BACR,kBACA,uBACA,sBACA,oBACA,kBACA,mBACA,kBACA;KAEQ;WAEG;;WAGA;;WAGA;WACA;WAMA;;KAGH;WAEG;;WAGA;;WAGA;WACA;;KAQH;;WAGG;;WAEA;IAEX;KAEQ;WAEG;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;WAOA,QAAQ;;KAGX;WACD;WACA;WACA;WACA;WACA;WACA;WACA;;KAGC;WACD;WACA;aAEM;aACA;;;KAKZ;WACM;WACA,WAAW;;KAGV,sBAAsB;WACvB;WACA,mBAAmB;WACnB;aACE;aACA;aACA;aACA;aACA;aACA;aACA,QAAQ;;;KAIT,oBAAoB;WACrB;WACA,kBAAkB;WAClB,sBAAsB;WACtB;aACE;aACA;aACA;aACA;aACA;aACA;aACA;aACA,QAAQ;;;KAIT,yBAAyB;WAC1B;WACA,kBAAkB;WAClB,QAAQ;WACR;aACE,gBAAgB;aAChB,+BAA+B;aAC/B,wBAAwB;aACxB,gBAAgB;aAChB;eAA+B;;aAC/B,SAAS;;;;;aAKT;aACA,QAAQ;;;KAIhB;WACM,SAAS;WACT;aACE,iBAAiB;aACjB,gCAAgC;aAChC,yBAAyB;aACzB,iBAAiB;aACjB;eAA+B;;aAC/B,SAAS;aACT;aACA,QAAQ;;WAEV,cAAc;;KAGb,gBAAgB,qBACzB,sBAAsB,oBAAoB;KAEjC,cAAc;KAEd;WACD,SAAS;;KAGR,gBAAgB,KAAK;EAC/B;;EAGA;EACA,WAAW;EACX;;EAEA"}
1
+ {"version":3,"file":"message.d.ts","names":[],"sources":["../../src/types/message.ts"],"mappings":";;;;KASY;YACA,uBAAuB;;KAGvB;WACD;WACA;WACA,SAAS;WACT,mBAAmB;WACnB;;KAGC;WACD;WACA;WACA,SAAS;WACT;WACA,mBAAmB;WACnB;;KAGC,yBAAyB;KAEzB;WAEG;WACA;WACA;WACA;WACA;WACA,mBAAmB;WACnB;;WAGA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,mBAAmB;WACnB;;KAGH;WACD;WACA;WACA;WACA,mBAAmB;;KAGlB;WACD;WACA;WACA;WACA;;WAEA;WACA,mBAAmB;WACnB;;;;;;;;;;;KAYC;WACD;WACA;aACE;aACA;;;KAID,gBAAgB;WACjB;WACA;WACA,MAAM;;;;;;;;;;;KAYL;;WAIG;;WAEA,QAAQ;;WAER,oBAAoB;;WAEpB;;;;;KAMH;;WAED,MAAM,4BAA4B;;;;;;;;;;KAWjC;WACD;;WAEA,MAAM;;WAEN;WACA;;KAGC;WACD;WACA;WACA;;WAEA;;cAGE;cAEA,cAAe;KAGhB;WACD,MAAM;;KAGL;KAMA;;WAED;;;;;;;WAOA,MAAM;;WAEN;WACA;;WAEA;;WAEA;IAAsB;IAAgB;;;KAGrC;WACG;WAA4B;;WAC5B;WAA2B;;WAE3B;WACA;WACA;;KAGH,oBACV,QAAQ,oBACR;;WAGS;;WAEA;;WAEA;;;;;;WAMA,MAAM;;WAEN,SAAS;;WAET;;WAEA;;WAEA;;WAEA,SAAS;;WAET,MAAM;;WAEN,mBAAmB;;WAEnB,wBAAwB;;WAExB;IAAc;IAAe;;;WAE7B;aACE;aACA;aACA;aACA;;aAEA,mBAAmB;;aAEnB;;aAEA;;;WAGF;;;;;WAKA,oBAAoB;;KAGnB,wBACR,kBACA,mBACA,kBACA,kBACA;KAEQ,6BACR,kBACA,uBACA,sBACA,oBACA,kBACA,mBACA,kBACA;KAEQ;WAEG;;WAGA;;WAGA;WACA;WAMA;;KAGH;WAEG;;WAGA;;WAGA;WACA;;KAQH;;WAGG;;WAEA;IAEX;KAEQ;WAEG;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;WAOA,QAAQ;;KAGX;WACD;WACA;WACA;WACA;WACA;WACA;WACA;;KAGC;WACD;WACA;aAEM;aACA;;;KAKZ;WACM;WACA,WAAW;;KAGV,sBAAsB;WACvB;WACA,mBAAmB;WACnB;aACE;aACA;aACA;aACA;aACA;aACA;aACA,QAAQ;;;KAIT,oBAAoB;WACrB;WACA,kBAAkB;WAClB,sBAAsB;WACtB;aACE;aACA;aACA;aACA;aACA;aACA;aACA;aACA,QAAQ;;;KAIT,yBAAyB;WAC1B;WACA,kBAAkB;WAClB,QAAQ;WACR;aACE,gBAAgB;aAChB,+BAA+B;aAC/B,wBAAwB;aACxB,gBAAgB;aAChB;eAA+B;;aAC/B,SAAS;;;;;aAKT;aACA,QAAQ;;;KAIhB;WACM,SAAS;WACT;aACE,iBAAiB;aACjB,gCAAgC;aAChC,yBAAyB;aACzB,iBAAiB;aACjB;eAA+B;;aAC/B,SAAS;aACT;aACA,QAAQ;;WAEV,cAAc;;KAGb,gBAAgB,qBACzB,sBAAsB,oBAAoB;KAEjC,cAAc;KAEd;WACD,SAAS;;KAGR,gBAAgB,KAAK;EAC/B;;EAGA;EACA,WAAW;EACX;;EAEA"}
@@ -1 +1 @@
1
- {"version":3,"file":"message.js","names":["ReadonlyJSONObject","ReadonlyJSONValue","ToolCallTiming","ToolModelContentPart","CompleteAttachment","PartProviderMetadata","providerName","TextMessagePart","type","text","status","MessagePartStreamStatus","providerMetadata","parentId","ReasoningMessagePart","unstable_summary","SourceProviderMetadata","SourceMessagePart","sourceType","id","url","title","mediaType","filename","ImageMessagePart","image","FileMessagePart","data","mimeType","Unstable_AudioMessagePart","audio","format","DataMessagePart","name","T","GenerativeUINode","component","props","Record","children","key","GenerativeUISpec","root","GenerativeUIMessagePart","spec","McpAppMetadata","resourceUri","visibility","serverId","MCP_APP_URI_SCHEME","isMcpAppUri","uri","startsWith","ToolCallMessagePartMcpMetadata","app","ToolApprovalOptionKind","ToolApprovalOption","kind","label","description","grants","confirm","ToolApprovalResponse","approved","reason","optionId","ToolCallMessagePart","toolCallId","toolName","args","TArgs","result","TResult","isError","argsText","artifact","timing","mcp","modelContent","interrupt","payload","approval","isAutomatic","options","resolution","messages","ThreadMessage","ThreadUserMessagePart","ThreadAssistantMessagePart","MessagePartStatus","error","ToolCallMessagePartStatus","MessageStatus","MessageTiming","streamStartTime","firstTokenTime","totalStreamTime","tokenCount","tokensPerSecond","totalChunks","toolCallCount","ThreadStep","messageId","usage","inputTokens","outputTokens","MessageCommonProps","createdAt","Date","ThreadSystemMessage","role","content","metadata","unstable_state","unstable_annotations","unstable_data","steps","submittedFeedback","custom","ThreadUserMessage","attachments","isOptimistic","ThreadAssistantMessage","BaseThreadMessage","MessageRole","RunConfig","AppendMessage","Omit","sourceId","runConfig","startRun","steer"],"sources":["../../src/types/message.ts"],"sourcesContent":["import type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\nimport type { ToolCallTiming, ToolModelContentPart } from \"assistant-stream\";\nimport type { CompleteAttachment } from \"./attachment\";\n\nexport type { ToolCallTiming, ToolModelContentPart };\n\nexport type PartProviderMetadata = {\n readonly [providerName: string]: ReadonlyJSONObject;\n};\n\nexport type TextMessagePart = {\n readonly type: \"text\";\n readonly text: string;\n readonly status?: MessagePartStreamStatus;\n readonly providerMetadata?: PartProviderMetadata;\n readonly parentId?: string;\n};\n\nexport type ReasoningMessagePart = {\n readonly type: \"reasoning\";\n readonly text: string;\n readonly status?: MessagePartStreamStatus;\n readonly unstable_summary?: string;\n readonly providerMetadata?: PartProviderMetadata;\n readonly parentId?: string;\n};\n\nexport type SourceProviderMetadata = PartProviderMetadata;\n\nexport type SourceMessagePart =\n | {\n readonly type: \"source\";\n readonly sourceType: \"url\";\n readonly id: string;\n readonly url: string;\n readonly title?: string;\n readonly providerMetadata?: SourceProviderMetadata;\n readonly parentId?: string;\n }\n | {\n readonly type: \"source\";\n readonly sourceType: \"document\";\n readonly id: string;\n readonly url?: undefined;\n readonly title: string;\n readonly mediaType: string;\n readonly filename?: string;\n readonly providerMetadata?: SourceProviderMetadata;\n readonly parentId?: string;\n };\n\nexport type ImageMessagePart = {\n readonly type: \"image\";\n readonly image: string;\n readonly filename?: string;\n};\n\nexport type FileMessagePart = {\n readonly type: \"file\";\n readonly filename?: string;\n readonly data: string;\n readonly mimeType: string;\n /** How `data` goes on the wire: a url or id reference; omitted = inferred (http(s) → url, else base64). \"url\" is honored by the LangChain-family, A2A, AG-UI, and Google ADK runtimes; \"id\" by the LangChain family only. */\n readonly sourceType?: \"url\" | \"id\";\n readonly parentId?: string;\n};\n\n/**\n * @deprecated Use {@link FileMessagePart} with an `audio/*` mime type. `file`\n * is the carrier for every non-image binary modality: it is a member of both\n * the user and assistant unions, carries a filename, and can declare how its\n * payload goes on the wire, none of which this shape can express. The payload\n * form a `file` part needs is still adapter specific; see the Part Types\n * section of the message primitive docs. Honored everywhere it is accepted; it\n * will not gain fields.\n */\nexport type Unstable_AudioMessagePart = {\n readonly type: \"audio\";\n readonly audio: {\n readonly data: string;\n readonly format: \"mp3\" | \"wav\";\n };\n};\n\nexport type DataMessagePart<T = any> = {\n readonly type: \"data\";\n readonly name: string;\n readonly data: T;\n};\n\n/**\n * A JSON spec describing a tree of UI components to render.\n *\n * The agent emits a {@link GenerativeUIMessagePart} containing this spec, and\n * the consumer-provided component allowlist is used to resolve `component`\n * names. Any component referenced that is not present in the allowlist is\n * rejected with a typed error — the allowlist is the security boundary in the\n * default same-realm rendering path.\n */\nexport type GenerativeUINode =\n | string\n | {\n /** Allowlisted component name (resolved against the consumer registry). */\n readonly component: string;\n /** Props passed to the resolved component (must be JSON-serializable). */\n readonly props?: Record<string, unknown>;\n /** Optional children — strings render as text, objects recurse. */\n readonly children?: readonly GenerativeUINode[];\n /** Optional stable key for React reconciliation. */\n readonly key?: string;\n };\n\n/**\n * The root spec for a generative UI tree.\n */\nexport type GenerativeUISpec = {\n /** Root node(s) to render. */\n readonly root: GenerativeUINode | readonly GenerativeUINode[];\n};\n\n/**\n * A message part that carries a JSON spec describing UI to render.\n *\n * Render with `<MessagePrimitive.GenerativeUI components={...} />`. The\n * primitive resolves component names against the consumer-provided allowlist\n * — any unknown name throws a typed error rather than rendering. Stream-\n * friendly: a partially-streamed spec renders progressively.\n */\nexport type GenerativeUIMessagePart = {\n readonly type: \"generative-ui\";\n /** The JSON spec describing the UI tree. */\n readonly spec: GenerativeUISpec;\n /** Optional id (useful for replays / stable keys). */\n readonly id?: string;\n readonly parentId?: string;\n};\n\nexport type McpAppMetadata = {\n readonly resourceUri: string;\n readonly mimeType?: string;\n readonly visibility?: readonly (\"model\" | \"app\")[];\n /** Routable server identity emitted by the agent stack when multiple MCP servers back one agent; for @ag-ui/mcp-apps-middleware this is the configured serverId, falling back to its serverHash. */\n readonly serverId?: string;\n};\n\nexport const MCP_APP_URI_SCHEME = \"ui://\";\n\nexport const isMcpAppUri = (uri: string | undefined): boolean =>\n !!uri?.startsWith(MCP_APP_URI_SCHEME);\n\nexport type ToolCallMessagePartMcpMetadata = {\n readonly app?: McpAppMetadata;\n};\n\nexport type ToolApprovalOptionKind =\n | \"allow-once\"\n | \"allow-always\"\n | \"reject-once\"\n | \"reject-always\";\n\nexport type ToolApprovalOption = {\n /** Opaque, host-defined identifier. Scope semantics (session vs project vs global) belong to the option supplier. */\n readonly id: string;\n /**\n * Decision class. Drives approved-resolution and default rendering.\n * Open union: `_`-prefixed custom kinds are never auto-resolved and the\n * default kit skips them; they must be answered with an explicit\n * `approved` value (optionally alongside the `optionId`).\n */\n readonly kind: ToolApprovalOptionKind | (string & {});\n /** Human label. Renderers supply defaults per kind when omitted. */\n readonly label?: string;\n readonly description?: string;\n /** Patterns or rules this option would persist, shown before the user commits. Supplied by the host; never derived by the library. */\n readonly grants?: readonly string[];\n /** Opt-in confirmation step before this option resolves. */\n readonly confirm?: boolean | { title?: string; description?: string };\n};\n\nexport type ToolApprovalResponse =\n | { readonly approved: boolean; readonly reason?: string }\n | { readonly optionId: string; readonly reason?: string }\n | {\n readonly approved: boolean;\n readonly optionId: string;\n readonly reason?: string;\n };\n\nexport type ToolCallMessagePart<\n TArgs = ReadonlyJSONObject,\n TResult = unknown,\n> = {\n /** Identifies this part as a tool call. */\n readonly type: \"tool-call\";\n /** Stable identifier for this invocation of the tool. */\n readonly toolCallId: string;\n /** Name of the tool requested by the model. */\n readonly toolName: string;\n /**\n * Arguments supplied by the model. During streaming this is a partial parse:\n * fields may be missing or incomplete. From a tool-call renderer, use\n * `useToolArgsStatus` to detect which fields are still arriving.\n */\n readonly args: TArgs;\n /** Result returned by the tool, if it has completed. */\n readonly result?: TResult | undefined;\n /** Whether the result represents a tool execution error. */\n readonly isError?: boolean | undefined;\n /** Raw JSON argument text streamed by the model. */\n readonly argsText: string;\n /** UI-only artifact associated with the tool result. */\n readonly artifact?: unknown;\n /** Wall-clock timing for this call, when the runtime or host tracks it. */\n readonly timing?: ToolCallTiming;\n /** MCP app metadata associated with this tool call, when present. */\n readonly mcp?: ToolCallMessagePartMcpMetadata;\n /** Provider metadata associated with this tool call, when present. */\n readonly providerMetadata?: PartProviderMetadata;\n /** Content returned to the model for this tool result. */\n readonly modelContent?: readonly ToolModelContentPart[] | undefined;\n /** Human-input request that must be resolved before the run can continue. */\n readonly interrupt?: { type: \"human\"; payload: unknown };\n /** Server-side approval gate. `respondToApproval` may only be called while `approved` is undefined and no `resolution` is recorded. */\n readonly approval?: {\n readonly id: string;\n readonly approved?: boolean;\n readonly reason?: string;\n readonly isAutomatic?: boolean;\n /** Available decisions for this call. Absent: a plain allow / deny pair. */\n readonly options?: readonly ToolApprovalOption[];\n /** The option chosen at resolution, when options were present. */\n readonly optionId?: string;\n /** Terminal non-decision state: the request was cancelled or expired without a user decision. Set by the host. */\n readonly resolution?: \"cancelled\" | \"expired\";\n };\n /** Parent message-part ID when this part belongs to a nested structure. */\n readonly parentId?: string;\n /**\n * Nested thread messages produced by this tool call, for example a sub-agent\n * conversation.\n */\n readonly messages?: readonly ThreadMessage[];\n};\n\nexport type ThreadUserMessagePart =\n | TextMessagePart\n | ImageMessagePart\n | FileMessagePart\n | DataMessagePart\n | Unstable_AudioMessagePart;\n\nexport type ThreadAssistantMessagePart =\n | TextMessagePart\n | ReasoningMessagePart\n | ToolCallMessagePart\n | SourceMessagePart\n | FileMessagePart\n | ImageMessagePart\n | DataMessagePart\n | GenerativeUIMessagePart;\n\nexport type MessagePartStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"complete\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n readonly error?: unknown;\n };\n\nexport type MessagePartStreamStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"complete\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n };\n\nexport type ToolCallMessagePartStatus =\n | {\n /** The tool call is waiting for UI or human input before continuing. */\n readonly type: \"requires-action\";\n /** Reason the tool call requires action. */\n readonly reason: \"interrupt\";\n }\n | MessagePartStatus;\n\nexport type MessageStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"requires-action\";\n readonly reason: \"tool-calls\" | \"interrupt\";\n }\n | {\n readonly type: \"complete\";\n readonly reason: \"stop\" | \"unknown\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"tool-calls\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n readonly error?: ReadonlyJSONValue;\n };\n\nexport type MessageTiming = {\n readonly streamStartTime: number;\n readonly firstTokenTime?: number;\n readonly totalStreamTime?: number;\n readonly tokenCount?: number;\n readonly tokensPerSecond?: number;\n readonly totalChunks: number;\n readonly toolCallCount: number;\n};\n\nexport type ThreadStep = {\n readonly messageId?: string;\n readonly usage?:\n | {\n readonly inputTokens: number;\n readonly outputTokens: number;\n }\n | undefined;\n};\n\ntype MessageCommonProps = {\n readonly id: string;\n readonly createdAt: Date;\n};\n\nexport type ThreadSystemMessage = MessageCommonProps & {\n readonly role: \"system\";\n readonly content: readonly [TextMessagePart];\n readonly metadata: {\n readonly unstable_state?: undefined;\n readonly unstable_annotations?: undefined;\n readonly unstable_data?: undefined;\n readonly steps?: undefined;\n readonly submittedFeedback?: undefined;\n readonly timing?: undefined;\n readonly custom: Record<string, unknown>;\n };\n};\n\nexport type ThreadUserMessage = MessageCommonProps & {\n readonly role: \"user\";\n readonly content: readonly ThreadUserMessagePart[];\n readonly attachments: readonly CompleteAttachment[];\n readonly metadata: {\n readonly unstable_state?: undefined;\n readonly unstable_annotations?: undefined;\n readonly unstable_data?: undefined;\n readonly steps?: undefined;\n readonly submittedFeedback?: undefined;\n readonly timing?: undefined;\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n};\n\nexport type ThreadAssistantMessage = MessageCommonProps & {\n readonly role: \"assistant\";\n readonly content: readonly ThreadAssistantMessagePart[];\n readonly status: MessageStatus;\n readonly metadata: {\n readonly unstable_state: ReadonlyJSONValue;\n readonly unstable_annotations: readonly ReadonlyJSONValue[];\n readonly unstable_data: readonly ReadonlyJSONValue[];\n readonly steps: readonly ThreadStep[];\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly timing?: MessageTiming;\n /**\n * Marks a client-side optimistic placeholder. Such messages are evicted\n * once off the head branch and are never persisted.\n */\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n};\n\ntype BaseThreadMessage = {\n readonly status?: ThreadAssistantMessage[\"status\"];\n readonly metadata: {\n readonly unstable_state?: ReadonlyJSONValue;\n readonly unstable_annotations?: readonly ReadonlyJSONValue[];\n readonly unstable_data?: readonly ReadonlyJSONValue[];\n readonly steps?: readonly ThreadStep[];\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly timing?: MessageTiming;\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n readonly attachments?: ThreadUserMessage[\"attachments\"];\n};\n\nexport type ThreadMessage = BaseThreadMessage &\n (ThreadSystemMessage | ThreadUserMessage | ThreadAssistantMessage);\n\nexport type MessageRole = ThreadMessage[\"role\"];\n\nexport type RunConfig = {\n readonly custom?: Record<string, unknown>;\n};\n\nexport type AppendMessage = Omit<ThreadMessage, \"id\"> & {\n parentId: string | null;\n\n /** The ID of the message that was edited or undefined. */\n sourceId: string | null;\n runConfig: RunConfig | undefined;\n startRun?: boolean | undefined;\n /** Process this message next; only meaningful for queue-capable runtimes. */\n steer?: boolean | undefined;\n};\n"],"mappings":";AAoJA,MAAaiD,qBAAqB;AAElC,MAAaC,eAAeC,QAC1B,CAAC,CAACA,KAAKC,WAAWH,kBAAkB"}
1
+ {"version":3,"file":"message.js","names":["ReadonlyJSONObject","ReadonlyJSONValue","ToolCallTiming","ToolModelContentPart","CompleteAttachment","PartProviderMetadata","providerName","TextMessagePart","type","text","status","MessagePartStreamStatus","providerMetadata","parentId","ReasoningMessagePart","unstable_summary","SourceProviderMetadata","SourceMessagePart","sourceType","id","url","title","mediaType","filename","ImageMessagePart","image","FileMessagePart","data","mimeType","Unstable_AudioMessagePart","audio","format","DataMessagePart","name","T","GenerativeUINode","component","props","Record","children","key","GenerativeUISpec","root","GenerativeUIMessagePart","spec","McpAppMetadata","resourceUri","visibility","serverId","MCP_APP_URI_SCHEME","isMcpAppUri","uri","startsWith","ToolCallMessagePartMcpMetadata","app","ToolApprovalOptionKind","ToolApprovalOption","kind","label","description","grants","confirm","ToolApprovalResponse","approved","reason","optionId","ToolCallMessagePart","toolCallId","toolName","args","TArgs","result","TResult","isError","argsText","artifact","timing","mcp","modelContent","interrupt","payload","approval","isAutomatic","options","resolution","messages","ThreadMessage","ThreadUserMessagePart","ThreadAssistantMessagePart","MessagePartStatus","error","ToolCallMessagePartStatus","MessageStatus","MessageTiming","streamStartTime","firstTokenTime","totalStreamTime","tokenCount","tokensPerSecond","totalChunks","toolCallCount","ThreadStep","messageId","usage","inputTokens","outputTokens","MessageCommonProps","createdAt","Date","ThreadSystemMessage","role","content","metadata","unstable_state","unstable_annotations","unstable_data","steps","submittedFeedback","custom","ThreadUserMessage","attachments","isOptimistic","ThreadAssistantMessage","BaseThreadMessage","MessageRole","RunConfig","AppendMessage","Omit","sourceId","runConfig","startRun","steer"],"sources":["../../src/types/message.ts"],"sourcesContent":["import type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\nimport type { ToolCallTiming, ToolModelContentPart } from \"assistant-stream\";\nimport type { CompleteAttachment } from \"./attachment\";\n\nexport type { ToolCallTiming, ToolModelContentPart };\n\nexport type PartProviderMetadata = {\n readonly [providerName: string]: ReadonlyJSONObject;\n};\n\nexport type TextMessagePart = {\n readonly type: \"text\";\n readonly text: string;\n readonly status?: MessagePartStreamStatus;\n readonly providerMetadata?: PartProviderMetadata;\n readonly parentId?: string;\n};\n\nexport type ReasoningMessagePart = {\n readonly type: \"reasoning\";\n readonly text: string;\n readonly status?: MessagePartStreamStatus;\n readonly unstable_summary?: string;\n readonly providerMetadata?: PartProviderMetadata;\n readonly parentId?: string;\n};\n\nexport type SourceProviderMetadata = PartProviderMetadata;\n\nexport type SourceMessagePart =\n | {\n readonly type: \"source\";\n readonly sourceType: \"url\";\n readonly id: string;\n readonly url: string;\n readonly title?: string;\n readonly providerMetadata?: SourceProviderMetadata;\n readonly parentId?: string;\n }\n | {\n readonly type: \"source\";\n readonly sourceType: \"document\";\n readonly id: string;\n readonly url?: undefined;\n readonly title: string;\n readonly mediaType: string;\n readonly filename?: string;\n readonly providerMetadata?: SourceProviderMetadata;\n readonly parentId?: string;\n };\n\nexport type ImageMessagePart = {\n readonly type: \"image\";\n readonly image: string;\n readonly filename?: string;\n readonly providerMetadata?: PartProviderMetadata;\n};\n\nexport type FileMessagePart = {\n readonly type: \"file\";\n readonly filename?: string;\n readonly data: string;\n readonly mimeType: string;\n /** How `data` goes on the wire: a url or id reference; omitted = inferred (http(s) → url, else base64). \"url\" is honored by the LangChain-family, A2A, AG-UI, and Google ADK runtimes; \"id\" by the LangChain family only. */\n readonly sourceType?: \"url\" | \"id\";\n readonly providerMetadata?: PartProviderMetadata;\n readonly parentId?: string;\n};\n\n/**\n * @deprecated Use {@link FileMessagePart} with an `audio/*` mime type. `file`\n * is the carrier for every non-image binary modality: it is a member of both\n * the user and assistant unions, carries a filename, and can declare how its\n * payload goes on the wire, none of which this shape can express. The payload\n * form a `file` part needs is still adapter specific; see the Part Types\n * section of the message primitive docs. Honored everywhere it is accepted; it\n * will not gain fields.\n */\nexport type Unstable_AudioMessagePart = {\n readonly type: \"audio\";\n readonly audio: {\n readonly data: string;\n readonly format: \"mp3\" | \"wav\";\n };\n};\n\nexport type DataMessagePart<T = any> = {\n readonly type: \"data\";\n readonly name: string;\n readonly data: T;\n};\n\n/**\n * A JSON spec describing a tree of UI components to render.\n *\n * The agent emits a {@link GenerativeUIMessagePart} containing this spec, and\n * the consumer-provided component allowlist is used to resolve `component`\n * names. Any component referenced that is not present in the allowlist is\n * rejected with a typed error — the allowlist is the security boundary in the\n * default same-realm rendering path.\n */\nexport type GenerativeUINode =\n | string\n | {\n /** Allowlisted component name (resolved against the consumer registry). */\n readonly component: string;\n /** Props passed to the resolved component (must be JSON-serializable). */\n readonly props?: Record<string, unknown>;\n /** Optional children — strings render as text, objects recurse. */\n readonly children?: readonly GenerativeUINode[];\n /** Optional stable key for React reconciliation. */\n readonly key?: string;\n };\n\n/**\n * The root spec for a generative UI tree.\n */\nexport type GenerativeUISpec = {\n /** Root node(s) to render. */\n readonly root: GenerativeUINode | readonly GenerativeUINode[];\n};\n\n/**\n * A message part that carries a JSON spec describing UI to render.\n *\n * Render with `<MessagePrimitive.GenerativeUI components={...} />`. The\n * primitive resolves component names against the consumer-provided allowlist\n * — any unknown name throws a typed error rather than rendering. Stream-\n * friendly: a partially-streamed spec renders progressively.\n */\nexport type GenerativeUIMessagePart = {\n readonly type: \"generative-ui\";\n /** The JSON spec describing the UI tree. */\n readonly spec: GenerativeUISpec;\n /** Optional id (useful for replays / stable keys). */\n readonly id?: string;\n readonly parentId?: string;\n};\n\nexport type McpAppMetadata = {\n readonly resourceUri: string;\n readonly mimeType?: string;\n readonly visibility?: readonly (\"model\" | \"app\")[];\n /** Routable server identity emitted by the agent stack when multiple MCP servers back one agent; for @ag-ui/mcp-apps-middleware this is the configured serverId, falling back to its serverHash. */\n readonly serverId?: string;\n};\n\nexport const MCP_APP_URI_SCHEME = \"ui://\";\n\nexport const isMcpAppUri = (uri: string | undefined): boolean =>\n !!uri?.startsWith(MCP_APP_URI_SCHEME);\n\nexport type ToolCallMessagePartMcpMetadata = {\n readonly app?: McpAppMetadata;\n};\n\nexport type ToolApprovalOptionKind =\n | \"allow-once\"\n | \"allow-always\"\n | \"reject-once\"\n | \"reject-always\";\n\nexport type ToolApprovalOption = {\n /** Opaque, host-defined identifier. Scope semantics (session vs project vs global) belong to the option supplier. */\n readonly id: string;\n /**\n * Decision class. Drives approved-resolution and default rendering.\n * Open union: `_`-prefixed custom kinds are never auto-resolved and the\n * default kit skips them; they must be answered with an explicit\n * `approved` value (optionally alongside the `optionId`).\n */\n readonly kind: ToolApprovalOptionKind | (string & {});\n /** Human label. Renderers supply defaults per kind when omitted. */\n readonly label?: string;\n readonly description?: string;\n /** Patterns or rules this option would persist, shown before the user commits. Supplied by the host; never derived by the library. */\n readonly grants?: readonly string[];\n /** Opt-in confirmation step before this option resolves. */\n readonly confirm?: boolean | { title?: string; description?: string };\n};\n\nexport type ToolApprovalResponse =\n | { readonly approved: boolean; readonly reason?: string }\n | { readonly optionId: string; readonly reason?: string }\n | {\n readonly approved: boolean;\n readonly optionId: string;\n readonly reason?: string;\n };\n\nexport type ToolCallMessagePart<\n TArgs = ReadonlyJSONObject,\n TResult = unknown,\n> = {\n /** Identifies this part as a tool call. */\n readonly type: \"tool-call\";\n /** Stable identifier for this invocation of the tool. */\n readonly toolCallId: string;\n /** Name of the tool requested by the model. */\n readonly toolName: string;\n /**\n * Arguments supplied by the model. During streaming this is a partial parse:\n * fields may be missing or incomplete. From a tool-call renderer, use\n * `useToolArgsStatus` to detect which fields are still arriving.\n */\n readonly args: TArgs;\n /** Result returned by the tool, if it has completed. */\n readonly result?: TResult | undefined;\n /** Whether the result represents a tool execution error. */\n readonly isError?: boolean | undefined;\n /** Raw JSON argument text streamed by the model. */\n readonly argsText: string;\n /** UI-only artifact associated with the tool result. */\n readonly artifact?: unknown;\n /** Wall-clock timing for this call, when the runtime or host tracks it. */\n readonly timing?: ToolCallTiming;\n /** MCP app metadata associated with this tool call, when present. */\n readonly mcp?: ToolCallMessagePartMcpMetadata;\n /** Provider metadata associated with this tool call, when present. */\n readonly providerMetadata?: PartProviderMetadata;\n /** Content returned to the model for this tool result. */\n readonly modelContent?: readonly ToolModelContentPart[] | undefined;\n /** Human-input request that must be resolved before the run can continue. */\n readonly interrupt?: { type: \"human\"; payload: unknown };\n /** Server-side approval gate. `respondToApproval` may only be called while `approved` is undefined and no `resolution` is recorded. */\n readonly approval?: {\n readonly id: string;\n readonly approved?: boolean;\n readonly reason?: string;\n readonly isAutomatic?: boolean;\n /** Available decisions for this call. Absent: a plain allow / deny pair. */\n readonly options?: readonly ToolApprovalOption[];\n /** The option chosen at resolution, when options were present. */\n readonly optionId?: string;\n /** Terminal non-decision state: the request was cancelled or expired without a user decision. Set by the host. */\n readonly resolution?: \"cancelled\" | \"expired\";\n };\n /** Parent message-part ID when this part belongs to a nested structure. */\n readonly parentId?: string;\n /**\n * Nested thread messages produced by this tool call, for example a sub-agent\n * conversation.\n */\n readonly messages?: readonly ThreadMessage[];\n};\n\nexport type ThreadUserMessagePart =\n | TextMessagePart\n | ImageMessagePart\n | FileMessagePart\n | DataMessagePart\n | Unstable_AudioMessagePart;\n\nexport type ThreadAssistantMessagePart =\n | TextMessagePart\n | ReasoningMessagePart\n | ToolCallMessagePart\n | SourceMessagePart\n | FileMessagePart\n | ImageMessagePart\n | DataMessagePart\n | GenerativeUIMessagePart;\n\nexport type MessagePartStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"complete\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n readonly error?: unknown;\n };\n\nexport type MessagePartStreamStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"complete\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n };\n\nexport type ToolCallMessagePartStatus =\n | {\n /** The tool call is waiting for UI or human input before continuing. */\n readonly type: \"requires-action\";\n /** Reason the tool call requires action. */\n readonly reason: \"interrupt\";\n }\n | MessagePartStatus;\n\nexport type MessageStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"requires-action\";\n readonly reason: \"tool-calls\" | \"interrupt\";\n }\n | {\n readonly type: \"complete\";\n readonly reason: \"stop\" | \"unknown\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"tool-calls\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n readonly error?: ReadonlyJSONValue;\n };\n\nexport type MessageTiming = {\n readonly streamStartTime: number;\n readonly firstTokenTime?: number;\n readonly totalStreamTime?: number;\n readonly tokenCount?: number;\n readonly tokensPerSecond?: number;\n readonly totalChunks: number;\n readonly toolCallCount: number;\n};\n\nexport type ThreadStep = {\n readonly messageId?: string;\n readonly usage?:\n | {\n readonly inputTokens: number;\n readonly outputTokens: number;\n }\n | undefined;\n};\n\ntype MessageCommonProps = {\n readonly id: string;\n readonly createdAt: Date;\n};\n\nexport type ThreadSystemMessage = MessageCommonProps & {\n readonly role: \"system\";\n readonly content: readonly [TextMessagePart];\n readonly metadata: {\n readonly unstable_state?: undefined;\n readonly unstable_annotations?: undefined;\n readonly unstable_data?: undefined;\n readonly steps?: undefined;\n readonly submittedFeedback?: undefined;\n readonly timing?: undefined;\n readonly custom: Record<string, unknown>;\n };\n};\n\nexport type ThreadUserMessage = MessageCommonProps & {\n readonly role: \"user\";\n readonly content: readonly ThreadUserMessagePart[];\n readonly attachments: readonly CompleteAttachment[];\n readonly metadata: {\n readonly unstable_state?: undefined;\n readonly unstable_annotations?: undefined;\n readonly unstable_data?: undefined;\n readonly steps?: undefined;\n readonly submittedFeedback?: undefined;\n readonly timing?: undefined;\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n};\n\nexport type ThreadAssistantMessage = MessageCommonProps & {\n readonly role: \"assistant\";\n readonly content: readonly ThreadAssistantMessagePart[];\n readonly status: MessageStatus;\n readonly metadata: {\n readonly unstable_state: ReadonlyJSONValue;\n readonly unstable_annotations: readonly ReadonlyJSONValue[];\n readonly unstable_data: readonly ReadonlyJSONValue[];\n readonly steps: readonly ThreadStep[];\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly timing?: MessageTiming;\n /**\n * Marks a client-side optimistic placeholder. Such messages are evicted\n * once off the head branch and are never persisted.\n */\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n};\n\ntype BaseThreadMessage = {\n readonly status?: ThreadAssistantMessage[\"status\"];\n readonly metadata: {\n readonly unstable_state?: ReadonlyJSONValue;\n readonly unstable_annotations?: readonly ReadonlyJSONValue[];\n readonly unstable_data?: readonly ReadonlyJSONValue[];\n readonly steps?: readonly ThreadStep[];\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly timing?: MessageTiming;\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n readonly attachments?: ThreadUserMessage[\"attachments\"];\n};\n\nexport type ThreadMessage = BaseThreadMessage &\n (ThreadSystemMessage | ThreadUserMessage | ThreadAssistantMessage);\n\nexport type MessageRole = ThreadMessage[\"role\"];\n\nexport type RunConfig = {\n readonly custom?: Record<string, unknown>;\n};\n\nexport type AppendMessage = Omit<ThreadMessage, \"id\"> & {\n parentId: string | null;\n\n /** The ID of the message that was edited or undefined. */\n sourceId: string | null;\n runConfig: RunConfig | undefined;\n startRun?: boolean | undefined;\n /** Process this message next; only meaningful for queue-capable runtimes. */\n steer?: boolean | undefined;\n};\n"],"mappings":";AAsJA,MAAaiD,qBAAqB;AAElC,MAAaC,eAAeC,QAC1B,CAAC,CAACA,KAAKC,WAAWH,kBAAkB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/core",
3
- "version": "0.3.12",
3
+ "version": "0.3.13",
4
4
  "description": "Framework-agnostic core runtime for assistant-ui",
5
5
  "keywords": [
6
6
  "assistant",
@@ -95,11 +95,11 @@
95
95
  "react-dom": "^19.2.8",
96
96
  "vitest": "^4.1.10",
97
97
  "zustand": "^5.0.14",
98
- "@assistant-ui/store": "0.3.8",
99
- "@assistant-ui/tap": "0.9.11",
98
+ "@assistant-ui/tap": "0.9.12",
100
99
  "@assistant-ui/vite": "0.0.12",
101
- "@assistant-ui/x-buildutils": "0.0.22",
102
- "assistant-cloud": "0.1.39"
100
+ "assistant-cloud": "0.1.40",
101
+ "@assistant-ui/store": "0.3.9",
102
+ "@assistant-ui/x-buildutils": "0.0.22"
103
103
  },
104
104
  "publishConfig": {
105
105
  "access": "public",
package/src/index.ts CHANGED
@@ -208,6 +208,7 @@ export type {
208
208
  AssistantError,
209
209
  } from "./types/error";
210
210
  export { toAssistantError, isAssistantError } from "./types/error";
211
+ export { MessageNotSentError, isMessageNotSentError } from "./types/error";
211
212
 
212
213
  export type {
213
214
  RuntimeCapabilities,
@@ -17,6 +17,11 @@ const ID_PROPERTY = {
17
17
  "The id of the instance to update, as shown in its state snapshot in the conversation.",
18
18
  };
19
19
 
20
+ const ITEM_ID_PROPERTY = {
21
+ type: "string" as const,
22
+ description: "The id of an item currently in this list.",
23
+ };
24
+
20
25
  const hasIdProperty = (schema: Record<string, unknown>) => {
21
26
  const properties = schema.properties;
22
27
  return isRecord(properties) && properties.id !== undefined;
@@ -52,7 +57,7 @@ const toArrayUpdateSchema = (schema: unknown, field: string) => {
52
57
  },
53
58
  remove: {
54
59
  type: "array",
55
- items: idKeyed ? ID_PROPERTY : itemSchema,
60
+ items: idKeyed ? ITEM_ID_PROPERTY : itemSchema,
56
61
  },
57
62
  clear: { type: "boolean" },
58
63
  };
@@ -0,0 +1,114 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { StrictMode } from "react";
4
+ import { cleanup, render, waitFor } from "@testing-library/react";
5
+ import { afterEach, describe, expect, it } from "vitest";
6
+ import {
7
+ AuiConfig,
8
+ useAui,
9
+ useAuiState,
10
+ type AssistantClient,
11
+ } from "@assistant-ui/store";
12
+ import type { ThreadSuggestion } from "../../runtime/interfaces/thread-runtime-core";
13
+ import { Suggestions } from "../../store/clients/suggestions";
14
+ import { AssistantRuntimeProvider } from "../AssistantRuntimeProvider";
15
+ import { useExternalStoreRuntime } from "./useExternalStoreRuntime";
16
+
17
+ let aui!: AssistantClient;
18
+ let scopeSuggestions!: readonly { prompt: string }[];
19
+
20
+ const Consumer = () => {
21
+ aui = useAui();
22
+ scopeSuggestions = useAuiState((s) => s.suggestions.suggestions);
23
+ return null;
24
+ };
25
+
26
+ const App = ({
27
+ suggestions,
28
+ config,
29
+ strict,
30
+ }: {
31
+ suggestions?: ThreadSuggestion[];
32
+ config?: AuiConfig;
33
+ strict?: boolean;
34
+ }) => {
35
+ const runtime = useExternalStoreRuntime({
36
+ messages: [],
37
+ onNew: async () => {},
38
+ ...(suggestions && { suggestions }),
39
+ });
40
+ const tree = (
41
+ <AssistantRuntimeProvider runtime={runtime} config={config}>
42
+ <Consumer />
43
+ </AssistantRuntimeProvider>
44
+ );
45
+ return strict ? <StrictMode>{tree}</StrictMode> : tree;
46
+ };
47
+
48
+ afterEach(() => {
49
+ cleanup();
50
+ });
51
+
52
+ describe("useExternalStoreRuntime suggestions scope", () => {
53
+ it("exposes runtime suggestions on the suggestions scope", () => {
54
+ render(
55
+ <App suggestions={[{ prompt: "Tell me a joke" }, { prompt: "Help" }]} />,
56
+ );
57
+
58
+ expect(scopeSuggestions).toEqual([
59
+ { title: "Tell me a joke", label: "", prompt: "Tell me a joke" },
60
+ { title: "Help", label: "", prompt: "Help" },
61
+ ]);
62
+ expect(aui.suggestions.suggestion({ index: 1 }).getState()).toEqual({
63
+ title: "Help",
64
+ label: "",
65
+ prompt: "Help",
66
+ });
67
+ expect(aui.thread.getState().suggestions).toEqual([
68
+ { prompt: "Tell me a joke" },
69
+ { prompt: "Help" },
70
+ ]);
71
+ });
72
+
73
+ it("exposes runtime suggestions under StrictMode", () => {
74
+ render(<App strict suggestions={[{ prompt: "Tell me a joke" }]} />);
75
+
76
+ expect(scopeSuggestions).toEqual([
77
+ { title: "Tell me a joke", label: "", prompt: "Tell me a joke" },
78
+ ]);
79
+ });
80
+
81
+ it("reports an empty scope without runtime suggestions", () => {
82
+ render(<App />);
83
+
84
+ expect(scopeSuggestions).toEqual([]);
85
+ });
86
+
87
+ it("follows runtime suggestion updates", async () => {
88
+ const view = render(<App suggestions={[{ prompt: "First" }]} />);
89
+ expect(scopeSuggestions).toEqual([
90
+ { title: "First", label: "", prompt: "First" },
91
+ ]);
92
+
93
+ view.rerender(<App suggestions={[{ prompt: "Second" }]} />);
94
+ await waitFor(() => {
95
+ expect(scopeSuggestions).toEqual([
96
+ { title: "Second", label: "", prompt: "Second" },
97
+ ]);
98
+ });
99
+ });
100
+
101
+ it("prefers config-provided suggestions over runtime suggestions", () => {
102
+ render(
103
+ <App
104
+ suggestions={[{ prompt: "Runtime" }]}
105
+ config={AuiConfig({ suggestions: Suggestions(["Static"]) })}
106
+ />,
107
+ );
108
+
109
+ expect(scopeSuggestions).toEqual([
110
+ { title: "Static", label: "", prompt: "Static" },
111
+ ]);
112
+ expect(aui.thread.getState().suggestions).toEqual([{ prompt: "Runtime" }]);
113
+ });
114
+ });
@@ -34,6 +34,7 @@ import type {
34
34
  import type { ThreadListItemState } from "./bindings";
35
35
  import type { AppendMessage, ThreadMessage } from "../../types/message";
36
36
  import type { Unsubscribe } from "../../types/unsubscribe";
37
+ import { isMessageNotSentError } from "../../types/error";
37
38
  import type { RunConfig } from "../../types/message";
38
39
  import { EventSubscriptionSubject } from "../../subscribable/subscribable";
39
40
  import { symbolInnerMessage } from "../utils/external-store-message";
@@ -416,11 +417,17 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
416
417
  }
417
418
 
418
419
  public append(message: CreateAppendMessage) {
419
- this._threadBinding
420
+ const task = this._threadBinding
420
421
  .getState()
421
422
  .append(
422
423
  toAppendMessage(this._threadBinding.getState().messages, message),
423
424
  );
425
+ // An undispatched send is reported to the composer, so it is a control
426
+ // signal rather than a failure to surface; every other rejection keeps
427
+ // reaching the host untouched.
428
+ void Promise.resolve(task).catch((error) => {
429
+ if (!isMessageNotSentError(error)) throw error;
430
+ });
424
431
  }
425
432
 
426
433
  public deleteMessage(messageId: string) {