@assistant-ui/core 0.2.23 → 0.3.0

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 (193) hide show
  1. package/dist/react/adapters/LocalStorageThreadListAdapter.js +2 -2
  2. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  3. package/dist/react/client/Tools.d.ts.map +1 -1
  4. package/dist/react/client/Tools.js +40 -55
  5. package/dist/react/client/Tools.js.map +1 -1
  6. package/dist/react/interactables-legacy/useAssistantInteractable.js +1 -1
  7. package/dist/react/interactables-legacy/useAssistantInteractable.js.map +1 -1
  8. package/dist/react/interactables-legacy/useInteractableState.js +3 -3
  9. package/dist/react/interactables-legacy/useInteractableState.js.map +1 -1
  10. package/dist/react/model-context/useAssistantContext.js +1 -1
  11. package/dist/react/model-context/useAssistantContext.js.map +1 -1
  12. package/dist/react/model-context/useAssistantDataUI.js +1 -1
  13. package/dist/react/model-context/useAssistantDataUI.js.map +1 -1
  14. package/dist/react/model-context/useAssistantInstructions.js +1 -1
  15. package/dist/react/model-context/useAssistantInstructions.js.map +1 -1
  16. package/dist/react/model-context/useAssistantTool.js +29 -25
  17. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  18. package/dist/react/model-context/useAssistantToolUI.js +1 -1
  19. package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
  20. package/dist/react/model-context/useAuiToolOverrides.js +1 -1
  21. package/dist/react/model-context/useAuiToolOverrides.js.map +1 -1
  22. package/dist/react/model-context/useInteractable.js +1 -1
  23. package/dist/react/model-context/useInteractable.js.map +1 -1
  24. package/dist/react/model-context/useInteractableState.js +2 -2
  25. package/dist/react/model-context/useInteractableState.js.map +1 -1
  26. package/dist/react/primitive-hooks/useActionBarCopy.js +3 -3
  27. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  28. package/dist/react/primitive-hooks/useActionBarEdit.js +1 -1
  29. package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
  30. package/dist/react/primitive-hooks/useActionBarFeedback.js +2 -2
  31. package/dist/react/primitive-hooks/useActionBarFeedback.js.map +1 -1
  32. package/dist/react/primitive-hooks/useActionBarReload.js +1 -1
  33. package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
  34. package/dist/react/primitive-hooks/useActionBarSpeak.js +1 -1
  35. package/dist/react/primitive-hooks/useActionBarSpeak.js.map +1 -1
  36. package/dist/react/primitive-hooks/useActionBarStopSpeaking.js +1 -1
  37. package/dist/react/primitive-hooks/useActionBarStopSpeaking.js.map +1 -1
  38. package/dist/react/primitive-hooks/useBranchPickerNext.js +1 -1
  39. package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
  40. package/dist/react/primitive-hooks/useBranchPickerPrevious.js +1 -1
  41. package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
  42. package/dist/react/primitive-hooks/useComposerAddAttachment.js +1 -1
  43. package/dist/react/primitive-hooks/useComposerAddAttachment.js.map +1 -1
  44. package/dist/react/primitive-hooks/useComposerCancel.js +1 -1
  45. package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
  46. package/dist/react/primitive-hooks/useComposerDictate.js +1 -1
  47. package/dist/react/primitive-hooks/useComposerDictate.js.map +1 -1
  48. package/dist/react/primitive-hooks/useComposerSend.js +1 -1
  49. package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
  50. package/dist/react/primitive-hooks/useEditComposerCancel.js +1 -1
  51. package/dist/react/primitive-hooks/useEditComposerCancel.js.map +1 -1
  52. package/dist/react/primitive-hooks/useEditComposerSend.js +1 -1
  53. package/dist/react/primitive-hooks/useEditComposerSend.js.map +1 -1
  54. package/dist/react/primitive-hooks/useMessageBranching.js +2 -2
  55. package/dist/react/primitive-hooks/useMessageBranching.js.map +1 -1
  56. package/dist/react/primitive-hooks/useMessageReload.js +1 -1
  57. package/dist/react/primitive-hooks/useMessageReload.js.map +1 -1
  58. package/dist/react/primitive-hooks/useSuggestionTrigger.js +7 -7
  59. package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
  60. package/dist/react/primitive-hooks/useThreadListItemArchive.js +1 -1
  61. package/dist/react/primitive-hooks/useThreadListItemArchive.js.map +1 -1
  62. package/dist/react/primitive-hooks/useThreadListItemDelete.js +1 -1
  63. package/dist/react/primitive-hooks/useThreadListItemDelete.js.map +1 -1
  64. package/dist/react/primitive-hooks/useThreadListItemTrigger.js +1 -1
  65. package/dist/react/primitive-hooks/useThreadListItemTrigger.js.map +1 -1
  66. package/dist/react/primitive-hooks/useThreadListItemUnarchive.js +1 -1
  67. package/dist/react/primitive-hooks/useThreadListItemUnarchive.js.map +1 -1
  68. package/dist/react/primitive-hooks/useThreadListLoadMore.js +1 -1
  69. package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
  70. package/dist/react/primitive-hooks/useThreadListNew.js +1 -1
  71. package/dist/react/primitive-hooks/useThreadListNew.js.map +1 -1
  72. package/dist/react/primitive-hooks/useVoice.js +5 -13
  73. package/dist/react/primitive-hooks/useVoice.js.map +1 -1
  74. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js +1 -1
  75. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js.map +1 -1
  76. package/dist/react/primitives/composer/ComposerAttachments.js +1 -1
  77. package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
  78. package/dist/react/primitives/composer/ComposerQueue.d.ts.map +1 -1
  79. package/dist/react/primitives/composer/ComposerQueue.js +1 -1
  80. package/dist/react/primitives/composer/ComposerQueue.js.map +1 -1
  81. package/dist/react/primitives/message/MessageAttachments.d.ts.map +1 -1
  82. package/dist/react/primitives/message/MessageAttachments.js +1 -1
  83. package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
  84. package/dist/react/primitives/message/MessageParts.js +84 -122
  85. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  86. package/dist/react/primitives/thread/ThreadMessages.js +1 -1
  87. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  88. package/dist/react/primitives/thread/ThreadSuggestions.js +1 -1
  89. package/dist/react/primitives/thread/ThreadSuggestions.js.map +1 -1
  90. package/dist/react/primitives/threadList/ThreadListItems.js +1 -1
  91. package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
  92. package/dist/react/providers/AttachmentByIndexProvider.js +2 -2
  93. package/dist/react/providers/AttachmentByIndexProvider.js.map +1 -1
  94. package/dist/react/providers/ChainOfThoughtByIndicesProvider.js +1 -1
  95. package/dist/react/providers/ChainOfThoughtByIndicesProvider.js.map +1 -1
  96. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.d.ts.map +1 -1
  97. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js +30 -18
  98. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js.map +1 -1
  99. package/dist/react/providers/MessageByIdProvider.js +2 -2
  100. package/dist/react/providers/MessageByIdProvider.js.map +1 -1
  101. package/dist/react/providers/MessageByIndexProvider.js +2 -2
  102. package/dist/react/providers/MessageByIndexProvider.js.map +1 -1
  103. package/dist/react/providers/PartByIndexProvider.d.ts.map +1 -1
  104. package/dist/react/providers/PartByIndexProvider.js +30 -18
  105. package/dist/react/providers/PartByIndexProvider.js.map +1 -1
  106. package/dist/react/providers/QueueItemByIndexProvider.js +1 -1
  107. package/dist/react/providers/QueueItemByIndexProvider.js.map +1 -1
  108. package/dist/react/providers/ReadonlyThreadProvider.js +1 -1
  109. package/dist/react/providers/ReadonlyThreadProvider.js.map +1 -1
  110. package/dist/react/providers/SuggestionByIndexProvider.js +1 -1
  111. package/dist/react/providers/SuggestionByIndexProvider.js.map +1 -1
  112. package/dist/react/providers/ThreadListItemByIndexProvider.js +1 -1
  113. package/dist/react/providers/ThreadListItemByIndexProvider.js.map +1 -1
  114. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +3 -3
  115. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  116. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  117. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +32 -20
  118. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  119. package/dist/react/runtimes/createRuntimeExtras.js +1 -1
  120. package/dist/react/runtimes/createRuntimeExtras.js.map +1 -1
  121. package/dist/react/types/scopes/tools.d.ts +0 -6
  122. package/dist/react/types/scopes/tools.d.ts.map +1 -1
  123. package/dist/react/utils/groupParts.d.ts +1 -3
  124. package/dist/react/utils/groupParts.d.ts.map +1 -1
  125. package/dist/react/utils/groupParts.js +1 -3
  126. package/dist/react/utils/groupParts.js.map +1 -1
  127. package/dist/store/clients/runtime-adapter.js +3 -3
  128. package/dist/store/clients/runtime-adapter.js.map +1 -1
  129. package/package.json +5 -5
  130. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +2 -2
  131. package/src/react/client/Tools.ts +0 -7
  132. package/src/react/interactables-legacy/useAssistantInteractable.ts +1 -1
  133. package/src/react/interactables-legacy/useInteractableState.ts +3 -3
  134. package/src/react/model-context/useAssistantContext.ts +1 -1
  135. package/src/react/model-context/useAssistantDataUI.ts +1 -1
  136. package/src/react/model-context/useAssistantInstructions.ts +1 -1
  137. package/src/react/model-context/useAssistantTool.ts +2 -2
  138. package/src/react/model-context/useAssistantToolUI.ts +1 -1
  139. package/src/react/model-context/useAuiToolOverrides.ts +1 -1
  140. package/src/react/model-context/useInteractable.ts +1 -1
  141. package/src/react/model-context/useInteractableState.ts +2 -2
  142. package/src/react/primitive-hooks/useActionBarCopy.test.ts +2 -2
  143. package/src/react/primitive-hooks/useActionBarCopy.ts +3 -3
  144. package/src/react/primitive-hooks/useActionBarEdit.ts +1 -1
  145. package/src/react/primitive-hooks/useActionBarFeedback.ts +2 -2
  146. package/src/react/primitive-hooks/useActionBarReload.ts +1 -1
  147. package/src/react/primitive-hooks/useActionBarSpeak.ts +1 -1
  148. package/src/react/primitive-hooks/useActionBarStopSpeaking.ts +1 -1
  149. package/src/react/primitive-hooks/useBranchPickerNext.ts +1 -1
  150. package/src/react/primitive-hooks/useBranchPickerPrevious.ts +1 -1
  151. package/src/react/primitive-hooks/useComposerAddAttachment.ts +1 -1
  152. package/src/react/primitive-hooks/useComposerCancel.ts +1 -1
  153. package/src/react/primitive-hooks/useComposerDictate.ts +1 -1
  154. package/src/react/primitive-hooks/useComposerSend.ts +1 -1
  155. package/src/react/primitive-hooks/useEditComposerCancel.ts +1 -1
  156. package/src/react/primitive-hooks/useEditComposerSend.ts +1 -1
  157. package/src/react/primitive-hooks/useMessageBranching.ts +2 -2
  158. package/src/react/primitive-hooks/useMessageReload.ts +1 -1
  159. package/src/react/primitive-hooks/useSuggestionTrigger.ts +9 -9
  160. package/src/react/primitive-hooks/useThreadListItemArchive.ts +1 -1
  161. package/src/react/primitive-hooks/useThreadListItemDelete.ts +1 -1
  162. package/src/react/primitive-hooks/useThreadListItemTrigger.ts +1 -1
  163. package/src/react/primitive-hooks/useThreadListItemUnarchive.ts +1 -1
  164. package/src/react/primitive-hooks/useThreadListLoadMore.ts +1 -1
  165. package/src/react/primitive-hooks/useThreadListNew.ts +1 -1
  166. package/src/react/primitive-hooks/useVoice.ts +5 -5
  167. package/src/react/primitives/chainOfThought/ChainOfThoughtParts.tsx +1 -1
  168. package/src/react/primitives/composer/ComposerAttachments.tsx +1 -1
  169. package/src/react/primitives/composer/ComposerQueue.tsx +1 -3
  170. package/src/react/primitives/message/MessageAttachments.tsx +1 -3
  171. package/src/react/primitives/message/MessageParts.tsx +9 -9
  172. package/src/react/primitives/thread/ThreadMessages.tsx +1 -1
  173. package/src/react/primitives/thread/ThreadSuggestions.tsx +1 -1
  174. package/src/react/primitives/threadList/ThreadListItems.tsx +1 -1
  175. package/src/react/providers/AttachmentByIndexProvider.tsx +2 -2
  176. package/src/react/providers/ChainOfThoughtByIndicesProvider.tsx +1 -1
  177. package/src/react/providers/ChainOfThoughtPartByIndexProvider.tsx +2 -19
  178. package/src/react/providers/MessageByIdProvider.tsx +2 -2
  179. package/src/react/providers/MessageByIndexProvider.tsx +2 -2
  180. package/src/react/providers/PartByIndexProvider.tsx +2 -16
  181. package/src/react/providers/QueueItemByIndexProvider.tsx +1 -1
  182. package/src/react/providers/ReadonlyThreadProvider.tsx +1 -1
  183. package/src/react/providers/SuggestionByIndexProvider.tsx +1 -1
  184. package/src/react/providers/ThreadListItemByIndexProvider.tsx +1 -1
  185. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +3 -3
  186. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +32 -7
  187. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +26 -16
  188. package/src/react/runtimes/createRuntimeExtras.test.ts +1 -1
  189. package/src/react/runtimes/createRuntimeExtras.ts +1 -1
  190. package/src/react/types/scopes/tools.ts +0 -6
  191. package/src/react/utils/groupParts.ts +1 -7
  192. package/src/store/clients/runtime-adapter.ts +3 -3
  193. package/src/tests/groupParts.test.ts +3 -48
