@assistant-ui/react 0.12.0 → 0.12.3

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 (154) hide show
  1. package/dist/client/Suggestions.d.ts +11 -0
  2. package/dist/client/Suggestions.d.ts.map +1 -0
  3. package/dist/client/Suggestions.js +43 -0
  4. package/dist/client/Suggestions.js.map +1 -0
  5. package/dist/client/Tools.d.ts.map +1 -1
  6. package/dist/client/Tools.js +5 -1
  7. package/dist/client/Tools.js.map +1 -1
  8. package/dist/context/providers/SuggestionByIndexProvider.d.ts +6 -0
  9. package/dist/context/providers/SuggestionByIndexProvider.d.ts.map +1 -0
  10. package/dist/context/providers/SuggestionByIndexProvider.js +14 -0
  11. package/dist/context/providers/SuggestionByIndexProvider.js.map +1 -0
  12. package/dist/context/providers/ThreadListItemProvider.d.ts +3 -2
  13. package/dist/context/providers/ThreadListItemProvider.d.ts.map +1 -1
  14. package/dist/context/providers/ThreadListItemProvider.js +3 -6
  15. package/dist/context/providers/ThreadListItemProvider.js.map +1 -1
  16. package/dist/context/providers/index.d.ts +2 -1
  17. package/dist/context/providers/index.d.ts.map +1 -1
  18. package/dist/context/providers/index.js +2 -1
  19. package/dist/context/providers/index.js.map +1 -1
  20. package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts +5 -0
  21. package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts.map +1 -1
  22. package/dist/legacy-runtime/AssistantRuntimeProvider.js +2 -4
  23. package/dist/legacy-runtime/AssistantRuntimeProvider.js.map +1 -1
  24. package/dist/legacy-runtime/RuntimeAdapter.js +2 -1
  25. package/dist/legacy-runtime/RuntimeAdapter.js.map +1 -1
  26. package/dist/legacy-runtime/client/ThreadListRuntimeClient.js +3 -3
  27. package/dist/legacy-runtime/client/ThreadListRuntimeClient.js.map +1 -1
  28. package/dist/legacy-runtime/runtime/RuntimeBindings.d.ts +0 -4
  29. package/dist/legacy-runtime/runtime/RuntimeBindings.d.ts.map +1 -1
  30. package/dist/legacy-runtime/runtime/ThreadListRuntime.d.ts +3 -3
  31. package/dist/legacy-runtime/runtime/ThreadListRuntime.d.ts.map +1 -1
  32. package/dist/legacy-runtime/runtime/ThreadListRuntime.js +4 -5
  33. package/dist/legacy-runtime/runtime/ThreadListRuntime.js.map +1 -1
  34. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -1
  35. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +3 -5
  36. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
  37. package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.d.ts +10 -12
  38. package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.d.ts.map +1 -1
  39. package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.js +14 -19
  40. package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.js.map +1 -1
  41. package/dist/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.d.ts +1 -1
  42. package/dist/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.d.ts.map +1 -1
  43. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.d.ts +1 -1
  44. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.d.ts.map +1 -1
  45. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.js +1 -1
  46. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.js.map +1 -1
  47. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.d.ts.map +1 -1
  48. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.js +32 -4
  49. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.js.map +1 -1
  50. package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.d.ts +1 -1
  51. package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.d.ts.map +1 -1
  52. package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.js +1 -1
  53. package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.js.map +1 -1
  54. package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.d.ts.map +1 -1
  55. package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.js +3 -0
  56. package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.js.map +1 -1
  57. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts +3 -1
  58. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  59. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.js +8 -5
  60. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.js.map +1 -1
  61. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts +1 -1
  62. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  63. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js +2 -2
  64. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  65. package/dist/model-context/index.d.ts +1 -0
  66. package/dist/model-context/index.d.ts.map +1 -1
  67. package/dist/model-context/index.js +1 -0
  68. package/dist/model-context/index.js.map +1 -1
  69. package/dist/primitives/assistantModal/AssistantModalRoot.js +1 -1
  70. package/dist/primitives/assistantModal/AssistantModalRoot.js.map +1 -1
  71. package/dist/primitives/index.d.ts +1 -0
  72. package/dist/primitives/index.d.ts.map +1 -1
  73. package/dist/primitives/index.js +1 -0
  74. package/dist/primitives/index.js.map +1 -1
  75. package/dist/primitives/message/MessageParts.d.ts +11 -0
  76. package/dist/primitives/message/MessageParts.d.ts.map +1 -1
  77. package/dist/primitives/message/MessageParts.js +18 -2
  78. package/dist/primitives/message/MessageParts.js.map +1 -1
  79. package/dist/primitives/suggestion/SuggestionDescription.d.ts +18 -0
  80. package/dist/primitives/suggestion/SuggestionDescription.d.ts.map +1 -0
  81. package/dist/primitives/suggestion/SuggestionDescription.js +19 -0
  82. package/dist/primitives/suggestion/SuggestionDescription.js.map +1 -0
  83. package/dist/primitives/suggestion/SuggestionTitle.d.ts +18 -0
  84. package/dist/primitives/suggestion/SuggestionTitle.d.ts.map +1 -0
  85. package/dist/primitives/suggestion/SuggestionTitle.js +19 -0
  86. package/dist/primitives/suggestion/SuggestionTitle.js.map +1 -0
  87. package/dist/primitives/suggestion/SuggestionTrigger.d.ts +49 -0
  88. package/dist/primitives/suggestion/SuggestionTrigger.d.ts.map +1 -0
  89. package/dist/primitives/suggestion/SuggestionTrigger.js +45 -0
  90. package/dist/primitives/suggestion/SuggestionTrigger.js.map +1 -0
  91. package/dist/primitives/suggestion/index.d.ts +4 -0
  92. package/dist/primitives/suggestion/index.d.ts.map +1 -0
  93. package/dist/primitives/suggestion/index.js +4 -0
  94. package/dist/primitives/suggestion/index.js.map +1 -0
  95. package/dist/primitives/thread/ThreadSuggestions.d.ts +53 -0
  96. package/dist/primitives/thread/ThreadSuggestions.d.ts.map +1 -0
  97. package/dist/primitives/thread/ThreadSuggestions.js +58 -0
  98. package/dist/primitives/thread/ThreadSuggestions.js.map +1 -0
  99. package/dist/primitives/thread/index.d.ts +1 -0
  100. package/dist/primitives/thread/index.d.ts.map +1 -1
  101. package/dist/primitives/thread/index.js +1 -0
  102. package/dist/primitives/thread/index.js.map +1 -1
  103. package/dist/types/scopes/index.d.ts +2 -0
  104. package/dist/types/scopes/index.d.ts.map +1 -1
  105. package/dist/types/scopes/suggestion.d.ts +20 -0
  106. package/dist/types/scopes/suggestion.d.ts.map +1 -0
  107. package/dist/types/scopes/suggestion.js +2 -0
  108. package/dist/types/scopes/suggestion.js.map +1 -0
  109. package/dist/types/scopes/suggestions.d.ts +20 -0
  110. package/dist/types/scopes/suggestions.d.ts.map +1 -0
  111. package/dist/types/scopes/suggestions.js +2 -0
  112. package/dist/types/scopes/suggestions.js.map +1 -0
  113. package/dist/types/store-augmentation.d.ts +4 -0
  114. package/dist/types/store-augmentation.d.ts.map +1 -1
  115. package/dist/utils/idUtils.d.ts +2 -0
  116. package/dist/utils/idUtils.d.ts.map +1 -1
  117. package/dist/utils/idUtils.js +3 -0
  118. package/dist/utils/idUtils.js.map +1 -1
  119. package/package.json +10 -10
  120. package/src/client/Suggestions.ts +74 -0
  121. package/src/client/Tools.ts +10 -1
  122. package/src/context/providers/SuggestionByIndexProvider.tsx +23 -0
  123. package/src/context/providers/ThreadListItemProvider.tsx +6 -8
  124. package/src/context/providers/index.ts +2 -1
  125. package/src/legacy-runtime/AssistantRuntimeProvider.tsx +8 -5
  126. package/src/legacy-runtime/RuntimeAdapter.ts +2 -1
  127. package/src/legacy-runtime/client/ThreadListRuntimeClient.ts +3 -3
  128. package/src/legacy-runtime/runtime/RuntimeBindings.ts +0 -4
  129. package/src/legacy-runtime/runtime/ThreadListRuntime.ts +7 -8
  130. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.tsx +3 -4
  131. package/src/legacy-runtime/runtime-cores/assistant-transport/utils.ts +19 -24
  132. package/src/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.tsx +1 -1
  133. package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.tsx +1 -1
  134. package/src/legacy-runtime/runtime-cores/external-store/external-message-converter.tsx +42 -7
  135. package/src/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.tsx +1 -1
  136. package/src/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.tsx +3 -0
  137. package/src/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.tsx +20 -6
  138. package/src/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.tsx +2 -2
  139. package/src/model-context/index.ts +2 -0
  140. package/src/primitives/assistantModal/AssistantModalRoot.tsx +1 -1
  141. package/src/primitives/index.ts +1 -0
  142. package/src/primitives/message/MessageParts.tsx +45 -1
  143. package/src/primitives/suggestion/SuggestionDescription.tsx +33 -0
  144. package/src/primitives/suggestion/SuggestionTitle.tsx +33 -0
  145. package/src/primitives/suggestion/SuggestionTrigger.tsx +79 -0
  146. package/src/primitives/suggestion/index.ts +3 -0
  147. package/src/primitives/thread/ThreadSuggestions.tsx +109 -0
  148. package/src/primitives/thread/index.ts +4 -0
  149. package/src/tests/external-message-converter.test.ts +105 -16
  150. package/src/types/scopes/index.ts +12 -0
  151. package/src/types/scopes/suggestion.ts +20 -0
  152. package/src/types/scopes/suggestions.ts +21 -0
  153. package/src/types/store-augmentation.ts +4 -0
  154. package/src/utils/idUtils.tsx +4 -0
