@assistant-ui/react 0.12.14 → 0.12.16

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 (102) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/internal.d.ts +1 -1
  6. package/dist/internal.d.ts.map +1 -1
  7. package/dist/internal.js +1 -1
  8. package/dist/internal.js.map +1 -1
  9. package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.d.ts +1 -4
  10. package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  11. package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.js +2 -527
  12. package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  13. package/dist/legacy-runtime/hooks/AttachmentContext.d.ts +96 -96
  14. package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.d.ts +1 -16
  15. package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.d.ts.map +1 -1
  16. package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.js +1 -14
  17. package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.js.map +1 -1
  18. package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.d.ts +1 -13
  19. package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.d.ts.map +1 -1
  20. package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.js +2 -82
  21. package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.js.map +1 -1
  22. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.d.ts +1 -23
  23. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.d.ts.map +1 -1
  24. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.js +1 -305
  25. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.js.map +1 -1
  26. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.d.ts +1 -16
  27. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.d.ts.map +1 -1
  28. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.js +1 -48
  29. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.js.map +1 -1
  30. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.d.ts +1 -33
  31. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.d.ts.map +1 -1
  32. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.js +1 -295
  33. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.js.map +1 -1
  34. package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.d.ts +1 -3
  35. package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.d.ts.map +1 -1
  36. package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.js +1 -17
  37. package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.js.map +1 -1
  38. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.d.ts +1 -1
  39. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts +1 -96
  40. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  41. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.js +1 -110
  42. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.js.map +1 -1
  43. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts +1 -112
  44. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  45. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js +1 -439
  46. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  47. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.d.ts +1 -12
  48. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.d.ts.map +1 -1
  49. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.js +1 -102
  50. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.js.map +1 -1
  51. package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.d.ts +1 -3
  52. package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.d.ts.map +1 -1
  53. package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.js +1 -46
  54. package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.js.map +1 -1
  55. package/dist/primitives/actionBar/ActionBarInteractionContext.d.ts +6 -0
  56. package/dist/primitives/actionBar/ActionBarInteractionContext.d.ts.map +1 -0
  57. package/dist/primitives/actionBar/ActionBarInteractionContext.js +5 -0
  58. package/dist/primitives/actionBar/ActionBarInteractionContext.js.map +1 -0
  59. package/dist/primitives/actionBar/ActionBarRoot.d.ts.map +1 -1
  60. package/dist/primitives/actionBar/ActionBarRoot.js +18 -4
  61. package/dist/primitives/actionBar/ActionBarRoot.js.map +1 -1
  62. package/dist/primitives/actionBar/useActionBarFloatStatus.d.ts +2 -1
  63. package/dist/primitives/actionBar/useActionBarFloatStatus.d.ts.map +1 -1
  64. package/dist/primitives/actionBar/useActionBarFloatStatus.js +3 -2
  65. package/dist/primitives/actionBar/useActionBarFloatStatus.js.map +1 -1
  66. package/dist/primitives/actionBarMore/ActionBarMoreRoot.d.ts.map +1 -1
  67. package/dist/primitives/actionBarMore/ActionBarMoreRoot.js +35 -2
  68. package/dist/primitives/actionBarMore/ActionBarMoreRoot.js.map +1 -1
  69. package/dist/utils/createActionButton.js +1 -1
  70. package/dist/utils/createActionButton.js.map +1 -1
  71. package/dist/utils/json/is-json-equal.d.ts +2 -0
  72. package/dist/utils/json/is-json-equal.d.ts.map +1 -0
  73. package/dist/utils/json/is-json-equal.js +31 -0
  74. package/dist/utils/json/is-json-equal.js.map +1 -0
  75. package/dist/utils/json/is-json.d.ts +1 -0
  76. package/dist/utils/json/is-json.d.ts.map +1 -1
  77. package/dist/utils/json/is-json.js +5 -3
  78. package/dist/utils/json/is-json.js.map +1 -1
  79. package/package.json +8 -8
  80. package/src/index.ts +1 -1
  81. package/src/internal.ts +1 -1
  82. package/src/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.ts +2 -784
  83. package/src/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.tsx +5 -43
  84. package/src/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.ts +2 -100
  85. package/src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.test.ts +225 -2
  86. package/src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts +4 -439
  87. package/src/legacy-runtime/runtime-cores/external-store/createMessageConverter.ts +1 -76
  88. package/src/legacy-runtime/runtime-cores/external-store/external-message-converter.ts +4 -465
  89. package/src/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.ts +1 -27
  90. package/src/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.tsx +1 -178
  91. package/src/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.tsx +1 -529
  92. package/src/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.tsx +1 -152
  93. package/src/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.ts +1 -80
  94. package/src/primitives/actionBar/ActionBarInteractionContext.ts +13 -0
  95. package/src/primitives/actionBar/ActionBarRoot.tsx +38 -8
  96. package/src/primitives/actionBar/useActionBarFloatStatus.ts +4 -1
  97. package/src/primitives/actionBarMore/ActionBarMoreRoot.tsx +52 -2
  98. package/src/tests/BaseComposerRuntimeCore.test.ts +2 -3
  99. package/src/tests/external-message-converter.test.ts +80 -0
  100. package/src/utils/createActionButton.tsx +1 -1
  101. package/src/utils/json/is-json-equal.ts +48 -0
  102. package/src/utils/json/is-json.ts +6 -3