@@ -78,7 +78,7 @@ const ThreadListPrimitiveItemsInner: FC<{
78
78
  >
79
79
  <RenderChildrenWithAccessor
80
80
  getItemState={(aui) =>
81
- aui.threads().item({ index, archived }).getState()
81
+ aui.threads.item({ index, archived }).getState()
82
82
  }
83
83
  >
84
84
  {(getItem) =>
@@ -10,7 +10,7 @@ export const MessageAttachmentByIndexProvider: FC<
10
10
  attachment: Derived({
11
11
  source: "message",
12
12
  query: { type: "index", index },
13
- get: (aui) => aui.message().attachment({ index }),
13
+ get: (aui) => aui.message.attachment({ index }),
14
14
  }),
15
15
  });
16
16
 
@@ -26,7 +26,7 @@ export const ComposerAttachmentByIndexProvider: FC<
26
26
  attachment: Derived({
27
27
  source: "composer",
28
28
  query: { type: "index", index },
29
- get: (aui) => aui.composer().attachment({ index }),
29
+ get: (aui) => aui.composer.attachment({ index }),
30
30
  }),
31
31
  });
32
32
 
@@ -25,7 +25,7 @@ export const ChainOfThoughtByIndicesProvider: FC<
25
25
  `ChainOfThought part index ${index} is out of bounds (0..${parts.length - 1})`,
