@assistant-ui/react 0.11.38 → 0.11.39

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 (113) hide show
  1. package/dist/client/AssistantClient.d.ts.map +1 -1
  2. package/dist/client/AssistantClient.js +14 -30
  3. package/dist/client/AssistantClient.js.map +1 -1
  4. package/dist/client/ModelContextClient.d.ts +1 -1
  5. package/dist/client/NoOpComposerClient.d.ts +1 -1
  6. package/dist/client/ThreadMessageClient.d.ts +1 -1
  7. package/dist/client/Tools.d.ts +1 -1
  8. package/dist/client/Tools.d.ts.map +1 -1
  9. package/dist/client/Tools.js +29 -18
  10. package/dist/client/Tools.js.map +1 -1
  11. package/dist/client/types/Tools.d.ts +6 -1
  12. package/dist/client/types/Tools.d.ts.map +1 -1
  13. package/dist/context/react/AssistantApiContext.d.ts +2 -4
  14. package/dist/context/react/AssistantApiContext.d.ts.map +1 -1
  15. package/dist/context/react/AssistantApiContext.js +0 -7
  16. package/dist/context/react/AssistantApiContext.js.map +1 -1
  17. package/dist/context/react/hooks/useAssistantState.js +2 -2
  18. package/dist/context/react/hooks/useAssistantState.js.map +1 -1
  19. package/dist/legacy-runtime/RuntimeAdapter.d.ts +1 -1
  20. package/dist/legacy-runtime/client/AttachmentRuntimeClient.d.ts +1 -1
  21. package/dist/legacy-runtime/client/ComposerRuntimeClient.d.ts +1 -1
  22. package/dist/legacy-runtime/client/EventManagerRuntimeClient.d.ts +1 -1
  23. package/dist/legacy-runtime/client/MessagePartRuntimeClient.d.ts +1 -1
  24. package/dist/legacy-runtime/client/MessageRuntimeClient.d.ts +1 -1
  25. package/dist/legacy-runtime/client/ThreadListItemRuntimeClient.d.ts +1 -1
  26. package/dist/legacy-runtime/client/ThreadListRuntimeClient.d.ts +1 -1
  27. package/dist/legacy-runtime/client/ThreadRuntimeClient.d.ts +1 -1
  28. package/dist/legacy-runtime/cloud/auiV0.js.map +1 -1
  29. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.d.ts +2 -2
  30. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.d.ts.map +1 -1
  31. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.js +2 -0
  32. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.js.map +1 -1
  33. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.d.ts.map +1 -1
  34. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.js +7 -4
  35. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.js.map +1 -1
  36. package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.d.ts +7 -2
  37. package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.d.ts.map +1 -1
  38. package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.js +17 -3
  39. package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.js.map +1 -1
  40. package/dist/model-context/index.d.ts +1 -1
  41. package/dist/model-context/index.d.ts.map +1 -1
  42. package/dist/model-context/index.js +0 -4
  43. package/dist/model-context/index.js.map +1 -1
  44. package/dist/model-context/makeAssistantVisible.d.ts.map +1 -1
  45. package/dist/model-context/makeAssistantVisible.js +21 -8
  46. package/dist/model-context/makeAssistantVisible.js.map +1 -1
  47. package/dist/model-context/toolbox.d.ts +1 -19
  48. package/dist/model-context/toolbox.d.ts.map +1 -1
  49. package/dist/model-context/toolbox.js +0 -13
  50. package/dist/model-context/toolbox.js.map +1 -1
  51. package/dist/model-context/useAssistantTool.js +1 -1
  52. package/dist/model-context/useAssistantTool.js.map +1 -1
  53. package/dist/model-context/useAssistantToolUI.js +1 -1
  54. package/dist/model-context/useAssistantToolUI.js.map +1 -1
  55. package/dist/primitives/index.d.ts +1 -0
  56. package/dist/primitives/index.d.ts.map +1 -1
  57. package/dist/primitives/index.js +2 -0
  58. package/dist/primitives/index.js.map +1 -1
  59. package/dist/primitives/message/MessageParts.d.ts.map +1 -1
  60. package/dist/primitives/message/MessageParts.js +4 -2
  61. package/dist/primitives/message/MessageParts.js.map +1 -1
  62. package/dist/primitives/message/MessagePartsGrouped.d.ts.map +1 -1
  63. package/dist/primitives/message/MessagePartsGrouped.js +4 -2
  64. package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
  65. package/dist/primitives/messagePart/useMessagePartData.d.ts +3 -0
  66. package/dist/primitives/messagePart/useMessagePartData.d.ts.map +1 -0
  67. package/dist/primitives/messagePart/useMessagePartData.js +23 -0
  68. package/dist/primitives/messagePart/useMessagePartData.js.map +1 -0
  69. package/dist/types/AssistantTypes.d.ts +2 -2
  70. package/dist/types/AssistantTypes.d.ts.map +1 -1
  71. package/dist/types/MessagePartTypes.d.ts +6 -1
  72. package/dist/types/MessagePartTypes.d.ts.map +1 -1
  73. package/dist/types/index.d.ts +1 -1
  74. package/dist/types/index.d.ts.map +1 -1
  75. package/dist/utils/tap-store/derived-scopes.d.ts +1 -1
  76. package/dist/utils/tap-store/derived-scopes.d.ts.map +1 -1
  77. package/package.json +2 -2
  78. package/src/client/AssistantClient.ts +14 -33
  79. package/src/client/Tools.ts +31 -22
  80. package/src/client/types/Tools.ts +11 -2
  81. package/src/context/react/AssistantApiContext.tsx +2 -11
  82. package/src/context/react/hooks/useAssistantState.tsx +2 -2
  83. package/src/legacy-runtime/cloud/auiV0.ts +1 -1
  84. package/src/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.tsx +10 -1
  85. package/src/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.tsx +7 -3
  86. package/src/legacy-runtime/runtime-cores/utils/MessageRepository.tsx +27 -3
  87. package/src/model-context/index.ts +1 -6
  88. package/src/model-context/makeAssistantVisible.tsx +23 -12
  89. package/src/model-context/toolbox.tsx +1 -21
  90. package/src/model-context/useAssistantTool.tsx +1 -1
  91. package/src/model-context/useAssistantToolUI.tsx +1 -1
  92. package/src/primitives/index.ts +1 -0
  93. package/src/primitives/message/MessageParts.tsx +5 -3
  94. package/src/primitives/message/MessagePartsGrouped.tsx +5 -3
  95. package/src/primitives/messagePart/useMessagePartData.tsx +24 -0
  96. package/src/types/AssistantTypes.ts +2 -0
  97. package/src/types/MessagePartTypes.ts +8 -1
  98. package/src/types/index.ts +1 -0
  99. package/dist/client/ToolUIClient.d.ts +0 -7
  100. package/dist/client/ToolUIClient.d.ts.map +0 -1
  101. package/dist/client/ToolUIClient.js +0 -71
  102. package/dist/client/ToolUIClient.js.map +0 -1
  103. package/dist/client/ToolUIContext.d.ts +0 -4
  104. package/dist/client/ToolUIContext.d.ts.map +0 -1
  105. package/dist/client/ToolUIContext.js +0 -20
  106. package/dist/client/ToolUIContext.js.map +0 -1
  107. package/dist/client/types/ToolUI.d.ts +0 -23
  108. package/dist/client/types/ToolUI.d.ts.map +0 -1
  109. package/dist/client/types/ToolUI.js +0 -1
  110. package/dist/client/types/ToolUI.js.map +0 -1
  111. package/src/client/ToolUIClient.ts +0 -76
  112. package/src/client/ToolUIContext.ts +0 -22
  113. package/src/client/types/ToolUI.ts +0 -27