@@ -3,4 +3,7 @@ export const generateId = customAlphabet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZab
3
3
  const optimisticPrefix = "__optimistic__";
4
4
  export const generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
5
5
  export const isOptimisticId = (id) => id.startsWith(optimisticPrefix);
6
+ const errorPrefix = "__error__";
7
+ export const generateErrorMessageId = () => `${errorPrefix}${generateId()}`;
8
+ export const isErrorMessageId = (id) => id.startsWith(errorPrefix);
6
9
  //# sourceMappingURL=idUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"idUtils.js","sourceRoot":"","sources":["../../src/utils/idUtils.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CACtC,gEAAgE,EAChE,CAAC,CACF,CAAC;AAEF,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAC1C,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,EAAE,CAAC,GAAG,gBAAgB,GAAG,UAAU,EAAE,EAAE,CAAC;AAC/E,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC"}
1
+ {"version":3,"file":"idUtils.js","sourceRoot":"","sources":["../../src/utils/idUtils.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CACtC,gEAAgE,EAChE,CAAC,CACF,CAAC;AAEF,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAC1C,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,EAAE,CAAC,GAAG,gBAAgB,GAAG,UAAU,EAAE,EAAE,CAAC;AAC/E,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AAE9E,MAAM,WAAW,GAAG,WAAW,CAAC;AAChC,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE,CAAC,GAAG,WAAW,GAAG,UAAU,EAAE,EAAE,CAAC;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react",
3
- "version": "0.12.0",
3
+ "version": "0.12.3",
4
4
  "description": "TypeScript/React library for AI Chat",
5
5
  "keywords": [
6
6
  "radix-ui",
@@ -49,9 +49,9 @@
49
49
  ],
50
50
  "sideEffects": false,
51
51
  "dependencies": {
52
- "assistant-cloud": "^0.1.13",
53
- "@assistant-ui/tap": "^0.4.0",
54
- "@assistant-ui/store": "^0.1.0",
52
+ "assistant-cloud": "^0.1.15",
53
+ "@assistant-ui/tap": "^0.4.2",
54
+ "@assistant-ui/store": "^0.1.2",
55
55
  "@radix-ui/primitive": "^1.1.3",
56
56
  "@radix-ui/react-compose-refs": "^1.1.2",
57
57
  "@radix-ui/react-context": "^1.1.3",
@@ -61,10 +61,10 @@
61
61
  "@radix-ui/react-slot": "^1.2.4",
62
62
  "@radix-ui/react-use-callback-ref": "^1.1.1",
63
63
  "@radix-ui/react-use-escape-keydown": "^1.1.1",
64
- "assistant-stream": "^0.2.47",
64
+ "assistant-stream": "^0.3.0",
65
65
  "nanoid": "^5.1.6",
66
66
  "react-textarea-autosize": "^8.5.9",
67
- "zod": "^4.3.5",
67
+ "zod": "^4.3.6",
68
68
  "zustand": "^5.0.10"
69
69
  },
70
70
  "peerDependencies": {
@@ -83,12 +83,12 @@
83
83
  },
84
84
  "devDependencies": {
85
85
  "@types/json-schema": "^7.0.15",
86
- "@types/node": "^25.0.9",
86
+ "@types/node": "^25.0.10",
87
87
  "@types/react": "^19.2.9",
88
88
  "@types/react-dom": "^19.2.3",
89
- "react": "^19.2.3",
90
- "react-dom": "^19.2.3",
91
- "vitest": "^4.0.17",
89
+ "react": "^19.2.4",
90
+ "react-dom": "^19.2.4",
91
+ "vitest": "^4.0.18",
92
92
  "@assistant-ui/x-buildutils": "0.0.1"
93
93
  },
94
94
  "publishConfig": {
@@ -0,0 +1,74 @@
1
+ import { resource, tapState, withKey } from "@assistant-ui/tap";
2
+ import { type ClientOutput, tapClientLookup } from "@assistant-ui/store";
3
+ import type { SuggestionsState, SuggestionState } from "../types/scopes";
4
+
5
+ export type SuggestionConfig =
6
+ | string
7
+ | { title: string; label: string; prompt: string };
8
+
9
+ const SuggestionClient = resource(
10
+ (state: SuggestionState): ClientOutput<"suggestion"> => {
11
+ return {
12
+ state,
13
+ methods: {
14
+ getState: () => state,
15
+ },
16
+ };
17
+ },
18
+ );
19
+
20
+ const SuggestionsResource = resource(
21
+ (suggestions?: SuggestionConfig[]): ClientOutput<"suggestions"> => {
22
+ const [state] = tapState<SuggestionsState>(() => {
23
+ const normalizedSuggestions = (suggestions ?? []).map((s) => {
24
+ if (typeof s === "string") {
25
+ return {
26
+ title: s,
27
+ label: "",
28
+ prompt: s,
29
+ };
30
+ }
31
+ return {
32
+ title: s.title,
33
+ label: s.label,
34
+ prompt: s.prompt,
35
+ };
36
+ });
37
+
38
+ return {
39
+ suggestions: normalizedSuggestions,
40
+ };
41
+ });
42
+
43
+ const suggestionClients = tapClientLookup(
44
+ () =>
45
+ state.suggestions.map((suggestion, index) =>
46
+ withKey(index, SuggestionClient(suggestion)),
47
+ ),
48
+ [state.suggestions],
49
+ );
50
+
51
+ return {
52
+ state,
53
+ methods: {
54
+ getState: () => state,
55
+ suggestion: ({ index }: { index: number }) => {
56
+ return suggestionClients.get({ index });
57
+ },
58
+ },
59
+ };
60
+ },
61
+ );
62
+
63
+ export const Suggestions: {
64
+ (): import("@assistant-ui/tap").ResourceElement<
65
+ ClientOutput<"suggestions">,
66
+ undefined
67
+ >;
68
+ (
69
+ suggestions: SuggestionConfig[],
70
+ ): import("@assistant-ui/tap").ResourceElement<
71
+ ClientOutput<"suggestions">,
72
+ SuggestionConfig[]
73
+ >;
74
+ } = SuggestionsResource as any;
@@ -1,9 +1,14 @@
1
1
  import { resource, tapState, tapEffect, tapCallback } from "@assistant-ui/tap";
2
- import { tapAssistantClientRef, type ClientOutput } from "@assistant-ui/store";
2
+ import {
3
+ tapAssistantClientRef,
4
+ type ClientOutput,
5
+ attachDefaultPeers,
6
+ } from "@assistant-ui/store";
3
7
  import { ToolsState } from "../types/scopes";
4
8
  import type { Tool } from "assistant-stream";
5
9
  import { type Toolkit } from "../model-context/toolbox";
6
10
  import { ToolCallMessagePartComponent } from "../types";
11
+ import { ModelContext } from "./ModelContextClient";
7
12
 
8
13
  export const Tools = resource(
9
14
  ({ toolkit }: { toolkit?: Toolkit }): ClientOutput<"tools"> => {
@@ -86,3 +91,7 @@ export const Tools = resource(
86
91
  };
87
92
  },
88
93
  );
94
+
95
+ attachDefaultPeers(Tools, {
96
+ modelContext: ModelContext(),
97
+ });
@@ -0,0 +1,23 @@
1
+ "use client";
2
+
3
+ import { type FC, type PropsWithChildren } from "react";
4
+ import { AuiProvider, Derived, useAui } from "@assistant-ui/store";
5
+
6
+ export type SuggestionByIndexProviderProps = PropsWithChildren<{
7
+ index: number;
8
+ }>;
9
+
10
+ export const SuggestionByIndexProvider: FC<SuggestionByIndexProviderProps> = ({
11
+ index,
12
+ children,
13
+ }) => {
14
+ const aui = useAui({
15
+ suggestion: Derived({
16
+ source: "suggestions",
17
+ query: { index },
18
+ get: (aui) => aui.suggestions().suggestion({ index }),
19
+ }),
20
+ });
21
+
22
+ return <AuiProvider value={aui}>{children}</AuiProvider>;
23
+ };
@@ -2,6 +2,8 @@
2
2
 
3
3
  import { type FC, type PropsWithChildren } from "react";
4
4
  import { useAui, AuiProvider, Derived } from "@assistant-ui/store";
5
+ import type { ThreadListItemRuntime } from "../../legacy-runtime/runtime/ThreadListItemRuntime";
6
+ import { ThreadListItemClient } from "../../legacy-runtime/client/ThreadListItemRuntimeClient";
5
7
 
6
8
  export const ThreadListItemByIndexProvider: FC<
7
9
  PropsWithChildren<{
@@ -20,17 +22,13 @@ export const ThreadListItemByIndexProvider: FC<
20
22
  return <AuiProvider value={aui}>{children}</AuiProvider>;
21
23
  };
22
24
 
23
- export const ThreadListItemByIdProvider: FC<
25
+ export const ThreadListItemRuntimeProvider: FC<
24
26
  PropsWithChildren<{
25
- id: string;
27
+ runtime: ThreadListItemRuntime;
26
28
  }>
27
- > = ({ id, children }) => {
29
+ > = ({ runtime, children }) => {
28
30
  const aui = useAui({
29
- threadListItem: Derived({
30
- source: "threads",
31
- query: { type: "id", id },
32
- get: (aui) => aui.threads().item({ id }),
33
- }),
31
+ threadListItem: ThreadListItemClient({ runtime }),
34
32
  });
35
33
 
36
34
  return <AuiProvider value={aui}>{children}</AuiProvider>;
@@ -1,9 +1,10 @@
1
1
  export { AssistantRuntimeProvider } from "../../legacy-runtime/AssistantRuntimeProvider";
2
2
  export {
3
3
  ThreadListItemByIndexProvider,
4
- ThreadListItemByIdProvider,
4
+ ThreadListItemRuntimeProvider,
5
5
  } from "./ThreadListItemProvider";
6
6
  export { MessageByIndexProvider } from "./MessageByIndexProvider";
7
+ export { SuggestionByIndexProvider } from "./SuggestionByIndexProvider";
7
8
  export { PartByIndexProvider } from "./PartByIndexProvider";
8
9
  export {
9
10
  MessageAttachmentByIndexProvider,
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { FC, memo, PropsWithChildren } from "react";
4
- import { useAui, AuiProvider } from "@assistant-ui/store";
4
+ import { useAui, AuiProvider, AssistantClient } from "@assistant-ui/store";
5
5
  import { AssistantRuntime } from "./runtime/AssistantRuntime";
6
6
  import { AssistantRuntimeCore } from "./runtime-cores/core/AssistantRuntimeCore";
7
7
  import { RuntimeAdapter } from "./RuntimeAdapter";
@@ -13,6 +13,11 @@ export namespace AssistantRuntimeProvider {
13
13
  * The runtime to provide to the rest of your app.
14
14
  */
15
15
  runtime: AssistantRuntime;
16
+
17
+ /**
18
+ * The aui instance to extend. If not provided, a new aui instance will be created.
19
+ */
20
+ aui?: AssistantClient;
16
21
  }>;
17
22
  }
18
23
 
@@ -22,10 +27,8 @@ const getRenderComponent = (runtime: AssistantRuntime) => {
22
27
 
23
28
  export const AssistantRuntimeProviderImpl: FC<
24
29
  AssistantRuntimeProvider.Props
25
- > = ({ children, runtime }) => {
26
- const aui = useAui({
27
- threads: RuntimeAdapter(runtime),
28
- });
30
+ > = ({ children, aui: parent = null, runtime }) => {
31
+ const aui = useAui({ threads: RuntimeAdapter(runtime) }, { parent: parent });
29
32
 
30
33
  const RenderComponent = getRenderComponent(runtime);
31
34
 
@@ -7,7 +7,7 @@ import {
7
7
  attachDefaultPeers,
8
8
  } from "@assistant-ui/store";
9
9
  import { ModelContext } from "../client/ModelContextClient";
10
- import { Tools } from "../model-context";
10
+ import { Tools, Suggestions } from "../model-context";
11
11
 
12
12
  export const RuntimeAdapter = resource((runtime: AssistantRuntime) => {
13
13
  const clientRef = tapAssistantClientRef();
@@ -29,6 +29,7 @@ export const RuntimeAdapter = resource((runtime: AssistantRuntime) => {
29
29
  attachDefaultPeers(RuntimeAdapter, {
30
30
  modelContext: ModelContext(),
31
31
  tools: Tools({}),
32
+ suggestions: Suggestions(),
32
33
  threadListItem: Derived({
33
34
  source: "threads",
34
35
  query: { type: "main" },
@@ -57,10 +57,10 @@ export const ThreadListClient = resource(
57
57
  const state = tapMemo<ThreadsState>(() => {
58
58
  return {
59
59
  mainThreadId: runtimeState.mainThreadId,
60
- newThreadId: runtimeState.newThread ?? null,
60
+ newThreadId: runtimeState.newThreadId ?? null,
61
61
  isLoading: runtimeState.isLoading,
62
- threadIds: runtimeState.threads,
63
- archivedThreadIds: runtimeState.archivedThreads,
62
+ threadIds: runtimeState.threadIds,
63
+ archivedThreadIds: runtimeState.archivedThreadIds,
64
64
  threadItems: threadItems.state,
65
65
 
66
66
  main: main.state,
@@ -64,10 +64,6 @@ export type ThreadListItemState = {
64
64
  readonly id: string;
65
65
  readonly remoteId: string | undefined;
66
66
  readonly externalId: string | undefined;
67
- /**
68
- * @deprecated Use `id` instead. This field will be removed in version 0.12.0.
69
- */
70
- readonly threadId: string;
71
67
  readonly status: ThreadListItemStatus;
72
68
  readonly title?: string | undefined;
73
69
  };
@@ -18,9 +18,9 @@ import { NestedSubscriptionSubject } from "./subscribable/NestedSubscriptionSubj
18
18
 
19
19
  export type ThreadListState = {
20
20
  readonly mainThreadId: string;
21
- readonly newThread: string | undefined;
22
- readonly threads: readonly string[];
23
- readonly archivedThreads: readonly string[];
21
+ readonly newThreadId: string | undefined;
22
+ readonly threadIds: readonly string[];
23
+ readonly archivedThreadIds: readonly string[];
24
24
  readonly isLoading: boolean;
25
25
  readonly threadItems: Readonly<
26
26
  Record<string, Omit<ThreadListItemState, "isMain" | "threadId">>
@@ -49,11 +49,11 @@ const getThreadListState = (
49
49
  ): ThreadListState => {
50
50
  return {
51
51
  mainThreadId: threadList.mainThreadId,
52
- newThread: threadList.newThreadId,
53
- threads: threadList.threadIds,
54
- archivedThreads: threadList.archivedThreadIds,
52
+ newThreadId: threadList.newThreadId,
53
+ threadIds: threadList.threadIds,
54
+ archivedThreadIds: threadList.archivedThreadIds,
55
55
  isLoading: threadList.isLoading,
56
- threadItems: threadList.threadData,
56
+ threadItems: threadList.threadItems,
57
57
  };
58
58
  };
59
59
 
@@ -67,7 +67,6 @@ const getThreadListItemState = (
67
67
  if (!threadData) return SKIP_UPDATE;
68
68
  return {
69
69
  id: threadData.id,
70
- threadId: threadData.id, // TODO remove in 0.12.0
71
70
  remoteId: threadData.remoteId,
72
71
  externalId: threadData.externalId,
73
72
  title: threadData.title,
@@ -15,6 +15,7 @@ import {
15
15
  DataStreamDecoder,
16
16
  AssistantTransportDecoder,
17
17
  unstable_createInitialMessage as createInitialMessage,
18
+ toToolsJSONSchema,
18
19
  } from "assistant-stream";
19
20
  import {
20
21
  AssistantTransportOptions,
@@ -28,7 +29,7 @@ import { useCommandQueue } from "./commandQueue";
28
29
  import { useRunManager } from "./runManager";
29
30
  import { useConvertedState } from "./useConvertedState";
30
31
  import { ToolExecutionStatus, useToolInvocations } from "./useToolInvocations";
31
- import { toAISDKTools, getEnabledTools, createRequestHeaders } from "./utils";
32
+ import { createRequestHeaders } from "./utils";
32
33
  import { useRemoteThreadListRuntime } from "../remote-thread-list/useRemoteThreadListRuntime";
33
34
  import { InMemoryThreadListAdapter } from "../remote-thread-list/adapter/in-memory";
34
35
  import { useAui, useAuiState } from "@assistant-ui/store";
@@ -115,9 +116,7 @@ const useAssistantTransportThreadRuntime = <T,>(
115
116
  commands,
116
117
  state: agentStateRef.current,
117
118
  system: context.system,
118
- tools: context.tools
119
- ? toAISDKTools(getEnabledTools(context.tools))
120
- : undefined,
119
+ tools: context.tools ? toToolsJSONSchema(context.tools) : undefined,
121
120
  threadId,
122
121
  ...(parentIdRef.current !== undefined && {
123
122
  parentId: parentIdRef.current,
@@ -1,42 +1,37 @@
1
- import { Tool } from "assistant-stream";
2
- import type { JSONSchema7 } from "json-schema";
3
- import { z } from "zod";
1
+ import { Tool, toToolsJSONSchema, type ToolJSONSchema } from "assistant-stream";
4
2
 
5
- // Convert tools to AI SDK format
6
- export const toAISDKTools = (tools: Record<string, Tool>) => {
7
- return Object.fromEntries(
8
- Object.entries(tools).map(([name, tool]) => [
9
- name,
10
- {
11
- ...(tool.description ? { description: tool.description } : undefined),
12
- parameters: (tool.parameters instanceof z.ZodType
13
- ? z.toJSONSchema(tool.parameters)
14
- : tool.parameters) as JSONSchema7,
15
- },
16
- ]),
17
- );
18
- };
3
+ /**
4
+ * @deprecated Use `toToolsJSONSchema` from `assistant-stream` instead.
5
+ */
6
+ export function toAISDKTools(
7
+ tools: Record<string, Tool>,
8
+ ): Record<string, ToolJSONSchema> {
9
+ return toToolsJSONSchema(tools, { filter: () => true });
10
+ }
19
11
 
20
- // Filter enabled tools
21
- export const getEnabledTools = (tools: Record<string, Tool>) => {
12
+ /**
13
+ * @deprecated Use `toToolsJSONSchema` from `assistant-stream` instead, which includes filtering by default.
14
+ */
15
+ export function getEnabledTools(
16
+ tools: Record<string, Tool>,
17
+ ): Record<string, Tool> {
22
18
  return Object.fromEntries(
23
19
  Object.entries(tools).filter(
24
20
  ([, tool]) => !tool.disabled && tool.type !== "backend",
25
21
  ),
26
22
  );
27
- };
23
+ }
28
24
 
29
- // Create headers for fetch request
30
- export const createRequestHeaders = async (
25
+ export async function createRequestHeaders(
31
26
  headersValue:
32
27
  | Record<string, string>
33
28
  | Headers
34
29
  | (() => Promise<Record<string, string> | Headers>),
35
- ): Promise<Headers> => {
30
+ ): Promise<Headers> {
36
31
  const resolvedHeaders =
37
32
  typeof headersValue === "function" ? await headersValue() : headersValue;
38
33
 
39
34
  const headers = new Headers(resolvedHeaders);
40
35
  headers.set("Content-Type", "application/json");
41
36
  return headers;
42
- };
37
+ }
@@ -21,7 +21,7 @@ export type ThreadListRuntimeCore = {
21
21
  threadIds: readonly string[];
22
22
  archivedThreadIds: readonly string[];
23
23
 
24
- readonly threadData: Readonly<Record<string, ThreadListItemCoreState>>;
24
+ readonly threadItems: Readonly<Record<string, ThreadListItemCoreState>>;
25
25
 
26
26
  getMainThreadRuntimeCore(): ThreadRuntimeCore;
27
27
  getThreadRuntimeCore(threadId: string): ThreadRuntimeCore;
@@ -47,7 +47,7 @@ export class ExternalStoreThreadListRuntimeCore
47
47
  return this._archivedThreads;
48
48
  }
49
49
 
50
- public get threadData() {
50
+ public get threadItems() {
51
51
  return this._threadData;
52
52
  }
53
53
 
@@ -11,6 +11,8 @@ import { getAutoStatus, isAutoStatus } from "./auto-status";
11
11
  import { ThreadMessage, ToolCallMessagePart } from "../../../types";
12
12
  import { ToolExecutionStatus } from "../assistant-transport/useToolInvocations";
13
13
  import { ReadonlyJSONValue } from "assistant-stream/utils";
14
+ import { generateErrorMessageId } from "../../../utils/idUtils";
15
+ import { ThreadAssistantMessage } from "../../../types/AssistantTypes";
14
16
 
15
17
  export namespace useExternalMessageConverter {
16
18
  export type Message =
@@ -262,6 +264,28 @@ const chunkExternalMessages = <T,>(
262
264
  return results;
263
265
  };
264
266
 
267
+ function createErrorAssistantMessage(
268
+ error: ReadonlyJSONValue,
269
+ ): ThreadAssistantMessage {
270
+ return Object.assign<ThreadAssistantMessage, { [symbolInnerMessage]: [] }>(
271
+ {
272
+ id: generateErrorMessageId(),
273
+ role: "assistant",
274
+ content: [],
275
+ status: { type: "incomplete", reason: "error", error },
276
+ createdAt: new Date(),
277
+ metadata: {
278
+ unstable_state: null,
279
+ unstable_annotations: [],
280
+ unstable_data: [],
281
+ custom: {},
282
+ steps: [],
283
+ },
284
+ },
285
+ { [symbolInnerMessage]: [] },
286
+ );
287
+ }
288
+
265
289
  export const convertExternalMessages = <T extends WeakKey>(
266
290
  messages: T[],
267
291
  callback: useExternalMessageConverter.Callback<T>,
@@ -278,14 +302,9 @@ export const convertExternalMessages = <T extends WeakKey>(
278
302
 
279
303
  const chunks = chunkExternalMessages(callbackResults);
280
304
 
281
- return chunks.map((message, idx) => {
305
+ const result = chunks.map((message, idx) => {
282
306
  const isLast = idx === chunks.length - 1;
283
307
  const joined = joinExternalMessages(message.outputs);
284
- const hasSuspendedToolCalls =
285
- typeof joined.content === "object" &&
286
- joined.content.some(
287
- (c) => c.type === "tool-call" && c.result === undefined,
288
- );
289
308
  const hasPendingToolCalls =
290
309
  typeof joined.content === "object" &&
291
310
  joined.content.some(
@@ -294,7 +313,7 @@ export const convertExternalMessages = <T extends WeakKey>(
294
313
  const autoStatus = getAutoStatus(
295
314
  isLast,
296
315
  isRunning,
297
- hasSuspendedToolCalls,
316
+ hasPendingToolCalls,
298
317
  hasPendingToolCalls,
299
318
  isLast ? metadata.error : undefined,
300
319
  );
@@ -306,6 +325,15 @@ export const convertExternalMessages = <T extends WeakKey>(
306
325
  (newMessage as any)[symbolInnerMessage] = message.inputs;
307
326
  return newMessage;
308
327
  });
328
+
329
+ if (metadata.error) {
330
+ const lastMessage = result.at(-1);
331
+ if (!lastMessage || lastMessage.role !== "assistant") {
332
+ result.push(createErrorAssistantMessage(metadata.error));
333
+ }
334
+ }
335
+
336
+ return result;
309
337
  };
310
338
 
311
339
  export const useExternalMessageConverter = <T extends WeakKey>({
@@ -411,6 +439,13 @@ export const useExternalMessageConverter = <T extends WeakKey>({
411
439
  symbolInnerMessage
412
440
  ] = messages;
413
441
 
442
+ if (state.metadata.error) {
443
+ const lastMessage = threadMessages.at(-1);
444
+ if (!lastMessage || lastMessage.role !== "assistant") {
445
+ threadMessages.push(createErrorAssistantMessage(state.metadata.error));
446
+ }
447
+ }
448
+
414
449
  return threadMessages;
415
450
  }, [state, messages, isRunning, joinStrategy]);
416
451
  };
@@ -50,7 +50,7 @@ export class LocalThreadListRuntimeCore
50
50
  return DEFAULT_THREAD_ID;
51
51
  }
52
52
 
53
- public get threadData() {
53
+ public get threadItems() {
54
54
  return DEFAULT_THREAD_DATA;
55
55
  }
56
56
 
@@ -31,6 +31,9 @@ export class BaseSubscribable {
31
31
  if (errors.length === 1) {
32
32
  throw errors[0];
33
33
  } else {
34
+ for (const error of errors) {
35
+ console.error(error);
36
+ }
34
37
  throw new AggregateError(errors);
35
38
  }
36
39
  }
@@ -8,13 +8,19 @@ import {
8
8
  memo,
9
9
  PropsWithChildren,
10
10
  ComponentType,
11
+ useMemo,
11
12
  } from "react";
12
13
  import { UseBoundStore, StoreApi, create } from "zustand";
13
14
  import { useAui } from "@assistant-ui/store";
14
- import { ThreadListItemByIdProvider } from "../../../context/providers";
15
- import { ThreadRuntimeCore, ThreadRuntimeImpl } from "../../../internal";
15
+ import { ThreadListItemRuntimeProvider } from "../../../context/providers";
16
+ import {
17
+ ThreadListRuntimeCore,
18
+ ThreadRuntimeCore,
19
+ ThreadRuntimeImpl,
20
+ } from "../../../internal";
16
21
  import { BaseSubscribable } from "./BaseSubscribable";
17
22
  import { AssistantRuntime } from "../../runtime";
23
+ import { ThreadListRuntimeImpl } from "../../runtime/ThreadListRuntime";
18
24
 
19
25
  type RemoteThreadListHook = () => AssistantRuntime;
20
26
 
@@ -27,9 +33,14 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
27
33
  >;
28
34
  private instances = new Map<string, RemoteThreadListHookInstance>();
29
35
  private useAliveThreadsKeysChanged = create(() => ({}));
36
+ private parent: ThreadListRuntimeCore;
30
37
 
31
- constructor(runtimeHook: RemoteThreadListHook) {
38
+ constructor(
39
+ runtimeHook: RemoteThreadListHook,
40
+ parent: ThreadListRuntimeCore,
41
+ ) {
32
42
  super();
43
+ this.parent = parent;
33
44
  this.useRuntimeHook = create(() => ({ useRuntime: runtimeHook }));
34
45
  }
35
46
 
@@ -139,14 +150,17 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
139
150
  threadId: string;
140
151
  provider: ComponentType<PropsWithChildren>;
141
152
  }> = memo(({ threadId, provider: Provider }) => {
142
- // Runtime is provided by ThreadListItemByIdProvider
153
+ const runtime = useMemo(
154
+ () => new ThreadListRuntimeImpl(this.parent).getItemById(threadId),
155
+ [threadId],
156
+ );
143
157
 
144
158
  return (
145
- <ThreadListItemByIdProvider id={threadId}>
159
+ <ThreadListItemRuntimeProvider runtime={runtime}>
146
160
  <Provider>
147
161
  <this._InnerActiveThreadProvider threadId={threadId} />
148
162
  </Provider>
149
- </ThreadListItemByIdProvider>
163
+ </ThreadListItemRuntimeProvider>
150
164
  );
151
165
  });
152
166
 
@@ -156,7 +156,7 @@ export class RemoteThreadListThreadListRuntimeCore
156
156
  threadData: {},
157
157
  });
158
158
 
159
- public get threadData() {
159
+ public get threadItems() {
160
160
  return this._state.value.threadData;
161
161
  }
162
162
 
@@ -240,12 +240,12 @@ export class RemoteThreadListThreadListRuntimeCore
240
240
  this._state.subscribe(() => this._notifySubscribers());
241
241
  this._hookManager = new RemoteThreadListHookInstanceManager(
242
242
  options.runtimeHook,
243
+ this,
243
244
  );
244
245
  this.useProvider = create(() => ({
245
246
  Provider: options.adapter.unstable_Provider ?? Fragment,
246
247
  }));
247
248
  this.__internal_setOptions(options);
248
-
249
249
  this.switchToNewThread();
250
250
  }
251
251
 
@@ -23,5 +23,7 @@ export type { Toolkit, ToolDefinition } from "./toolbox";
23
23
 
24
24
  export { Tools } from "../client/Tools";
25
25
 
26
+ export { Suggestions, type SuggestionConfig } from "../client/Suggestions";
27
+
26
28
  export * from "./registry";
27
29
  export * from "./frame";