@@ -1,439 +1,4 @@
1
- import { useEffect, useRef, useState } from "react";
2
- import {
3
- createAssistantStreamController,
4
- type ToolCallStreamController,
5
- ToolResponse,
6
- unstable_toolResultStream,
7
- type Tool,
8
- } from "assistant-stream";
9
- import type {
10
- AssistantTransportCommand,
11
- AssistantTransportState,
12
- } from "./types";
13
- import {
14
- AssistantMetaTransformStream,
15
- type ReadonlyJSONValue,
16
- } from "assistant-stream/utils";
17
-
18
- const isArgsTextComplete = (argsText: string) => {
19
- try {
20
- JSON.parse(argsText);
21
- return true;
22
- } catch {
23
- return false;
24
- }
25
- };
26
-
27
- type UseToolInvocationsParams = {
28
- state: AssistantTransportState;
29
- getTools: () => Record<string, Tool> | undefined;
30
- onResult: (command: AssistantTransportCommand) => void;
31
- setToolStatuses: (
32
- updater:
33
- | Record<string, ToolExecutionStatus>
34
- | ((
35
- prev: Record<string, ToolExecutionStatus>,
36
- ) => Record<string, ToolExecutionStatus>),
37
- ) => void;
38
- };
39
-
40
- export type ToolExecutionStatus =
41
- | { type: "executing" }
42
- | { type: "interrupt"; payload: { type: "human"; payload: unknown } };
43
-
44
- type ToolState = {
45
- argsText: string;
46
- hasResult: boolean;
47
- argsComplete: boolean;
48
- streamToolCallId: string;
49
- controller: ToolCallStreamController;
50
- };
51
-
52
- export function useToolInvocations({
53
- state,
54
- getTools,
55
- onResult,
56
- setToolStatuses,
57
- }: UseToolInvocationsParams) {
58
- const lastToolStates = useRef<Record<string, ToolState>>({});
59
-
60
- const humanInputRef = useRef<
61
- Map<
62
- string,
63
- {
64
- resolve: (payload: unknown) => void;
65
- reject: (reason: unknown) => void;
66
- }
67
- >
68
- >(new Map());
69
-
70
- const acRef = useRef<AbortController>(new AbortController());
71
- const executingCountRef = useRef(0);
72
- const settledResolversRef = useRef<Array<() => void>>([]);
73
- const toolCallIdAliasesRef = useRef<Map<string, string>>(new Map());
74
- const ignoredResultToolCallIdsRef = useRef<Set<string>>(new Set());
75
- const rewriteCounterRef = useRef(0);
76
-
77
- const getLogicalToolCallId = (toolCallId: string) => {
78
- return toolCallIdAliasesRef.current.get(toolCallId) ?? toolCallId;
79
- };
80
-
81
- const shouldIgnoreAndCleanupResult = (toolCallId: string) => {
82
- if (!ignoredResultToolCallIdsRef.current.has(toolCallId)) return false;
83
- ignoredResultToolCallIdsRef.current.delete(toolCallId);
84
- toolCallIdAliasesRef.current.delete(toolCallId);
85
- return true;
86
- };
87
-
88
- const getWrappedTools = () => {
89
- const tools = getTools();
90
- if (!tools) return undefined;
91
-
92
- return Object.fromEntries(
93
- Object.entries(tools).map(([name, tool]) => {
94
- const execute = tool.execute;
95
- const streamCall = tool.streamCall;
96
-
97
- const wrappedTool = {
98
- ...tool,
99
- ...(execute !== undefined && {
100
- execute: (
101
- ...[args, context]: Parameters<NonNullable<typeof execute>>
102
- ) =>
103
- execute(args, {
104
- ...context,
105
- toolCallId: getLogicalToolCallId(context.toolCallId),
106
- }),
107
- }),
108
- ...(streamCall !== undefined && {
109
- streamCall: (
110
- ...[reader, context]: Parameters<NonNullable<typeof streamCall>>
111
- ) =>
112
- streamCall(reader, {
113
- ...context,
114
- toolCallId: getLogicalToolCallId(context.toolCallId),
115
- }),
116
- }),
117
- } as Tool;
118
- return [name, wrappedTool];
119
- }),
120
- ) as Record<string, Tool>;
121
- };
122
-
123
- const [controller] = useState(() => {
124
- const [stream, controller] = createAssistantStreamController();
125
- const transform = unstable_toolResultStream(
126
- getWrappedTools,
127
- () => acRef.current?.signal ?? new AbortController().signal,
128
- (toolCallId: string, payload: unknown) => {
129
- const logicalToolCallId = getLogicalToolCallId(toolCallId);
130
- return new Promise<unknown>((resolve, reject) => {
131
- // Reject previous human input request if it exists
132
- const previous = humanInputRef.current.get(logicalToolCallId);
133
- if (previous) {
134
- previous.reject(
135
- new Error("Human input request was superseded by a new request"),
136
- );
137
- }
138
-
139
- humanInputRef.current.set(logicalToolCallId, { resolve, reject });
140
- setToolStatuses((prev) => ({
141
- ...prev,
142
- [logicalToolCallId]: {
143
- type: "interrupt",
144
- payload: { type: "human", payload },
145
- },
146
- }));
147
- });
148
- },
149
- {
150
- onExecutionStart: (toolCallId: string) => {
151
- if (ignoredResultToolCallIdsRef.current.has(toolCallId)) {
152
- return;
153
- }
154
- const logicalToolCallId = getLogicalToolCallId(toolCallId);
155
- executingCountRef.current++;
156
- setToolStatuses((prev) => ({
157
- ...prev,
158
- [logicalToolCallId]: { type: "executing" },
159
- }));
160
- },
161
- onExecutionEnd: (toolCallId: string) => {
162
- if (ignoredResultToolCallIdsRef.current.has(toolCallId)) {
163
- return;
164
- }
165
- const logicalToolCallId = getLogicalToolCallId(toolCallId);
166
- executingCountRef.current--;
167
- setToolStatuses((prev) => {
168
- const next = { ...prev };
169
- delete next[logicalToolCallId];
170
- return next;
171
- });
172
- // Resolve any waiting abort promises when all tools have settled
173
- if (executingCountRef.current === 0) {
174
- settledResolversRef.current.forEach((resolve) => resolve());
175
- settledResolversRef.current = [];
176
- }
177
- },
178
- },
179
- );
180
- stream
181
- .pipeThrough(transform)
182
- .pipeThrough(new AssistantMetaTransformStream())
183
- .pipeTo(
184
- new WritableStream({
185
- write(chunk) {
186
- if (chunk.type === "result") {
187
- if (shouldIgnoreAndCleanupResult(chunk.meta.toolCallId)) {
188
- return;
189
- }
190
-
191
- const logicalToolCallId = getLogicalToolCallId(
192
- chunk.meta.toolCallId,
193
- );
194
- if (logicalToolCallId !== chunk.meta.toolCallId) {
195
- toolCallIdAliasesRef.current.delete(chunk.meta.toolCallId);
196
- }
197
- // the tool call result was already set by the backend
198
- if (lastToolStates.current[logicalToolCallId]?.hasResult) return;
199
-
200
- onResult({
201
- type: "add-tool-result",
202
- toolCallId: logicalToolCallId,
203
- toolName: chunk.meta.toolName,
204
- result: chunk.result,
205
- isError: chunk.isError,
206
- ...(chunk.artifact && { artifact: chunk.artifact }),
207
- });
208
- }
209
- },
210
- }),
211
- );
212
-
213
- return controller;
214
- });
215
-
216
- const ignoredToolIds = useRef<Set<string>>(new Set());
217
- const isInitialState = useRef(true);
218
-
219
- useEffect(() => {
220
- const createToolState = ({
221
- controller,
222
- streamToolCallId,
223
- }: {
224
- controller: ToolCallStreamController;
225
- streamToolCallId: string;
226
- }): ToolState => ({
227
- argsText: "",
228
- hasResult: false,
229
- argsComplete: false,
230
- streamToolCallId,
231
- controller,
232
- });
233
-
234
- const setToolState = (toolCallId: string, state: ToolState) => {
235
- lastToolStates.current[toolCallId] = state;
236
- return state;
237
- };
238
-
239
- const patchToolState = (
240
- toolCallId: string,
241
- state: ToolState,
242
- patch: Partial<ToolState>,
243
- ) => {
244
- return setToolState(toolCallId, { ...state, ...patch });
245
- };
246
-
247
- const processMessages = (
248
- messages: readonly (typeof state.messages)[number][],
249
- ) => {
250
- messages.forEach((message) => {
251
- message.content.forEach((content) => {
252
- if (content.type === "tool-call") {
253
- if (isInitialState.current) {
254
- ignoredToolIds.current.add(content.toolCallId);
255
- } else {
256
- if (ignoredToolIds.current.has(content.toolCallId)) {
257
- return;
258
- }
259
- let lastState = lastToolStates.current[content.toolCallId];
260
- if (!lastState) {
261
- toolCallIdAliasesRef.current.set(
262
- content.toolCallId,
263
- content.toolCallId,
264
- );
265
- const toolCallController = controller.addToolCallPart({
266
- toolName: content.toolName,
267
- toolCallId: content.toolCallId,
268
- });
269
- lastState = setToolState(
270
- content.toolCallId,
271
- createToolState({
272
- controller: toolCallController,
273
- streamToolCallId: content.toolCallId,
274
- }),
275
- );
276
- }
277
-
278
- if (content.argsText !== lastState.argsText) {
279
- if (lastState.argsComplete) {
280
- if (process.env.NODE_ENV !== "production") {
281
- console.warn(
282
- "argsText updated after controller was closed:",
283
- {
284
- previous: lastState.argsText,
285
- next: content.argsText,
286
- },
287
- );
288
- }
289
- } else {
290
- if (!content.argsText.startsWith(lastState.argsText)) {
291
- // Check if this is key reordering (both are complete JSON)
292
- // This happens when transitioning from streaming to complete state
293
- // and the provider returns keys in a different order
294
- if (
295
- isArgsTextComplete(lastState.argsText) &&
296
- isArgsTextComplete(content.argsText)
297
- ) {
298
- lastState.controller.argsText.close();
299
- patchToolState(content.toolCallId, lastState, {
300
- argsText: content.argsText,
301
- argsComplete: true,
302
- });
303
- return; // Continue to next content part
304
- }
305
- if (process.env.NODE_ENV !== "production") {
306
- console.warn(
307
- "argsText rewrote previous snapshot, restarting tool args stream:",
308
- {
309
- previous: lastState.argsText,
310
- next: content.argsText,
311
- toolCallId: content.toolCallId,
312
- },
313
- );
314
- }
315
-
316
- ignoredResultToolCallIdsRef.current.add(
317
- lastState.streamToolCallId,
318
- );
319
- lastState.controller.argsText.close();
320
-
321
- const streamToolCallId = `${content.toolCallId}:rewrite:${rewriteCounterRef.current++}`;
322
- toolCallIdAliasesRef.current.set(
323
- streamToolCallId,
324
- content.toolCallId,
325
- );
326
- const toolCallController = controller.addToolCallPart({
327
- toolName: content.toolName,
328
- toolCallId: streamToolCallId,
329
- });
330
- if (process.env.NODE_ENV !== "production") {
331
- console.warn("started replacement stream tool call", {
332
- toolCallId: content.toolCallId,
333
- streamToolCallId,
334
- });
335
- }
336
- lastState = setToolState(content.toolCallId, {
337
- ...createToolState({
338
- controller: toolCallController,
339
- streamToolCallId,
340
- }),
341
- hasResult: lastState.hasResult,
342
- });
343
- }
344
-
345
- const argsTextDelta = content.argsText.slice(
346
- lastState.argsText.length,
347
- );
348
- lastState.controller.argsText.append(argsTextDelta);
349
-
350
- const shouldClose = isArgsTextComplete(content.argsText);
351
- if (shouldClose) {
352
- lastState.controller.argsText.close();
353
- }
354
-
355
- patchToolState(content.toolCallId, lastState, {
356
- argsText: content.argsText,
357
- argsComplete: shouldClose,
358
- });
359
- }
360
- }
361
-
362
- if (content.result !== undefined && !lastState.hasResult) {
363
- patchToolState(content.toolCallId, lastState, {
364
- hasResult: true,
365
- argsComplete: true,
366
- });
367
-
368
- lastState.controller.setResponse(
369
- new ToolResponse({
370
- result: content.result as ReadonlyJSONValue,
371
- artifact: content.artifact as ReadonlyJSONValue | undefined,
372
- isError: content.isError,
373
- }),
374
- );
375
- lastState.controller.close();
376
- }
377
- }
378
-
379
- // Recursively process nested messages
380
- if (content.messages) {
381
- processMessages(content.messages);
382
- }
383
- }
384
- });
385
- });
386
- };
387
-
388
- processMessages(state.messages);
389
-
390
- if (isInitialState.current) {
391
- isInitialState.current = false;
392
- }
393
- }, [state, controller]);
394
-
395
- const abort = (): Promise<void> => {
396
- humanInputRef.current.forEach(({ reject }) => {
397
- reject(new Error("Tool execution aborted"));
398
- });
399
- humanInputRef.current.clear();
400
-
401
- acRef.current.abort();
402
- acRef.current = new AbortController();
403
-
404
- // Return a promise that resolves when all executing tools have settled
405
- if (executingCountRef.current === 0) {
406
- return Promise.resolve();
407
- }
408
- return new Promise<void>((resolve) => {
409
- settledResolversRef.current.push(resolve);
410
- });
411
- };
412
-
413
- return {
414
- reset: () => {
415
- isInitialState.current = true;
416
- void abort().finally(() => {
417
- toolCallIdAliasesRef.current.clear();
418
- ignoredResultToolCallIdsRef.current.clear();
419
- rewriteCounterRef.current = 0;
420
- });
421
- },
422
- abort,
423
- resume: (toolCallId: string, payload: unknown) => {
424
- const handlers = humanInputRef.current.get(toolCallId);
425
- if (handlers) {
426
- humanInputRef.current.delete(toolCallId);
427
- setToolStatuses((prev) => ({
428
- ...prev,
429
- [toolCallId]: { type: "executing" },
430
- }));
431
- handlers.resolve(payload);
432
- } else {
433
- throw new Error(
434
- `Tool call ${toolCallId} is not waiting for human input`,
435
- );
436
- }
437
- },
438
- };
439
- }
1
+ export {
2
+ useToolInvocations,
3
+ type ToolExecutionStatus,
4
+ } from "@assistant-ui/core/react";
@@ -1,77 +1,2 @@
1
1
  "use client";