@@ -24,18 +24,14 @@ import {
24
24
  useAssistantApiImpl,
25
25
  extendApi,
26
26
  } from "../context/react/AssistantApiContext";
27
- import { ToolUIClient } from "./ToolUIClient";
28
27
  import { withEventsProvider } from "./EventContext";
29
28
  import { withModelContextProvider } from "./ModelContext";
30
- import { withToolUIProvider } from "./ToolUIContext";
31
- import { ToolUIApi, ToolUIState } from "./types/ToolUI";
32
29
  import { ToolsApi, ToolsState } from "./types/Tools";
33
30
  import { ModelContextApi, ModelContextState } from "./types/ModelContext";
34
31
  import { ModelContext as ModelContextResource } from "./ModelContextClient";
35
32
 
36
33
  type AssistantClientState = {
37
34
  readonly threads: ThreadListClientState;
38
- readonly toolUIs: ToolUIState;
39
35
  readonly tools: ToolsState;
40
36
  readonly modelContext: ModelContextState;
41
37
  };
@@ -44,7 +40,6 @@ type AssistantClientApi = {
44
40
  getState(): AssistantClientState;
45
41
 
46
42
  readonly threads: ThreadListClientApi;
47
- readonly toolUIs: ToolUIApi;
48
43
  readonly tools: ToolsApi;
49
44
  readonly modelContext: ModelContextApi;
50
45
 
@@ -61,44 +56,35 @@ const AssistantStore = resource(
61
56
  tools: toolsEl,
62
57
  }: AssistantClientProps) => {
63
58
  const events = tapInlineResource(EventManager());
64
- const toolUIsResource = tapInlineResource(ToolUIClient());
65
59
 
66
- const { threads, toolUIs, tools, modelContext } = withEventsProvider(
67
- events,
68
- () => {
69
- const modelContextResource = tapResource(
70
- modelContextEl ?? ModelContextResource(),
71
- [modelContextEl],
72
- );
60
+ const { threads, tools, modelContext } = withEventsProvider(events, () => {
61
+ const modelContextResource = tapResource(
62
+ modelContextEl ?? ModelContextResource(),
63
+ [modelContextEl],
64
+ );
73
65
 
74
- return withModelContextProvider(modelContextResource.api, () => {
75
- return withToolUIProvider(toolUIsResource.api, () => {
76
- return {
77
- toolUIs: toolUIsResource,
78
- modelContext: modelContextResource,
79
- tools: tapResource(toolsEl ?? Tools({}), [toolsEl]),
80
- threads: tapResource(threadsEl, [threadsEl]),
81
- };
82
- });
83
- });
84
- },
85
- );
66
+ return withModelContextProvider(modelContextResource.api, () => {
67
+ return {
68
+ modelContext: modelContextResource,
69
+ tools: tapResource(toolsEl ?? Tools({}), [toolsEl]),
70
+ threads: tapResource(threadsEl, [threadsEl]),
71
+ };
72
+ });
73
+ });
86
74
 
87
75
  const state = tapMemo<AssistantClientState>(
88
76
  () => ({
89
77
  threads: threads.state,
90
- toolUIs: toolUIs.state,
91
78
  tools: tools.state,
92
79
  modelContext: modelContext.state,
93
80
  }),
94
- [threads.state, toolUIs.state, tools.state, modelContext.state],
81
+ [threads.state, tools.state, modelContext.state],
95
82
  );
96
83
 
97
84
  return tapApi<AssistantClientApi>({
98
85
  getState: () => state,
99
86
 
100
87
  threads: threads.api,
101
- toolUIs: toolUIs.api,
102
88
  tools: tools.api,
103
89
  modelContext: modelContext.api,
104
90
  on: events.on,
@@ -116,11 +102,6 @@ const getClientFromStore = (client: Store<{ api: AssistantClientApi }>) => {
116
102
  query: {},
117
103
  get: () => client.getState().api.threads,
118
104
  }),
119
- toolUIs: createAssistantApiField({
120
- source: "root",
121
- query: {},
122
- get: () => client.getState().api.toolUIs,
123
- }),
124
105
  tools: createAssistantApiField({
125
106
  source: "root",
126
107
  query: {},
@@ -1,41 +1,25 @@
1
1
  import { resource, tapState, tapEffect } from "@assistant-ui/tap";
2
2
  import { tapApi } from "../utils/tap-store";
3
3
  import { tapModelContext } from "./ModelContext";
4
- import { tapToolUI } from "./ToolUIContext";
5
4
  import { ToolsState, ToolsApi } from "./types/Tools";
6
5
  import type { Tool } from "assistant-stream";
7
- import {
8
- type Toolkit,
9
- FallbackSymbol,
10
- LayoutSymbol,
11
- } from "../model-context/toolbox";
6
+ import { type Toolkit } from "../model-context/toolbox";
12
7
 
13
8
  export const Tools = resource(({ toolkit }: { toolkit?: Toolkit }) => {
14
- const [state] = tapState<ToolsState>(() => ({}));
9
+ const [state, setState] = tapState<ToolsState>(() => ({
10
+ tools: {},
11
+ }));
15
12
 
16
13
  const modelContext = tapModelContext();
17
- const toolUI = tapToolUI();
18
14
 
19
15
  tapEffect(() => {
20
16
  if (!toolkit) return;
21
17
  const unsubscribes: (() => void)[] = [];
22
18
 
23
- // Register fallback UI
24
- const fallback = toolkit[FallbackSymbol];
25
- if (fallback?.render) {
26
- unsubscribes.push(toolUI.setFallbackToolUI(fallback.render));
27
- }
28
-
29
- // Register layout
30
- const layout = toolkit[LayoutSymbol];
31
- if (layout?.render) {
32
- unsubscribes.push(toolUI.setToolUILayout(layout.render));
33
- }
34
-
35
19
  // Register tool UIs (exclude symbols)
36
20
  for (const [toolName, tool] of Object.entries(toolkit)) {
37
21
  if (tool.render) {
38
- unsubscribes.push(toolUI.setToolUI(toolName, tool.render));
22
+ unsubscribes.push(setToolUI(toolName, tool.render));
39
23
  }
40
24
  }
41
25
 
@@ -60,9 +44,34 @@ export const Tools = resource(({ toolkit }: { toolkit?: Toolkit }) => {
60
44
  return () => {
61
45
  unsubscribes.forEach((fn) => fn());
62
46
  };
63
- }, [toolkit, modelContext, toolUI]);
47
+ }, [toolkit, modelContext]);
48
+
49
+ const setToolUI = (toolName: string, render: any) => {
50
+ setState((prev) => {
51
+ return {
52
+ ...prev,
53
+ tools: {
54
+ ...prev.tools,
55
+ [toolName]: [...(prev.tools[toolName] ?? []), render],
56
+ },
57
+ };
58
+ });
59
+
60
+ return () => {
61
+ setState((prev) => {
62
+ return {
63
+ ...prev,
64
+ tools: {
65
+ ...prev.tools,
66
+ [toolName]: prev.tools[toolName]?.filter((r) => r !== render) ?? [],
67
+ },
68
+ };
69
+ });
70
+ };
71
+ };
64
72
 
65
73
  return tapApi<ToolsApi>({
66
74
  getState: () => state,
75
+ setToolUI,
67
76
  });
68
77
  });
@@ -1,8 +1,17 @@
1
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
2
- export type ToolsState = {};
1
+ import { Unsubscribe } from "@assistant-ui/tap";
2
+ import { ToolCallMessagePartComponent } from "../../types";
3
+
4
+ export type ToolsState = {
5
+ tools: Record<string, ToolCallMessagePartComponent[]>;
6
+ };
3
7
 
4
8
  export type ToolsApi = {
5
9
  getState(): ToolsState;
10
+
11
+ setToolUI(
12
+ toolName: string,
13
+ render: ToolCallMessagePartComponent,
14
+ ): Unsubscribe;
6
15
  };
7
16
 
8
17
  export type ToolsMeta = {
@@ -10,7 +10,6 @@ import {
10
10
  } from "react";
11
11
  import { useResource } from "@assistant-ui/tap/react";
12
12
 
13
- import { ToolUIApi, ToolUIState, ToolUIMeta } from "../../client/types/ToolUI";
14
13
  import {
15
14
  MessageClientApi,
16
15
  MessageClientState,
@@ -49,7 +48,7 @@ import {
49
48
  AssistantClientProps,
50
49
  useAssistantClient,
51
50
  } from "../../client/AssistantClient";
52
- import { ToolsApi, ToolsMeta } from "../../client/types/Tools";
51
+ import { ToolsApi, ToolsMeta, ToolsState } from "../../client/types/Tools";
53
52
  import {
54
53
  ModelContextApi,
55
54
  ModelContextMeta,
@@ -61,7 +60,7 @@ import {
61
60
 
62
61
  export type AssistantState = {
63
62
  readonly threads: ThreadListClientState;
64
- readonly toolUIs: ToolUIState;
63
+ readonly tools: ToolsState;
65
64
 
66
65
  readonly threadListItem: ThreadListItemClientState;
67
66
  readonly thread: ThreadClientState;
@@ -122,7 +121,6 @@ type AttachmentMeta = {
122
121
 
123
122
  export type AssistantApi = {
124
123
  threads: AssistantApiField<ThreadListClientApi, ThreadsMeta>;
125
- toolUIs: AssistantApiField<ToolUIApi, ToolUIMeta>;
126
124
  tools: AssistantApiField<ToolsApi, ToolsMeta>;
127
125
  modelContext: AssistantApiField<ModelContextApi, ModelContextMeta>;
128
126
  threadListItem: AssistantApiField<
@@ -168,13 +166,6 @@ const AssistantApiContext = createContext<AssistantApi>({
168
166
  throw new Error("Threads is only available inside <AssistantProvider />");
169
167
  },
170
168
  }),
171
- toolUIs: createAssistantApiField({
172
- source: null,
173
- query: {},
174
- get: (): never => {
175
- throw new Error("ToolUIs is only available inside <AssistantProvider />");
176
- },
177
- }),
178
169
  tools: createAssistantApiField({
179
170
  source: null,
180
171
  query: {},
@@ -15,8 +15,8 @@ class ProxiedAssistantState implements AssistantState {
15
15
  return this.#api.threads().getState();
16
16
  }
17
17
 
18
- get toolUIs() {
19
- return this.#api.toolUIs().getState();
18
+ get tools() {
19
+ return this.#api.tools().getState();
20
20
  }
21
21
 
22
22
  get threadListItem() {
@@ -112,7 +112,7 @@ export const auiV0Encode = (message: ThreadMessage): AuiV0Message => {
112
112
  }
113
113
 
114
114
  default: {
115
- const unhandledType: "image" | "file" | "audio" = type;
115
+ const unhandledType: "image" | "file" | "audio" | "data" = type;
116
116
  throw new Error(
117
117
  `Message part type not supported by aui/v0: ${unhandledType}`,
118
118
  );
@@ -12,6 +12,7 @@ import {
12
12
  ThreadSystemMessage,
13
13
  CompleteAttachment,
14
14
  FileMessagePart,
15
+ DataMessagePart,
15
16
  Unstable_AudioMessagePart,
16
17
  } from "../../../types";
17
18
  import {
@@ -31,6 +32,7 @@ export type ThreadMessageLike = {
31
32
  | SourceMessagePart
32
33
  | ImageMessagePart
33
34
  | FileMessagePart
35
+ | DataMessagePart
34
36
  | Unstable_AudioMessagePart
35
37
  | {
36
38
  readonly type: "tool-call";
@@ -123,6 +125,9 @@ export const fromThreadMessageLike = (
123
125
  case "image":
124
126
  return sanitizeImageContent(part);
125
127
 
128
+ case "data":
129
+ return part;
130
+
126
131
  case "tool-call": {
127
132
  const { parentId, messages, ...basePart } = part;
128
133
  const commonProps = {
@@ -182,7 +187,11 @@ export const fromThreadMessageLike = (
182
187
  return part;
183
188
 
184
189
  default: {
185
- const unhandledType: "tool-call" | "reasoning" | "source" = type;
190
+ const unhandledType:
191
+ | "tool-call"
192
+ | "reasoning"
193
+ | "source"
194
+ | "data" = type;
186
195
  throw new Error(
187
196
  `Unsupported user message part type: ${unhandledType}`,
188
197
  );
@@ -152,6 +152,7 @@ export class LocalThreadRuntimeCore
152
152
  this._options.adapters.history?.append({
153
153
  parentId: message.parentId,
154
154
  message: newMessage,
155
+ ...(message.runConfig !== undefined && { runConfig: message.runConfig }),
155
156
  });
156
157
 
157
158
  const startRun = message.startRun ?? message.role === "user";
@@ -183,8 +184,6 @@ export class LocalThreadRuntimeCore
183
184
  ): Promise<void> {
184
185
  this.ensureInitialized();
185
186
 
186
- this.repository.resetHead(parentId);
187
-
188
187
  // add assistant message
189
188
  const id = generateId();
190
189
  let message: ThreadAssistantMessage = {
@@ -254,7 +253,7 @@ export class LocalThreadRuntimeCore
254
253
  runConfig: RunConfig | undefined,
255
254
  runCallback?: ChatModelAdapter["run"],
256
255
  ) {
257
- const messages = this.repository.getMessages();
256
+ const messages = parentId ? this.repository.getMessages(parentId) : [];
258
257
 
259
258
  // abort existing run
260
259
  this.abortController?.abort();
@@ -327,6 +326,10 @@ export class LocalThreadRuntimeCore
327
326
  type: "running",
328
327
  },
329
328
  });
329
+
330
+ // Switch to the new message branch right after adding it for the first time
331
+ this.repository.resetHead(message.id);
332
+ this._notifySubscribers();
330
333
  }
331
334
 
332
335
  try {
@@ -401,6 +404,7 @@ export class LocalThreadRuntimeCore
401
404
  await this._options.adapters.history?.append({
402
405
  parentId,
403
406
  message: message,
407
+ runConfig: this._lastRunConfig,
404
408
  });
405
409
  }
406
410
  }
@@ -1,4 +1,5 @@
1
1
  import type { ThreadMessage } from "../../../types";
2
+ import { RunConfig } from "../../../types/AssistantTypes";
2
3
  import { generateId, generateOptimisticId } from "../../../utils/idUtils";
3
4
  import { ThreadMessageLike } from "../external-store";
4
5
  import { getAutoStatus } from "../external-store/auto-status";
@@ -34,6 +35,8 @@ export type ExportedMessageRepositoryItem = {
34
35
  message: ThreadMessage;
35
36
  /** ID of the parent message, or null for root messages */
36
37
  parentId: string | null;
38
+ /** The run configuration for the message */
39
+ runConfig?: RunConfig;
37
40
  };
38
41
 
39
42
  /**
@@ -46,6 +49,7 @@ export type ExportedMessageRepository = {
46
49
  messages: Array<{
47
50
  message: ThreadMessage;
48
51
  parentId: string | null;
52
+ runConfig?: RunConfig;
49
53
  }>;
50
54
  };
51
55
 
@@ -248,10 +252,30 @@ export class MessageRepository {
248
252
 
249
253
  /**
250
254
  * Gets all messages in the current active branch, from root to head.
251
- * @returns Array of messages in the current branch
255
+ * @param headId - Optional ID of the head message to get messages for. If not provided, uses the current head.
256
+ * @returns Array of messages in the specified branch
252
257
  */
253
- getMessages() {
254
- return this._messages.value;
258
+ getMessages(headId?: string) {
259
+ if (headId === undefined || headId === this.head?.current.id) {
260
+ return this._messages.value;
261
+ }
262
+
263
+ const headMessage = this.messages.get(headId);
264
+ if (!headMessage) {
265
+ throw new Error(
266
+ "MessageRepository(getMessages): Head message not found. This is likely an internal bug in assistant-ui.",
267
+ );
268
+ }
269
+
270
+ const messages = new Array<ThreadMessage>(headMessage.level + 1);
271
+ for (
272
+ let current: RepositoryMessage | null = headMessage;
273
+ current;
274
+ current = current.prev
275
+ ) {
276
+ messages[current.level] = current.current;
277
+ }
278
+ return messages;
255
279
  }
256
280
 
257
281
  /**
@@ -19,12 +19,7 @@ export { tool } from "./tool";
19
19
 
20
20
  export { makeAssistantVisible } from "./makeAssistantVisible";
21
21
 
22
- export {
23
- Toolkit,
24
- type ToolDefinition,
25
- type ToolkitFallback,
26
- type ToolkitLayout,
27
- } from "./toolbox";
22
+ export type { Toolkit, ToolDefinition } from "./toolbox";
28
23
 
29
24
  export { Tools } from "../client/Tools";
30
25
 
@@ -11,18 +11,21 @@ import {
11
11
  createContext,
12
12
  useContext,
13
13
  } from "react";
14
- import { z } from "zod";
15
14
  import { useAssistantApi } from "../context/react/AssistantApiContext";
16
15
  import { useComposedRefs } from "@radix-ui/react-compose-refs";
17
16
  import { tool } from "./tool";
18
17
 
19
- // TODO replace zod with json-schema so we can drop the zod dep
20
-
21
18
  const click = tool({
22
- parameters: z.object({
23
- clickId: z.string(),
24
- }),
25
- execute: async ({ clickId }) => {
19
+ parameters: {
20
+ type: "object",
21
+ properties: {
22
+ clickId: {
23
+ type: "string",
24
+ },
25
+ },
26
+ required: ["clickId"],
27
+ },
28
+ execute: async ({ clickId }: { clickId: string }) => {
26
29
  const escapedClickId = CSS.escape(clickId);
27
30
  const el = document.querySelector(`[data-click-id='${escapedClickId}']`);
28
31
  if (el instanceof HTMLElement) {
@@ -38,11 +41,19 @@ const click = tool({
38
41
  });
39
42
 
40
43
  const edit = tool({
41
- parameters: z.object({
42
- editId: z.string(),
43
- value: z.string(),
44
- }),
45
- execute: async ({ editId, value }) => {
44
+ parameters: {
45
+ type: "object",
46
+ properties: {
47
+ editId: {
48
+ type: "string",
49
+ },
50
+ value: {
51
+ type: "string",
52
+ },
53
+ },
54
+ required: ["editId", "value"],
55
+ },
56
+ execute: async ({ editId, value }: { editId: string; value: string }) => {
46
57
  const escapedEditId = CSS.escape(editId);
47
58
  const el = document.querySelector(`[data-edit-id='${escapedEditId}']`);
48
59
  if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
@@ -1,6 +1,5 @@
1
1
  "use client";
2
2
 
3
- import type { ComponentType, ReactNode } from "react";
4
3
  import type { Tool } from "assistant-stream";
5
4
  import type { ToolCallMessagePartComponent } from "../types/MessagePartComponentTypes";
6
5
 
@@ -11,26 +10,7 @@ export type ToolDefinition<
11
10
  render?: ToolCallMessagePartComponent<TArgs, TResult> | undefined;
12
11
  };
13
12
 
14
- export const FallbackSymbol = Symbol("Toolkit.Fallback");
15
- export const LayoutSymbol = Symbol("Toolkit.Layout");
16
-
17
- export type ToolkitFallback = {
18
- render: ToolCallMessagePartComponent<unknown, unknown>;
19
- };
20
-
21
- export type ToolkitLayout = {
22
- render: ComponentType<{ children: ReactNode }>;
23
- };
24
-
25
- export type Toolkit = Record<string, ToolDefinition<any, any>> & {
26
- [FallbackSymbol]?: ToolkitFallback;
27
- [LayoutSymbol]?: ToolkitLayout;
28
- };
29
-
30
- export const Toolkit = {
31
- Fallback: FallbackSymbol,
32
- Layout: LayoutSymbol,
33
- } as const;
13
+ export type Toolkit = Record<string, ToolDefinition<any, any>>;
34
14
 
35
15
  export type ToolsConfig = {
36
16
  toolkit: Toolkit;
@@ -23,7 +23,7 @@ export const useAssistantTool = <
23
23
 
24
24
  useEffect(() => {
25
25
  if (!tool.render) return undefined;
26
- return api.toolUIs().setToolUI(tool.toolName, tool.render);
26
+ return api.tools().setToolUI(tool.toolName, tool.render);
27
27
  }, [api, tool.toolName, tool.render]);
28
28
 
29
29
  useEffect(() => {
@@ -15,6 +15,6 @@ export const useAssistantToolUI = (
15
15
  const api = useAssistantApi();
16
16
  useEffect(() => {
17
17
  if (!tool?.toolName || !tool?.render) return undefined;
18
- return api.toolUIs().setToolUI(tool.toolName, tool.render);
18
+ return api.tools().setToolUI(tool.toolName, tool.render);
19
19
  }, [api, tool?.toolName, tool?.render]);
20
20
  };
@@ -15,5 +15,6 @@ export { useMessagePartReasoning } from "./messagePart/useMessagePartReasoning";
15
15
  export { useMessagePartSource } from "./messagePart/useMessagePartSource";
16
16
  export { useMessagePartFile } from "./messagePart/useMessagePartFile";
17
17
  export { useMessagePartImage } from "./messagePart/useMessagePartImage";
18
+ export { useMessagePartData } from "./messagePart/useMessagePartData";
18
19
  export { useThreadViewportAutoScroll } from "./thread/useThreadViewportAutoScroll";
19
20
  export { useScrollLock } from "./reasoning";
@@ -252,9 +252,8 @@ const ToolUIDisplay = ({
252
252
  }: {
253
253
  Fallback: ToolCallMessagePartComponent | undefined;
254
254
  } & ToolCallMessagePartProps) => {
255
- const Render = useAssistantState(({ toolUIs }) => {
256
- const Render =
257
- toolUIs.tools[props.toolName] ?? toolUIs.fallback ?? Fallback;
255
+ const Render = useAssistantState(({ tools }) => {
256
+ const Render = tools.tools[props.toolName] ?? Fallback;
258
257
  if (Array.isArray(Render)) return Render[0] ?? Fallback;
259
258
  return Render;
260
259
  });
@@ -338,6 +337,9 @@ const MessagePartComponent: FC<MessagePartComponentProps> = ({
338
337
  case "audio":
339
338
  return <Audio {...part} />;
340
339
 
340
+ case "data":
341
+ return null;
342
+
341
343
  default:
342
344
  const unhandledType: never = type;
343
345
  throw new Error(`Unknown message part type: ${unhandledType}`);
@@ -220,9 +220,8 @@ const ToolUIDisplay = ({
220
220
  }: {
221
221
  Fallback: ToolCallMessagePartComponent | undefined;
222
222
  } & ToolCallMessagePartProps) => {
223
- const Render = useAssistantState(({ toolUIs }) => {
224
- const Render =
225
- toolUIs.tools[props.toolName] ?? toolUIs.fallback ?? Fallback;
223
+ const Render = useAssistantState(({ tools }) => {
224
+ const Render = tools.tools[props.toolName] ?? Fallback;
226
225
  if (Array.isArray(Render)) return Render[0] ?? Fallback;
227
226
  return Render;
228
227
  });
@@ -305,6 +304,9 @@ const MessagePartComponent: FC<MessagePartComponentProps> = ({
305
304
  case "audio":
306
305
  return <Audio {...part} />;
307
306
 
307
+ case "data":
308
+ return null;
309
+
308
310
  default:
309
311
  const unhandledType: never = type;
310
312
  throw new Error(`Unknown message part type: ${unhandledType}`);
@@ -0,0 +1,24 @@
1
+ "use client";
2
+
3
+ import { useAssistantState } from "../../context";
4
+ import { DataMessagePart } from "../../types";
5
+
6
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
7
+ export const useMessagePartData = <T = any,>(name?: string) => {
8
+ const part = useAssistantState(({ part }) => {
9
+ if (part.type !== "data") {
10
+ return null;
11
+ }
12
+ return part as DataMessagePart<T>;
13
+ });
14
+
15
+ if (!part) {
16
+ return null;
17
+ }
18
+
19
+ if (name && part.name !== name) {
20
+ return null;
21
+ }
22
+
23
+ return part;
24
+ };
@@ -6,6 +6,7 @@ import type {
6
6
  SourceMessagePart,
7
7
  ImageMessagePart,
8
8
  FileMessagePart,
9
+ DataMessagePart,
9
10
  Unstable_AudioMessagePart,
10
11
  ToolCallMessagePart,
11
12
  ThreadUserMessagePart,
@@ -19,6 +20,7 @@ export type {
19
20
  SourceMessagePart,
20
21
  ImageMessagePart,
21
22
  FileMessagePart,
23
+ DataMessagePart,
22
24
  Unstable_AudioMessagePart,
23
25
  ToolCallMessagePart,
24
26
  ThreadUserMessagePart,
@@ -43,6 +43,12 @@ export type Unstable_AudioMessagePart = {
43
43
  };
44
44
  };
45
45
 
46
+ export type DataMessagePart<T = any> = {
47
+ readonly type: "data";
48
+ readonly name: string;
49
+ readonly data: T;
50
+ };
51
+
46
52
  export type ToolCallMessagePart<
47
53
  TArgs = ReadonlyJSONObject,
48
54
  TResult = unknown,
@@ -72,4 +78,5 @@ export type ThreadAssistantMessagePart =
72
78
  | ToolCallMessagePart
73
79
  | SourceMessagePart
74
80
  | FileMessagePart
75
- | ImageMessagePart;
81
+ | ImageMessagePart
82
+ | DataMessagePart;
@@ -12,6 +12,7 @@ export type {
12
12
  SourceMessagePart,
13
13
  ImageMessagePart,
14
14
  FileMessagePart,
15
+ DataMessagePart,
15
16
  Unstable_AudioMessagePart,
16
17
  ToolCallMessagePart,
17
18
  MessageStatus,
@@ -1,7 +0,0 @@
1
- import { ToolUIApi } from "./types/ToolUI";
2
- export declare const ToolUIClient: import("@assistant-ui/tap").ResourceElementConstructor<{
3
- key: string | undefined;
4
- state: any;
5
- api: ToolUIApi;
6
- }, undefined>;
7
- //# sourceMappingURL=ToolUIClient.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ToolUIClient.d.ts","sourceRoot":"","sources":["../../src/client/ToolUIClient.ts"],"names":[],"mappings":"AAEA,OAAO,EAAe,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAExD,eAAO,MAAM,YAAY;;;;aAuEvB,CAAC"}