26
26
  );
27
27
  }
28
- return parentAui.message().part({ index: startIndex + index });
28
+ return parentAui.message.part({ index: startIndex + index });
29
29
  },
30
30
  }),
31
31
  });
@@ -1,33 +1,16 @@
1
- import { useMemo, type FC, type PropsWithChildren } from "react";
1
+ import type { FC, PropsWithChildren } from "react";
2
2
  import { useAui, AuiProvider, Derived } from "@assistant-ui/store";
3
- import type { PartMethods } from "../../store/scopes/part";
4
3
 
5
4
  export const ChainOfThoughtPartByIndexProvider: FC<
6
5
  PropsWithChildren<{
7
6
  index: number;
8
7
  }>
9
8
  > = ({ index, children }) => {
10
- const lastPartRef = useMemo(
11
- () => ({ index, current: null as PartMethods | null }),
12
- [index],
13
- );
14
9
  const aui = useAui({
15
10
  part: Derived({
16
11
  source: "chainOfThought",
17
12
  query: { type: "index", index },
18
- get: (aui) => {
19
- const chainOfThought = aui.chainOfThought();
20
- if (
21
- index >= chainOfThought.getState().parts.length &&
22
- lastPartRef.current
23
- ) {
24
- return lastPartRef.current;
25
- }
26
-
27
- const part = chainOfThought.part({ index });
28
- lastPartRef.current = part;
29
- return part;
30
- },
13
+ get: (aui) => aui.chainOfThought.part({ index }),
31
14
  }),
32
15
  });
33
16
 
@@ -10,12 +10,12 @@ export const MessageByIdProvider: FC<
10
10
  message: Derived({
11
11
  source: "thread",
12
12
  query: { type: "id", id },
13
- get: (aui) => aui.thread().message({ id }),
13
+ get: (aui) => aui.thread.message({ id }),
14
14
  }),
15
15
  composer: Derived({
16
16
  source: "message",
17
17
  query: {},
18
- get: (aui) => aui.thread().message({ id }).composer(),
18
+ get: (aui) => aui.thread.message({ id }).composer(),
19
19
  }),
20
20
  });