2
- import type { ThreadMessage } from "@assistant-ui/core";
3
- import { ThreadState } from "../../runtime";
4
- import { useAui, useAuiState } from "@assistant-ui/store";
5
- import {
6
- useExternalMessageConverter,
7
- convertExternalMessages,
8
- } from "./external-message-converter";
9
- import { getExternalStoreMessages } from "./getExternalStoreMessage";
10
-
11
- export const createMessageConverter = <T extends object>(
12
- callback: useExternalMessageConverter.Callback<T>,
13
- ) => {
14
- const result = {
15
- useThreadMessages: ({
16
- messages,
17
- isRunning,
18
- joinStrategy,
19
- metadata,
20
- }: {
21
- messages: T[];
22
- isRunning: boolean;
23
- joinStrategy?: "concat-content" | "none" | undefined;
24
- metadata?: useExternalMessageConverter.Metadata;
25
- }) => {
26
- return useExternalMessageConverter<T>({
27
- callback,
28
- messages,
29
- isRunning,
30
- joinStrategy,
31
- metadata,
32
- });
33
- },
34
- toThreadMessages: (
35
- messages: T[],
36
- isRunning = false,
37
- metadata: useExternalMessageConverter.Metadata = {},
38
- ) => {
39
- return convertExternalMessages(messages, callback, isRunning, metadata);
40
- },
41
- toOriginalMessages: (
42
- input: ThreadState | ThreadMessage | ThreadMessage["content"][number],
43
- ) => {
44
- const messages = getExternalStoreMessages(input);
45
- if (messages.length === 0) throw new Error("No original messages found");
46
- return messages;
47
- },
48
- toOriginalMessage: (
49
- input: ThreadState | ThreadMessage | ThreadMessage["content"][number],
50
- ) => {
51
- const messages = result.toOriginalMessages(input);
52
- return messages[0]!;
53
- },
54
- useOriginalMessage: () => {
55
- const messageMessages = result.useOriginalMessages();
56
- const first = messageMessages[0]!;
57
- return first;
58
- },
59
- useOriginalMessages: () => {
60
- const aui = useAui();
61
- const partMessages = useAuiState((s) => {
62
- if (aui.part.source) return getExternalStoreMessages(s.part);
63
- return undefined;
64
- });
65
-
66
- const messageMessages = useAuiState<T[]>((s) =>
67
- getExternalStoreMessages(s.message),
68
- );
69
-
70
- const messages = partMessages ?? messageMessages;
71
- if (messages.length === 0) throw new Error("No original messages found");
72
- return messages;
73
- },
74
- };
75
-
76
- return result;
77
- };
2
+ export { createMessageConverter } from "@assistant-ui/core/react";