21
21
 
@@ -10,12 +10,12 @@ export const MessageByIndexProvider: FC<
10
10
  message: Derived({
11
11
  source: "thread",
12
12
  query: { type: "index", index },
13
- get: (aui) => aui.thread().message({ index }),
13
+ get: (aui) => aui.thread.message({ index }),
14
14
  }),
15
15
  composer: Derived({
16
16
  source: "message",
17
17
  query: {},
18
- get: (aui) => aui.thread().message({ index }).composer(),
18
+ get: (aui) => aui.thread.message({ index }).composer(),
19
19
  }),
20
20
  });
21
21
 
@@ -1,30 +1,16 @@
1
- import { useMemo, type FC, type PropsWithChildren } from "react";
1
+ import type { FC, PropsWithChildren } from "react";
2
2
  import { useAui, AuiProvider, Derived } from "@assistant-ui/store";
3
- import type { PartMethods } from "../../store/scopes/part";
4
3
 
5
4
  export const PartByIndexProvider: FC<
6
5
  PropsWithChildren<{
7
6
  index: number;
8
7
  }>
9
8
  > = ({ index, children }) => {
10
- const lastPartRef = useMemo(
11
- () => ({ index, current: null as PartMethods | null }),
12
- [index],
13
- );
14
9
  const aui = useAui({
15
10
  part: Derived({
16
11
  source: "message",
17
12
  query: { type: "index", index },
18
- get: (aui) => {
19
- const message = aui.message();
20
- if (index >= message.getState().parts.length && lastPartRef.current) {
21
- return lastPartRef.current;
22
- }
23
-
24
- const part = message.part({ index });
25
- lastPartRef.current = part;
26
- return part;
27
- },
13
+ get: (aui) => aui.message.part({ index }),
28
14
  }),
29
15
  });
30
16
 
@@ -13,7 +13,7 @@ export const QueueItemByIndexProvider: FC<QueueItemByIndexProviderProps> = ({
13
13
  queueItem: Derived({
14
14
  source: "composer",
15
15
  query: { index },
16
- get: (aui) => aui.composer().queueItem({ index }),
16
+ get: (aui) => aui.composer.queueItem({ index }),
17
17
  }),
18
18
  });
19
19
 
@@ -76,7 +76,7 @@ export const ReadonlyThreadProvider: FC<ReadonlyThreadProvider.Props> = ({
76
76
  composer: Derived({
77
77
  source: "thread",
78
78
  query: {},
79
- get: (aui) => aui.thread().composer(),
79
+ get: (aui) => aui.thread.composer(),
80
80
  }),
81
81
  });
82
82
 
@@ -13,7 +13,7 @@ export const SuggestionByIndexProvider: FC<SuggestionByIndexProviderProps> = ({
13
13
  suggestion: Derived({
14
14
  source: "suggestions",
15
15
  query: { index },
16
- get: (aui) => aui.suggestions().suggestion({ index }),
16
+ get: (aui) => aui.suggestions.suggestion({ index }),
17
17
  }),
18
18
  });
19
19
 
@@ -11,7 +11,7 @@ export const ThreadListItemByIndexProvider: FC<
11
11
  threadListItem: Derived({
12
12
  source: "threads",
13
13
  query: { type: "index", index, archived },
14
- get: (aui) => aui.threads().item({ index, archived }),
14
+ get: (aui) => aui.threads.item({ index, archived }),
15
15
  }),
16
16
  });
17
17
 
@@ -147,15 +147,15 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
147
147
  return runtime.threads.main.unstable_on("initialize", () => {
148
148
  if (hasInitializedRef.current) return;
149
149
 
150
- const state = aui.threadListItem().getState();
150
+ const state = aui.threadListItem.getState();
151
151
  if (state.status !== "new") return;
152
152
  hasInitializedRef.current = true;
153
153
 
154
- initPromiseRef.current = aui.threadListItem().initialize();
154
+ initPromiseRef.current = aui.threadListItem.initialize();
155
155
 
156
156
  const dispose = runtime.thread.unstable_on("runEnd", () => {
157
157
  dispose();
158
- aui.threadListItem().generateTitle();
158
+ aui.threadListItem.generateTitle();
159
159
  });
160
160
  });
161
161
  }, [runtime, aui]);
@@ -6,20 +6,22 @@ import { describe, expect, it, vi } from "vitest";
6
6
  import { useAssistantCloudThreadHistoryAdapter } from "./AssistantCloudThreadHistoryAdapter";
7
7
 
8
8
  const mocks = vi.hoisted(() => {
9
- const threadListItem = {
10
- getState: () => ({ remoteId: "thread-1" }),
11
- };
9
+ const makeClient = (remoteId: string) =>
10
+ ({
11
+ threadListItem: {
12
+ getState: () => ({ remoteId }),
13
+ },
14
+ }) as unknown as import("@assistant-ui/store").AssistantClient;
12
15
 
13
16
  return {
14
- assistantClient: {
15
- threadListItem: () => threadListItem,
16
- },
17
+ makeClient,
18
+ aui: makeClient("thread-1"),
17
19
  };
18
20
  });
19
21
 
20
22
  vi.mock("@assistant-ui/store", async (importOriginal) => ({
21
23
  ...(await importOriginal<typeof import("@assistant-ui/store")>()),
22
- useAui: () => mocks.assistantClient,
24
+ useAui: () => mocks.aui,
23
25
  }));
24
26
 
25
27
  const makeCloud = () =>
@@ -33,6 +35,7 @@ const makeCloud = () =>
33
35
 
34
36
  describe("useAssistantCloudThreadHistoryAdapter", () => {
35
37
  it("refreshes formatted persistence when the Cloud client changes", async () => {
38
+ mocks.aui = mocks.makeClient("thread-1");
36
39
  const firstCloud = makeCloud();
37
40
  const secondCloud = makeCloud();
38
41
  const cloudRef = { current: firstCloud };
@@ -66,4 +69,26 @@ describe("useAssistantCloudThreadHistoryAdapter", () => {
66
69
  format: "test",
67
70
  });
68
71
  });
72
+
73
+ it("resolves the aui client at call time instead of capturing it", async () => {
74
+ mocks.aui = mocks.makeClient("thread-1");
75
+ const cloud = makeCloud();
76
+ const cloudRef = { current: cloud };
77
+ const { result, rerender } = renderHook(() =>
78
+ useAssistantCloudThreadHistoryAdapter(cloudRef),
79
+ );
80
+
81
+ await result.current.load();
82
+ expect(cloud.threads.messages.list).toHaveBeenCalledWith("thread-1", {
83
+ format: "aui/v0",
84
+ });
85
+
86
+ mocks.aui = mocks.makeClient("thread-2");
87
+ rerender();
88
+
89
+ await result.current.load();
90
+ expect(cloud.threads.messages.list).toHaveBeenCalledWith("thread-2", {
91
+ format: "aui/v0",
92
+ });
93
+ });
69
94
  });
@@ -1,4 +1,4 @@
1
- import { type RefObject, useState } from "react";
1
+ import { type RefObject, useEffect, useRef, useState } from "react";
2
2
  import type {
3
3
  GenericThreadHistoryAdapter,
4
4
  ThreadHistoryAdapter,
@@ -13,25 +13,31 @@ import {
13
13
  createFormattedPersistence,
14
14
  } from "assistant-cloud";
15
15
  import { auiV0Decode, auiV0Encode } from "./auiV0";
16
- import { type AssistantClient, useAui } from "@assistant-ui/store";
17
- import type { ThreadListItemMethods } from "../../../store/scopes/thread-list-item";
16
+ import { type AssistantClient, getClientId, useAui } from "@assistant-ui/store";
18
17
 
19
18
  const globalPersistence = new WeakMap<
20
- ThreadListItemMethods,
19
+ getClientId.ClientId,
21
20
  CloudMessagePersistence
22
21
  >();
23
22
 
24
23
  class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
25
24
  private cloudRef: RefObject<AssistantCloud>;
26
- private aui: AssistantClient;
25
+ private auiRef: RefObject<AssistantClient>;
27
26
 
28
- constructor(cloudRef: RefObject<AssistantCloud>, aui: AssistantClient) {
27
+ constructor(
28
+ cloudRef: RefObject<AssistantCloud>,
29
+ auiRef: RefObject<AssistantClient>,
30
+ ) {
29
31
  this.cloudRef = cloudRef;
30
- this.aui = aui;
32
+ this.auiRef = auiRef;
33
+ }
34
+
35
+ private get aui(): AssistantClient {
36
+ return this.auiRef.current;
31
37
  }
32
38
 
33
39
  private get _persistence(): CloudMessagePersistence {
34
- const key = this.aui.threadListItem();
40
+ const key = getClientId(this.aui.threadListItem);
35
41
  if (!globalPersistence.has(key)) {
36
42
  globalPersistence.set(
37
43
  key,
@@ -52,11 +58,11 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
52
58
  return {
53
59
  // Note: callers must also call reportTelemetry() for run tracking
54
60
  async append(item: MessageFormatItem<TMessage>) {
55
- const { remoteId } = await adapter.aui.threadListItem().initialize();
61
+ const { remoteId } = await adapter.aui.threadListItem.initialize();
56
62
  await formatted.append(remoteId, item);
57
63
  },
58
64
  async update(item: MessageFormatItem<TMessage>, localMessageId: string) {
59
- const remoteId = adapter.aui.threadListItem().getState().remoteId;
65
+ const remoteId = adapter.aui.threadListItem.getState().remoteId;
60
66
  if (!remoteId) return;
61
67
  await formatted.update?.(remoteId, item, localMessageId);
62
68
  },
@@ -82,7 +88,7 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
82
88
  );
83
89
  },
84
90
  async load(): Promise<MessageFormatRepository<TMessage>> {
85
- const remoteId = adapter.aui.threadListItem().getState().remoteId;
91
+ const remoteId = adapter.aui.threadListItem.getState().remoteId;
86
92
  if (!remoteId) return { messages: [] };
87
93
  return formatted.load(remoteId);
88
94
  },
@@ -90,7 +96,7 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
90
96
  }
91
97
 
92
98
  async append({ parentId, message }: ExportedMessageRepositoryItem) {
93
- const { remoteId } = await this.aui.threadListItem().initialize();
99
+ const { remoteId } = await this.aui.threadListItem.initialize();
94
100
  const encoded = auiV0Encode(message);
95
101
  await this._persistence.append(
96
102
  remoteId,
@@ -110,7 +116,7 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
110
116
  return this.append(item);
111
117
  }
112
118
  const { message } = item;
113
- const remoteId = this.aui.threadListItem().getState().remoteId;
119
+ const remoteId = this.aui.threadListItem.getState().remoteId;
114
120
  if (!remoteId) return;
115
121
  const encoded = auiV0Encode(message);
116
122
  await this._persistence.update(remoteId, message.id, "aui/v0", encoded);
@@ -127,7 +133,7 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
127
133
  }
128
134
 
129
135
  async load() {
130
- const remoteId = this.aui.threadListItem().getState().remoteId;
136
+ const remoteId = this.aui.threadListItem.getState().remoteId;
131
137
  if (!remoteId) return { messages: [] };
132
138
  const messages = await this._persistence.load(remoteId, "aui/v0");
133
139
  return {
@@ -150,7 +156,7 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
150
156
  ) {
151
157
  if (!this.cloudRef.current.telemetry.enabled) return;
152
158
 
153
- const remoteId = this.aui.threadListItem().getState().remoteId;
159
+ const remoteId = this.aui.threadListItem.getState().remoteId;
154
160
  if (!remoteId) return;
155
161
 
156
162
  const extracted = extractRunTelemetry(format, runMessages);
@@ -810,8 +816,12 @@ export function useAssistantCloudThreadHistoryAdapter(
810
816
  cloudRef: RefObject<AssistantCloud>,
811
817
  ): ThreadHistoryAdapter {
812
818
  const aui = useAui();
819
+ const auiRef = useRef(aui);
820
+ useEffect(() => {
821
+ auiRef.current = aui;
822
+ });
813
823
  const [adapter] = useState(
814
- () => new AssistantCloudThreadHistoryAdapter(cloudRef, aui),
824
+ () => new AssistantCloudThreadHistoryAdapter(cloudRef, auiRef),
815
825
  );
816
826
  return adapter;
817
827
  }
@@ -6,7 +6,7 @@ type Extras = { value: number; greet: () => string };
6
6
 
7
7
  const clientWith = (extras: unknown) =>
8
8
  ({
9
- thread: () => ({ getState: () => ({ extras }) }),
9
+ thread: { getState: () => ({ extras }) },
10
10
  }) as unknown as AssistantClient;
11
11
 
12
12
  describe("createRuntimeExtras", () => {
@@ -46,7 +46,7 @@ export const createRuntimeExtras = <T extends object>(
46
46
  is(extras) ? extras : undefined;
47
47
 
48
48
  const get = (client: AssistantClient): T =>
49
- assert(client.thread().getState().extras);
49
+ assert(client.thread.getState().extras);
50
50
 
51
51
  function use<S>(
52
52
  select?: (extras: T) => S,
@@ -20,12 +20,6 @@ export type ToolsState = {
20
20
  /** Registered tool UIs (renderer + presentation options) keyed by tool name. */
21
21
  toolUIs: Record<string, readonly ToolRegistration[]>;
22
22
  mcpApp?: McpAppResourceOutput | undefined;
23
- /**
24
- * @deprecated Use {@link toolUIs} instead, whose entries carry the renderer
25
- * alongside its presentation options. This component-only map is kept for
26
- * back-compat and will be removed in v0.15.
27
- */
28
- tools: Record<string, ToolCallMessagePartComponent[]>;
29
23
  };
30
24
 
31
25
  export type ToolsMethods = {
@@ -47,10 +47,8 @@ export const GROUPBY_MEMO_KEY: unique symbol = Symbol.for(
47
47
  * `display: "standalone"`). Resolving the registry-driven cases reads the
48
48
  * {@link GroupByContext} passed to the `groupBy` function. Takes precedence
49
49
  * over the `"tool-call"` entry.
50
- * - `"mcp-app"` — **deprecated**, kept for back-compat. Matches only MCP-app
51
- * tool calls. Prefer `"standalone-tool-call"`, which is a superset.
52
50
  */
53
- type GroupPartType = PartState["type"] | "standalone-tool-call" | "mcp-app";
51
+ type GroupPartType = PartState["type"] | "standalone-tool-call";
54
52
 
55
53
  /**
56
54
  * Build a `groupBy` from a `part.type → group-key path` lookup.
@@ -93,10 +91,6 @@ export const groupPartByType = <TKey extends `group-${string}`>(
93
91
  if (isStandalone && lookup["standalone-tool-call"] !== undefined) {
94
92
  return lookup["standalone-tool-call"]!;
95
93
  }
96
- // TODO(v0.15): drop the deprecated "mcp-app" key (superseded by "standalone-tool-call").
97
- if (isMcpApp && lookup["mcp-app"] !== undefined) {
98
- return lookup["mcp-app"]!;
99
- }
100
94
  }
101
95
  return lookup[part.type] ?? [];
102
96
  }) as ((part: PartState, context?: GroupByContext) => readonly TKey[]) & {
@@ -13,17 +13,17 @@ export const baseRuntimeAdapterTransformScopes = (
13
13
  scopes.thread ??= Derived({
14
14
  source: "threads",
15
15
  query: { type: "main" },
16
- get: (aui) => aui.threads().thread("main"),
16
+ get: (aui) => aui.threads.thread("main"),
17
17
  });
18
18
  scopes.threadListItem ??= Derived({
19
19
  source: "threads",
20
20
  query: { type: "main" },
21
- get: (aui) => aui.threads().item("main"),
21
+ get: (aui) => aui.threads.item("main"),
22
22
  });
23
23
  scopes.composer ??= Derived({
24
24
  source: "thread",
25
25
  query: {},
26
- get: (aui) => aui.threads().thread("main").composer(),
26
+ get: (aui) => aui.threads.thread("main").composer(),
27
27
  });
28
28
 
29
29
  if (!scopes.modelContext && parent.modelContext.source === null) {
@@ -119,25 +119,7 @@ describe("groupPartByType", () => {
119
119
  expect(fn(part({ type: "text" }))).toEqual([]);
120
120
  });
121
121
 
122
- it("routes MCP-app tool calls through the 'mcp-app' entry when present", () => {
123
- const fn = groupPartByType({
124
- "tool-call": ["group-tool"],
125
- "mcp-app": [],
126
- });
127
- const mcpApp = part({
128
- type: "tool-call",
129
- toolName: "render",
130
- mcp: { app: { resourceUri: "ui://my-app" } },
131
- } as Partial<PartState>);
132
- const regular = part({
133
- type: "tool-call",
134
- toolName: "search",
135
- } as Partial<PartState>);
136
- expect(fn(mcpApp)).toEqual([]);
137
- expect(fn(regular)).toEqual(["group-tool"]);
138
- });
139
-
140
- it("falls back to 'tool-call' for MCP-app parts when 'mcp-app' is absent", () => {
122
+ it("falls back to 'tool-call' for MCP-app parts when 'standalone-tool-call' is absent", () => {
141
123
  const fn = groupPartByType({ "tool-call": ["group-tool"] });
142
124
  const mcpApp = part({
143
125
  type: "tool-call",
@@ -147,10 +129,10 @@ describe("groupPartByType", () => {
147
129
  expect(fn(mcpApp)).toEqual(["group-tool"]);
148
130
  });
149
131
 
150
- it("does not route non-`ui://` tool calls through 'mcp-app'", () => {
132
+ it("does not treat non-`ui://` tool calls as standalone", () => {
151
133
  const fn = groupPartByType({
152
134
  "tool-call": ["group-tool"],
153
- "mcp-app": ["group-mcp"],
135
+ "standalone-tool-call": ["group-standalone"],
154
136
  });
155
137
  const notMcp = part({
156
138
  type: "tool-call",
@@ -235,33 +217,6 @@ describe("groupPartByType", () => {
235
217
  expect(fn(mcpApp)).toEqual([]);
236
218
  });
237
219
 
238
- it("routes MCP-app parts through the deprecated 'mcp-app' entry", () => {
239
- const fn = groupPartByType({
240
- "tool-call": ["group-tool"],
241
- "mcp-app": ["group-mcp"],
242
- });
243
- const mcpApp = part({
244
- type: "tool-call",
245
- toolName: "render",
246
- mcp: { app: { resourceUri: "ui://my-app" } },
247
- } as Partial<PartState>);
248
- expect(fn(mcpApp)).toEqual(["group-mcp"]);
249
- });
250
-
251
- it("prefers 'standalone-tool-call' over the deprecated 'mcp-app' entry", () => {
252
- const fn = groupPartByType({
253
- "tool-call": ["group-tool"],
254
- "standalone-tool-call": ["group-standalone"],
255
- "mcp-app": ["group-mcp"],
256
- });
257
- const mcpApp = part({
258
- type: "tool-call",
259
- toolName: "render",
260
- mcp: { app: { resourceUri: "ui://x" } },
261
- } as Partial<PartState>);
262
- expect(fn(mcpApp)).toEqual(["group-standalone"]);
263
- });
264
-
265
220
  it("tags the function with a GROUPBY_MEMO_KEY fingerprint", () => {
266
221
  const fn = groupPartByType({ reasoning: ["group-r"] });
267
222
  const memoKey = (fn as unknown as { [GROUPBY_MEMO_KEY]: string })[