@assistant-ui/ai-sdk 0.0.10 → 0.0.12
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.
- package/dist/converters/convertMessage.d.ts +8 -6
- package/dist/converters/convertMessage.d.ts.map +1 -1
- package/dist/converters/convertMessage.js +106 -28
- package/dist/converters/convertMessage.js.map +1 -1
- package/dist/converters/toolApprovalAnswers.d.ts +3 -0
- package/dist/converters/toolApprovalAnswers.d.ts.map +1 -0
- package/dist/converters/toolApprovalAnswers.js +17 -0
- package/dist/converters/toolApprovalAnswers.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.native.d.ts +1 -1
- package/dist/index.native.d.ts.map +1 -1
- package/dist/index.native.js +1 -1
- package/dist/model-context/injectInteractableContext.d.ts +3 -0
- package/dist/model-context/injectInteractableContext.d.ts.map +1 -1
- package/dist/model-context/injectInteractableContext.js +3 -0
- package/dist/model-context/injectInteractableContext.js.map +1 -1
- package/dist/model-context/injectQuoteContext.d.ts +1 -0
- package/dist/model-context/injectQuoteContext.d.ts.map +1 -1
- package/dist/model-context/injectQuoteContext.js +1 -0
- package/dist/model-context/injectQuoteContext.js.map +1 -1
- package/dist/runtime/AISDKChat.js +1 -1
- package/dist/runtime/AISDKThreads.d.ts +5 -0
- package/dist/runtime/AISDKThreads.d.ts.map +1 -1
- package/dist/runtime/AISDKThreads.js +37 -4
- package/dist/runtime/AISDKThreads.js.map +1 -1
- package/dist/runtime/DynamicChatTransport.d.ts +49 -0
- package/dist/runtime/DynamicChatTransport.d.ts.map +1 -0
- package/dist/runtime/DynamicChatTransport.js +147 -0
- package/dist/runtime/DynamicChatTransport.js.map +1 -0
- package/dist/runtime/getResumableAdapter.d.ts +5 -0
- package/dist/runtime/getResumableAdapter.d.ts.map +1 -0
- package/dist/runtime/getResumableAdapter.js +12 -0
- package/dist/runtime/getResumableAdapter.js.map +1 -0
- package/dist/runtime/sdkIdentity.js +1 -1
- package/dist/runtime/toolHistoryCodec.d.ts +20 -0
- package/dist/runtime/toolHistoryCodec.d.ts.map +1 -0
- package/dist/runtime/toolHistoryCodec.js +107 -0
- package/dist/runtime/toolHistoryCodec.js.map +1 -0
- package/dist/runtime/useAISDKRuntime.d.ts +4 -1
- package/dist/runtime/useAISDKRuntime.d.ts.map +1 -1
- package/dist/runtime/useAISDKRuntime.js +154 -155
- package/dist/runtime/useAISDKRuntime.js.map +1 -1
- package/dist/runtime/useChatRuntime.d.ts +14 -2
- package/dist/runtime/useChatRuntime.d.ts.map +1 -1
- package/dist/runtime/useChatRuntime.js +12 -3
- package/dist/runtime/useChatRuntime.js.map +1 -1
- package/dist/runtime/useChatThread.d.ts +3 -2
- package/dist/runtime/useChatThread.d.ts.map +1 -1
- package/dist/runtime/useChatThread.js +56 -36
- package/dist/runtime/useChatThread.js.map +1 -1
- package/dist/runtime/useDynamicChatTransport.d.ts +4 -0
- package/dist/runtime/useDynamicChatTransport.d.ts.map +1 -0
- package/dist/runtime/useDynamicChatTransport.js +64 -0
- package/dist/runtime/useDynamicChatTransport.js.map +1 -0
- package/dist/runtime/useExternalHistory.d.ts.map +1 -1
- package/dist/runtime/useExternalHistory.js +11 -105
- package/dist/runtime/useExternalHistory.js.map +1 -1
- package/dist/runtime/useResourceCleanup.js +1 -1
- package/dist/runtime/useStreamingTiming.js +2 -2
- package/dist/runtime/useStreamingTiming.js.map +1 -1
- package/dist/tools/generativeTools.d.ts +2 -1
- package/dist/tools/generativeTools.d.ts.map +1 -1
- package/dist/tools/generativeTools.js +17 -6
- package/dist/tools/generativeTools.js.map +1 -1
- package/dist/usage.js +1 -1
- package/dist/utils/sliceMessagesUntil.d.ts.map +1 -1
- package/dist/utils/sliceMessagesUntil.js +1 -2
- package/dist/utils/sliceMessagesUntil.js.map +1 -1
- package/package.json +12 -10
- package/src/converters/convertMessage.test.ts +350 -2
- package/src/converters/convertMessage.tool-args-status.test.tsx +185 -0
- package/src/converters/convertMessage.ts +154 -23
- package/src/converters/toCreateMessage.test.ts +27 -0
- package/src/converters/toolApprovalAnswers.ts +27 -0
- package/src/index.native.ts +1 -1
- package/src/index.ts +1 -1
- package/src/model-context/injectInteractableContext.ts +3 -0
- package/src/model-context/injectQuoteContext.ts +1 -0
- package/src/runtime/AISDKChat.integration.test.tsx +57 -2
- package/src/runtime/AISDKThreads.cloud.test.ts +3 -0
- package/src/runtime/AISDKThreads.test.ts +181 -0
- package/src/runtime/AISDKThreads.ts +31 -4
- package/src/runtime/DynamicChatTransport.test.ts +203 -0
- package/src/runtime/DynamicChatTransport.ts +273 -0
- package/src/runtime/__tests__/controlled-transport.ts +3 -0
- package/src/runtime/getResumableAdapter.ts +16 -0
- package/src/runtime/toolHistoryCodec.test.ts +161 -0
- package/src/runtime/toolHistoryCodec.ts +207 -0
- package/src/runtime/useAISDKRuntime.approval.test.tsx +12 -0
- package/src/runtime/useAISDKRuntime.reload.test.tsx +219 -0
- package/src/runtime/useAISDKRuntime.test.ts +538 -5
- package/src/runtime/useAISDKRuntime.ts +161 -51
- package/src/runtime/useChatRuntime.integration.test.tsx +319 -4
- package/src/runtime/useChatRuntime.local-storage.test.tsx +123 -0
- package/src/runtime/useChatRuntime.test.ts +107 -1
- package/src/runtime/useChatRuntime.ts +26 -4
- package/src/runtime/useChatThread.binding.test.tsx +143 -0
- package/src/runtime/useChatThread.ts +98 -81
- package/src/runtime/useDynamicChatTransport.ts +26 -0
- package/src/runtime/useExternalHistory.test.ts +205 -0
- package/src/runtime/useExternalHistory.ts +14 -206
- package/src/runtime/useStreamingTiming.ts +2 -2
- package/src/tools/generativeTools.test.ts +190 -2
- package/src/tools/generativeTools.ts +28 -8
- package/src/utils/sliceMessagesUntil.test.ts +2 -6
- package/src/utils/sliceMessagesUntil.ts +1 -5
- package/dist/converters/modelContentEnvelope.d.ts +0 -14
- package/dist/converters/modelContentEnvelope.d.ts.map +0 -1
- package/dist/converters/modelContentEnvelope.js +0 -22
- package/dist/converters/modelContentEnvelope.js.map +0 -1
- package/dist/converters/toolOutputConversion.d.ts +0 -26
- package/dist/converters/toolOutputConversion.d.ts.map +0 -1
- package/dist/converters/toolOutputConversion.js +0 -31
- package/dist/converters/toolOutputConversion.js.map +0 -1
- package/dist/tools/frontendTools.d.ts +0 -30
- package/dist/tools/frontendTools.d.ts.map +0 -1
- package/dist/tools/frontendTools.js +0 -33
- package/dist/tools/frontendTools.js.map +0 -1
- package/src/converters/modelContentEnvelope.ts +0 -41
- package/src/converters/toolOutputConversion.ts +0 -26
- package/src/tools/frontendTools.test.ts +0 -205
- package/src/tools/frontendTools.ts +0 -83
|
@@ -12,10 +12,7 @@ import type {
|
|
|
12
12
|
Unstable_ToolInteractionLog,
|
|
13
13
|
} from "@assistant-ui/core";
|
|
14
14
|
import { getExternalStoreMessages } from "@assistant-ui/core";
|
|
15
|
-
import {
|
|
16
|
-
MessageRepository,
|
|
17
|
-
readToolInteractionLog,
|
|
18
|
-
} from "@assistant-ui/core/internal";
|
|
15
|
+
import { MessageRepository } from "@assistant-ui/core/internal";
|
|
19
16
|
import { useAui } from "@assistant-ui/store";
|
|
20
17
|
import {
|
|
21
18
|
useRef,
|
|
@@ -25,6 +22,14 @@ import {
|
|
|
25
22
|
useCallback,
|
|
26
23
|
useMemo,
|
|
27
24
|
} from "react";
|
|
25
|
+
import {
|
|
26
|
+
addToolData,
|
|
27
|
+
collectToolApprovalResponses,
|
|
28
|
+
collectToolArtifacts,
|
|
29
|
+
collectToolInteractions,
|
|
30
|
+
restoreToolData,
|
|
31
|
+
type StoredToolApprovalResponse,
|
|
32
|
+
} from "./toolHistoryCodec";
|
|
28
33
|
|
|
29
34
|
export const toExportedMessageRepository = <TMessage>(
|
|
30
35
|
toThreadMessages: (messages: TMessage[]) => ThreadMessage[],
|
|
@@ -71,206 +76,6 @@ const isTerminalMessage = (message: ThreadMessage) =>
|
|
|
71
76
|
message.status.type === "complete" ||
|
|
72
77
|
message.status.type === "incomplete";
|
|
73
78
|
|
|
74
|
-
const TOOL_ARTIFACTS_METADATA_KEY = "__aui_toolArtifacts";
|
|
75
|
-
const TOOL_INTERACTIONS_METADATA_KEY = "__aui_toolInteractions";
|
|
76
|
-
const TOOL_APPROVAL_RESPONSES_METADATA_KEY = "__aui_toolApprovalResponses";
|
|
77
|
-
|
|
78
|
-
type StoredToolApprovalResponse = Omit<
|
|
79
|
-
RespondToToolApprovalOptions,
|
|
80
|
-
"approvalId"
|
|
81
|
-
>;
|
|
82
|
-
|
|
83
|
-
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
84
|
-
value !== null && typeof value === "object" && !Array.isArray(value);
|
|
85
|
-
|
|
86
|
-
const collectToolArtifacts = (
|
|
87
|
-
message: ThreadMessage,
|
|
88
|
-
toolArtifacts: ReadonlyMap<string, unknown> | undefined,
|
|
89
|
-
) => {
|
|
90
|
-
if (!toolArtifacts) return undefined;
|
|
91
|
-
const entries = message.content.flatMap((part) => {
|
|
92
|
-
if (part.type !== "tool-call") return [];
|
|
93
|
-
const artifact = toolArtifacts.get(part.toolCallId);
|
|
94
|
-
return artifact === undefined ? [] : [[part.toolCallId, artifact] as const];
|
|
95
|
-
});
|
|
96
|
-
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const collectToolInteractions = (
|
|
100
|
-
message: ThreadMessage,
|
|
101
|
-
toolInteractions:
|
|
102
|
-
| ReadonlyMap<string, Unstable_ToolInteractionLog>
|
|
103
|
-
| undefined,
|
|
104
|
-
) => {
|
|
105
|
-
if (!toolInteractions) return undefined;
|
|
106
|
-
const entries = message.content.flatMap((part) => {
|
|
107
|
-
if (part.type !== "tool-call") return [];
|
|
108
|
-
const interactions = toolInteractions.get(part.toolCallId);
|
|
109
|
-
return interactions === undefined
|
|
110
|
-
? []
|
|
111
|
-
: [[part.toolCallId, interactions] as const];
|
|
112
|
-
});
|
|
113
|
-
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const collectToolApprovalResponses = (
|
|
117
|
-
message: ThreadMessage,
|
|
118
|
-
toolApprovalResponses:
|
|
119
|
-
| ReadonlyMap<string, RespondToToolApprovalOptions>
|
|
120
|
-
| undefined,
|
|
121
|
-
) => {
|
|
122
|
-
if (!toolApprovalResponses) return undefined;
|
|
123
|
-
const entries = message.content.flatMap((part) => {
|
|
124
|
-
if (part.type !== "tool-call" || !part.approval) return [];
|
|
125
|
-
const response = toolApprovalResponses.get(part.approval.id);
|
|
126
|
-
if (!response) return [];
|
|
127
|
-
return [
|
|
128
|
-
[
|
|
129
|
-
part.approval.id,
|
|
130
|
-
{
|
|
131
|
-
approved: response.approved,
|
|
132
|
-
...(response.optionId != null && { optionId: response.optionId }),
|
|
133
|
-
...(response.text != null && { text: response.text }),
|
|
134
|
-
...(response.reason != null && { reason: response.reason }),
|
|
135
|
-
},
|
|
136
|
-
] as const,
|
|
137
|
-
];
|
|
138
|
-
});
|
|
139
|
-
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
const addToolData = <TMessage>(
|
|
143
|
-
message: TMessage,
|
|
144
|
-
toolArtifacts: Record<string, unknown> | undefined,
|
|
145
|
-
toolInteractions: Record<string, Unstable_ToolInteractionLog> | undefined,
|
|
146
|
-
toolApprovalResponses: Record<string, StoredToolApprovalResponse> | undefined,
|
|
147
|
-
): TMessage => {
|
|
148
|
-
if (
|
|
149
|
-
(!toolArtifacts && !toolInteractions && !toolApprovalResponses) ||
|
|
150
|
-
!isRecord(message) ||
|
|
151
|
-
!Array.isArray(message.parts)
|
|
152
|
-
)
|
|
153
|
-
return message;
|
|
154
|
-
const toolCallIds = message.parts.flatMap((part) => {
|
|
155
|
-
if (!isRecord(part) || typeof part.toolCallId !== "string") return [];
|
|
156
|
-
return [part.toolCallId];
|
|
157
|
-
});
|
|
158
|
-
const artifacts = toolArtifacts
|
|
159
|
-
? Object.fromEntries(
|
|
160
|
-
toolCallIds.flatMap((toolCallId) =>
|
|
161
|
-
Object.hasOwn(toolArtifacts, toolCallId)
|
|
162
|
-
? [[toolCallId, toolArtifacts[toolCallId]] as const]
|
|
163
|
-
: [],
|
|
164
|
-
),
|
|
165
|
-
)
|
|
166
|
-
: undefined;
|
|
167
|
-
const interactions = toolInteractions
|
|
168
|
-
? Object.fromEntries(
|
|
169
|
-
toolCallIds.flatMap((toolCallId) =>
|
|
170
|
-
Object.hasOwn(toolInteractions, toolCallId)
|
|
171
|
-
? [[toolCallId, toolInteractions[toolCallId]] as const]
|
|
172
|
-
: [],
|
|
173
|
-
),
|
|
174
|
-
)
|
|
175
|
-
: undefined;
|
|
176
|
-
const approvalIds = message.parts.flatMap((part) => {
|
|
177
|
-
if (!isRecord(part) || !isRecord(part.approval)) return [];
|
|
178
|
-
const approvalId = part.approval.id;
|
|
179
|
-
return typeof approvalId === "string" ? [approvalId] : [];
|
|
180
|
-
});
|
|
181
|
-
const approvalResponses = toolApprovalResponses
|
|
182
|
-
? Object.fromEntries(
|
|
183
|
-
approvalIds.flatMap((approvalId) =>
|
|
184
|
-
Object.hasOwn(toolApprovalResponses, approvalId)
|
|
185
|
-
? [[approvalId, toolApprovalResponses[approvalId]] as const]
|
|
186
|
-
: [],
|
|
187
|
-
),
|
|
188
|
-
)
|
|
189
|
-
: undefined;
|
|
190
|
-
const hasArtifacts = !!artifacts && Object.keys(artifacts).length > 0;
|
|
191
|
-
const hasInteractions =
|
|
192
|
-
!!interactions && Object.keys(interactions).length > 0;
|
|
193
|
-
const hasApprovalResponses =
|
|
194
|
-
!!approvalResponses && Object.keys(approvalResponses).length > 0;
|
|
195
|
-
if (!hasArtifacts && !hasInteractions && !hasApprovalResponses)
|
|
196
|
-
return message;
|
|
197
|
-
const metadata = isRecord(message.metadata) ? message.metadata : {};
|
|
198
|
-
return {
|
|
199
|
-
...message,
|
|
200
|
-
metadata: {
|
|
201
|
-
...metadata,
|
|
202
|
-
...(hasArtifacts && { [TOOL_ARTIFACTS_METADATA_KEY]: artifacts }),
|
|
203
|
-
...(hasInteractions && {
|
|
204
|
-
[TOOL_INTERACTIONS_METADATA_KEY]: interactions,
|
|
205
|
-
}),
|
|
206
|
-
...(hasApprovalResponses && {
|
|
207
|
-
[TOOL_APPROVAL_RESPONSES_METADATA_KEY]: approvalResponses,
|
|
208
|
-
}),
|
|
209
|
-
},
|
|
210
|
-
} as TMessage;
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
const restoreToolData = <TMessage>(
|
|
214
|
-
message: TMessage,
|
|
215
|
-
toolArtifacts: Map<string, unknown> | undefined,
|
|
216
|
-
toolInteractions: Map<string, Unstable_ToolInteractionLog> | undefined,
|
|
217
|
-
toolApprovalResponses: Map<string, RespondToToolApprovalOptions> | undefined,
|
|
218
|
-
): TMessage => {
|
|
219
|
-
if (!isRecord(message) || !isRecord(message.metadata)) return message;
|
|
220
|
-
const metadata = message.metadata;
|
|
221
|
-
const hasArtifacts = Object.hasOwn(metadata, TOOL_ARTIFACTS_METADATA_KEY);
|
|
222
|
-
const hasInteractions = Object.hasOwn(
|
|
223
|
-
metadata,
|
|
224
|
-
TOOL_INTERACTIONS_METADATA_KEY,
|
|
225
|
-
);
|
|
226
|
-
const hasApprovalResponses = Object.hasOwn(
|
|
227
|
-
metadata,
|
|
228
|
-
TOOL_APPROVAL_RESPONSES_METADATA_KEY,
|
|
229
|
-
);
|
|
230
|
-
if (!hasArtifacts && !hasInteractions && !hasApprovalResponses)
|
|
231
|
-
return message;
|
|
232
|
-
const artifacts = metadata[TOOL_ARTIFACTS_METADATA_KEY];
|
|
233
|
-
if (toolArtifacts && isRecord(artifacts)) {
|
|
234
|
-
for (const [toolCallId, artifact] of Object.entries(artifacts)) {
|
|
235
|
-
toolArtifacts.set(toolCallId, artifact);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
const interactions = metadata[TOOL_INTERACTIONS_METADATA_KEY];
|
|
239
|
-
if (toolInteractions && isRecord(interactions)) {
|
|
240
|
-
for (const [toolCallId, value] of Object.entries(interactions)) {
|
|
241
|
-
const log = readToolInteractionLog(value);
|
|
242
|
-
if (log) toolInteractions.set(toolCallId, log);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
const approvalResponses = metadata[TOOL_APPROVAL_RESPONSES_METADATA_KEY];
|
|
246
|
-
if (toolApprovalResponses && isRecord(approvalResponses)) {
|
|
247
|
-
for (const [approvalId, value] of Object.entries(approvalResponses)) {
|
|
248
|
-
if (!isRecord(value) || typeof value.approved !== "boolean") continue;
|
|
249
|
-
toolApprovalResponses.set(approvalId, {
|
|
250
|
-
approvalId,
|
|
251
|
-
approved: value.approved,
|
|
252
|
-
...(typeof value.optionId === "string" && {
|
|
253
|
-
optionId: value.optionId,
|
|
254
|
-
}),
|
|
255
|
-
...(typeof value.text === "string" && { text: value.text }),
|
|
256
|
-
...(typeof value.reason === "string" && { reason: value.reason }),
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
const {
|
|
261
|
-
[TOOL_ARTIFACTS_METADATA_KEY]: _,
|
|
262
|
-
[TOOL_INTERACTIONS_METADATA_KEY]: __,
|
|
263
|
-
[TOOL_APPROVAL_RESPONSES_METADATA_KEY]: ___,
|
|
264
|
-
...restMetadata
|
|
265
|
-
} = metadata;
|
|
266
|
-
const { metadata: _metadata, ...restMessage } = message;
|
|
267
|
-
return (
|
|
268
|
-
Object.keys(restMetadata).length === 0
|
|
269
|
-
? restMessage
|
|
270
|
-
: { ...restMessage, metadata: restMetadata }
|
|
271
|
-
) as TMessage;
|
|
272
|
-
};
|
|
273
|
-
|
|
274
79
|
const encodeContent = <TMessage>(
|
|
275
80
|
storageFormatAdapter: MessageFormatAdapter<TMessage, any>,
|
|
276
81
|
item: MessageFormatItem<TMessage>,
|
|
@@ -330,6 +135,10 @@ export const useExternalHistory = <TMessage>(
|
|
|
330
135
|
const loadHistory = async () => {
|
|
331
136
|
try {
|
|
332
137
|
const repo = await formatAdapter.load();
|
|
138
|
+
const threadState = runtimeRef.current.thread.getState();
|
|
139
|
+
if (threadState.isRunning || threadState.messages.length > 0) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
333
142
|
toolArtifacts?.clear();
|
|
334
143
|
toolInteractions?.clear();
|
|
335
144
|
toolApprovalResponses?.clear();
|
|
@@ -390,8 +199,6 @@ export const useExternalHistory = <TMessage>(
|
|
|
390
199
|
|
|
391
200
|
const remoteId = optionalThreadListItem()?.getState().remoteId;
|
|
392
201
|
if (!remoteId) {
|
|
393
|
-
// History loads asynchronously against the thread list item; without a
|
|
394
|
-
// remote id there is nothing to await, so the flag settles here.
|
|
395
202
|
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
396
203
|
setHasLoaded(true);
|
|
397
204
|
return aui.subscribe(() => {
|
|
@@ -409,6 +216,7 @@ export const useExternalHistory = <TMessage>(
|
|
|
409
216
|
}
|
|
410
217
|
|
|
411
218
|
loadedRef.current = true;
|
|
219
|
+
setHasLoaded(false);
|
|
412
220
|
void loadHistory();
|
|
413
221
|
return undefined;
|
|
414
222
|
}, [
|
|
@@ -22,7 +22,7 @@ const getTextLength = (
|
|
|
22
22
|
if (!message?.parts) return 0;
|
|
23
23
|
let len = 0;
|
|
24
24
|
for (const part of message.parts) {
|
|
25
|
-
if (part
|
|
25
|
+
if (part?.type === "text") len += part.text?.length ?? 0;
|
|
26
26
|
}
|
|
27
27
|
return len;
|
|
28
28
|
};
|
|
@@ -35,7 +35,7 @@ const getToolCallCount = (
|
|
|
35
35
|
if (!message?.parts) return 0;
|
|
36
36
|
let count = 0;
|
|
37
37
|
for (const part of message.parts) {
|
|
38
|
-
if (isToolUIPart(part)) count++;
|
|
38
|
+
if (typeof part?.type === "string" && isToolUIPart(part)) count++;
|
|
39
39
|
}
|
|
40
40
|
return count;
|
|
41
41
|
};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
defineMcpToolkit,
|
|
4
|
+
defineToolkit,
|
|
5
|
+
type ToolkitDefinition,
|
|
6
|
+
} from "@assistant-ui/core/react";
|
|
3
7
|
import { AISDKToolkit } from "./generativeTools";
|
|
4
|
-
import { wrapModelContentEnvelope } from "
|
|
8
|
+
import { wrapModelContentEnvelope } from "assistant-stream/internal";
|
|
5
9
|
|
|
6
10
|
const mocks = vi.hoisted(() => ({
|
|
7
11
|
close: vi.fn(),
|
|
@@ -130,6 +134,190 @@ describe("AISDKToolkit.tools()", () => {
|
|
|
130
134
|
supportsDeferredResults: false,
|
|
131
135
|
});
|
|
132
136
|
});
|
|
137
|
+
|
|
138
|
+
it("converts unchanged provider and backend schemas once", async () => {
|
|
139
|
+
const toBackendJSONSchema = vi.fn(() => ({
|
|
140
|
+
type: "object" as const,
|
|
141
|
+
properties: {},
|
|
142
|
+
}));
|
|
143
|
+
const toProviderJSONSchema = vi.fn(() => ({
|
|
144
|
+
type: "object" as const,
|
|
145
|
+
properties: {},
|
|
146
|
+
}));
|
|
147
|
+
const toolkitDefinition = {
|
|
148
|
+
serverTool: {
|
|
149
|
+
type: "backend",
|
|
150
|
+
parameters: { toJSONSchema: toBackendJSONSchema },
|
|
151
|
+
execute: async () => "ok",
|
|
152
|
+
} as never,
|
|
153
|
+
providerTool: {
|
|
154
|
+
type: "provider",
|
|
155
|
+
providerId: "provider.tool",
|
|
156
|
+
args: {},
|
|
157
|
+
parameters: { toJSONSchema: toProviderJSONSchema },
|
|
158
|
+
} as never,
|
|
159
|
+
};
|
|
160
|
+
const firstToolkit = new AISDKToolkit({ toolkit: toolkitDefinition });
|
|
161
|
+
const secondToolkit = new AISDKToolkit({ toolkit: toolkitDefinition });
|
|
162
|
+
|
|
163
|
+
const first = await firstToolkit.tools();
|
|
164
|
+
const second = await secondToolkit.tools();
|
|
165
|
+
|
|
166
|
+
expect(toBackendJSONSchema).toHaveBeenCalledTimes(1);
|
|
167
|
+
expect(toProviderJSONSchema).toHaveBeenCalledTimes(1);
|
|
168
|
+
expect(second.serverTool).not.toBe(first.serverTool);
|
|
169
|
+
expect(second.providerTool).not.toBe(first.providerTool);
|
|
170
|
+
expect(second.serverTool!.inputSchema).not.toBe(
|
|
171
|
+
first.serverTool!.inputSchema,
|
|
172
|
+
);
|
|
173
|
+
expect(
|
|
174
|
+
(second.serverTool!.inputSchema as { jsonSchema: unknown }).jsonSchema,
|
|
175
|
+
).toBe(
|
|
176
|
+
(first.serverTool!.inputSchema as { jsonSchema: unknown }).jsonSchema,
|
|
177
|
+
);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("converts the current frontend tools on every call", async () => {
|
|
181
|
+
const toolkit = new AISDKToolkit({ toolkit: {} });
|
|
182
|
+
|
|
183
|
+
const first = await toolkit.tools({
|
|
184
|
+
frontend: {
|
|
185
|
+
firstClientTool: {
|
|
186
|
+
parameters: { type: "object", properties: {} },
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
const second = await toolkit.tools({
|
|
191
|
+
frontend: {
|
|
192
|
+
secondClientTool: {
|
|
193
|
+
parameters: { type: "object", properties: {} },
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
expect(first).toHaveProperty("firstClientTool");
|
|
199
|
+
expect(first).not.toHaveProperty("secondClientTool");
|
|
200
|
+
expect(second).toHaveProperty("secondClientTool");
|
|
201
|
+
expect(second).not.toHaveProperty("firstClientTool");
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("does not convert disabled static toolkit entries", async () => {
|
|
205
|
+
const toJSONSchema = vi.fn(() => ({
|
|
206
|
+
type: "object" as const,
|
|
207
|
+
properties: {},
|
|
208
|
+
}));
|
|
209
|
+
const toolkit = new AISDKToolkit({
|
|
210
|
+
toolkit: {
|
|
211
|
+
disabledServerTool: {
|
|
212
|
+
type: "backend",
|
|
213
|
+
disabled: true,
|
|
214
|
+
parameters: { toJSONSchema },
|
|
215
|
+
} as never,
|
|
216
|
+
disabledProviderTool: {
|
|
217
|
+
type: "provider",
|
|
218
|
+
disabled: true,
|
|
219
|
+
providerId: "provider.tool",
|
|
220
|
+
args: {},
|
|
221
|
+
parameters: { toJSONSchema },
|
|
222
|
+
} as never,
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
await expect(toolkit.tools()).resolves.toEqual({});
|
|
227
|
+
expect(toJSONSchema).not.toHaveBeenCalled();
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("reflects replaced toolkit entries on the next call", async () => {
|
|
231
|
+
const definition: ToolkitDefinition = {
|
|
232
|
+
serverTool: {
|
|
233
|
+
description: "Original tool",
|
|
234
|
+
parameters: { type: "object" as const, properties: {} },
|
|
235
|
+
execute: async () => "original",
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
const toolkit = new AISDKToolkit({ toolkit: defineToolkit(definition) });
|
|
239
|
+
|
|
240
|
+
const first = await toolkit.tools();
|
|
241
|
+
definition.serverTool = {
|
|
242
|
+
description: "Replacement tool",
|
|
243
|
+
parameters: { type: "object" as const, properties: {} },
|
|
244
|
+
execute: async () => "replacement",
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const refreshed = await toolkit.tools();
|
|
248
|
+
|
|
249
|
+
expect(first.serverTool?.description).toBe("Original tool");
|
|
250
|
+
expect(refreshed.serverTool?.description).toBe("Replacement tool");
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it("reconverts a replaced parameters object", async () => {
|
|
254
|
+
const firstConversion = vi.fn(() => ({
|
|
255
|
+
type: "object" as const,
|
|
256
|
+
properties: { first: { type: "string" } },
|
|
257
|
+
}));
|
|
258
|
+
const secondConversion = vi.fn(() => ({
|
|
259
|
+
type: "object" as const,
|
|
260
|
+
properties: { second: { type: "string" } },
|
|
261
|
+
}));
|
|
262
|
+
const definition: ToolkitDefinition = {
|
|
263
|
+
serverTool: {
|
|
264
|
+
parameters: { toJSONSchema: firstConversion },
|
|
265
|
+
execute: async () => "ok",
|
|
266
|
+
} as never,
|
|
267
|
+
};
|
|
268
|
+
const toolkit = new AISDKToolkit({ toolkit: defineToolkit(definition) });
|
|
269
|
+
|
|
270
|
+
await toolkit.tools();
|
|
271
|
+
definition.serverTool!.parameters = {
|
|
272
|
+
toJSONSchema: secondConversion,
|
|
273
|
+
} as never;
|
|
274
|
+
await toolkit.tools();
|
|
275
|
+
|
|
276
|
+
expect(firstConversion).toHaveBeenCalledOnce();
|
|
277
|
+
expect(secondConversion).toHaveBeenCalledOnce();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it("reflects in-place toolkit entry changes on the next call", async () => {
|
|
281
|
+
const definition: ToolkitDefinition = {
|
|
282
|
+
serverTool: {
|
|
283
|
+
description: "Original tool",
|
|
284
|
+
parameters: { type: "object" as const, properties: {} },
|
|
285
|
+
execute: async () => "ok",
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
const toolkit = new AISDKToolkit({ toolkit: defineToolkit(definition) });
|
|
289
|
+
|
|
290
|
+
expect((await toolkit.tools()).serverTool?.description).toBe(
|
|
291
|
+
"Original tool",
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
definition.serverTool!.description = "Updated tool";
|
|
295
|
+
expect((await toolkit.tools()).serverTool?.description).toBe(
|
|
296
|
+
"Updated tool",
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
definition.serverTool!.disabled = true;
|
|
300
|
+
expect(await toolkit.tools()).not.toHaveProperty("serverTool");
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it("does not share mutable tool entries between calls", async () => {
|
|
304
|
+
const toolkit = new AISDKToolkit({
|
|
305
|
+
toolkit: defineToolkit({
|
|
306
|
+
serverTool: {
|
|
307
|
+
description: "Original tool",
|
|
308
|
+
parameters: { type: "object" as const, properties: {} },
|
|
309
|
+
execute: async () => "ok",
|
|
310
|
+
},
|
|
311
|
+
}),
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
const first = await toolkit.tools();
|
|
315
|
+
first.serverTool!.description = "Changed returned tool";
|
|
316
|
+
|
|
317
|
+
const second = await toolkit.tools();
|
|
318
|
+
|
|
319
|
+
expect(second.serverTool?.description).toBe("Original tool");
|
|
320
|
+
});
|
|
133
321
|
});
|
|
134
322
|
|
|
135
323
|
describe("AISDKToolkit", () => {
|
|
@@ -13,15 +13,13 @@ import type {
|
|
|
13
13
|
Toolkit,
|
|
14
14
|
ToolkitDefinition,
|
|
15
15
|
} from "@assistant-ui/core/react";
|
|
16
|
-
import { frontendTools, type FrontendTools } from "
|
|
16
|
+
import { frontendTools, type FrontendTools } from "assistant-stream/ai-sdk";
|
|
17
17
|
import {
|
|
18
18
|
toAISDKContent,
|
|
19
19
|
toAISDKDefaultOutput,
|
|
20
|
-
} from "../converters/toolOutputConversion";
|
|
21
|
-
import {
|
|
22
20
|
unwrapModelContentEnvelope,
|
|
23
21
|
type ModelContentEnvelope,
|
|
24
|
-
} from "
|
|
22
|
+
} from "assistant-stream/internal";
|
|
25
23
|
|
|
26
24
|
const EMPTY_SCHEMA = { type: "object" as const, properties: {} };
|
|
27
25
|
|
|
@@ -76,8 +74,29 @@ const withMcpConnectionTimeout = async <T>(
|
|
|
76
74
|
}
|
|
77
75
|
};
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
// Converted schemas are shared by parameter identity and treated as immutable.
|
|
78
|
+
const convertedParameterSchemas = new WeakMap<
|
|
79
|
+
object,
|
|
80
|
+
ReturnType<typeof toJSONSchema>
|
|
81
|
+
>();
|
|
82
|
+
|
|
83
|
+
const getOrConvertParameterSchema = (
|
|
84
|
+
parameters: NonNullable<Tool["parameters"]>,
|
|
85
|
+
) => {
|
|
86
|
+
const cached = convertedParameterSchemas.get(parameters);
|
|
87
|
+
if (cached) return cached;
|
|
88
|
+
|
|
89
|
+
const converted = toJSONSchema(parameters);
|
|
90
|
+
convertedParameterSchemas.set(parameters, converted);
|
|
91
|
+
return converted;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const parametersToInputSchema = (
|
|
95
|
+
parameters: Tool["parameters"] | undefined,
|
|
96
|
+
) => {
|
|
97
|
+
if (!parameters) return jsonSchema(EMPTY_SCHEMA);
|
|
98
|
+
return jsonSchema(getOrConvertParameterSchema(parameters));
|
|
99
|
+
};
|
|
81
100
|
|
|
82
101
|
/**
|
|
83
102
|
* @deprecated Options for the deprecated {@link generativeTools}. Use
|
|
@@ -135,6 +154,7 @@ export type AISDKToolkitToolsOptions = {
|
|
|
135
154
|
* // In your route handler:
|
|
136
155
|
* const { tools } = await req.json();
|
|
137
156
|
* streamText({
|
|
157
|
+
* abortSignal: req.signal,
|
|
138
158
|
* model,
|
|
139
159
|
* messages,
|
|
140
160
|
* tools: await aiToolkit.tools({ frontend: tools }),
|
|
@@ -394,7 +414,7 @@ const toAISDKToModelOutput =
|
|
|
394
414
|
const { result, modelContent } = unwrapModelContentEnvelope(options.output);
|
|
395
415
|
|
|
396
416
|
if (modelContent !== undefined) {
|
|
397
|
-
return toAISDKContent(modelContent);
|
|
417
|
+
return toAISDKContent(modelContent, { taggedFileData: true });
|
|
398
418
|
}
|
|
399
419
|
|
|
400
420
|
if (!toModelOutput) {
|
|
@@ -405,7 +425,7 @@ const toAISDKToModelOutput =
|
|
|
405
425
|
...options,
|
|
406
426
|
output: result,
|
|
407
427
|
});
|
|
408
|
-
return toAISDKContent(parts);
|
|
428
|
+
return toAISDKContent(parts, { taggedFileData: true });
|
|
409
429
|
};
|
|
410
430
|
|
|
411
431
|
const toServerToolSet = (toolkit: ToolkitDefinition): ToolSet =>
|
|
@@ -31,18 +31,14 @@ describe("sliceMessagesUntil", () => {
|
|
|
31
31
|
]);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
it("
|
|
34
|
+
it("stops at the target even when assistant messages follow it", () => {
|
|
35
35
|
const messages = [
|
|
36
36
|
msg("u1", "user"),
|
|
37
37
|
msg("a1", "assistant"),
|
|
38
38
|
msg("a2", "assistant"),
|
|
39
39
|
msg("u2", "user"),
|
|
40
40
|
];
|
|
41
|
-
expect(sliceMessagesUntil(messages, "u1").map((m) => m.id)).toEqual([
|
|
42
|
-
"u1",
|
|
43
|
-
"a1",
|
|
44
|
-
"a2",
|
|
45
|
-
]);
|
|
41
|
+
expect(sliceMessagesUntil(messages, "u1").map((m) => m.id)).toEqual(["u1"]);
|
|
46
42
|
});
|
|
47
43
|
|
|
48
44
|
it("returns the whole array when the target is the last message", () => {
|
|
@@ -6,15 +6,11 @@ export const sliceMessagesUntil = <UI_MESSAGE extends UIMessage = UIMessage>(
|
|
|
6
6
|
) => {
|
|
7
7
|
if (messageId == null) return [];
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const messageIdx = messages.findIndex((m) => m.id === messageId);
|
|
10
10
|
if (messageIdx === -1)
|
|
11
11
|
throw new Error(
|
|
12
12
|
`sliceMessagesUntil: Message "${messageId}" not found in AI SDK messages. This is likely an internal bug in assistant-ui.`,
|
|
13
13
|
);
|
|
14
14
|
|
|
15
|
-
while (messages[messageIdx + 1]?.role === "assistant") {
|
|
16
|
-
messageIdx++;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
15
|
return messages.slice(0, messageIdx + 1);
|
|
20
16
|
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { ToolModelContentPart } from "assistant-stream";
|
|
2
|
-
declare const ENVELOPE_KEY = "__aui_modelContent";
|
|
3
|
-
export type ModelContentEnvelope<TResult = unknown> = {
|
|
4
|
-
readonly [ENVELOPE_KEY]: readonly ToolModelContentPart[];
|
|
5
|
-
readonly value: TResult;
|
|
6
|
-
};
|
|
7
|
-
export declare function isModelContentEnvelope<TResult = unknown>(value: TResult | ModelContentEnvelope<TResult>): value is ModelContentEnvelope<TResult>;
|
|
8
|
-
export declare function wrapModelContentEnvelope<TResult>(result: TResult, modelContent: readonly ToolModelContentPart[]): ModelContentEnvelope<TResult>;
|
|
9
|
-
export declare function unwrapModelContentEnvelope<TResult>(output: TResult | ModelContentEnvelope<TResult>): {
|
|
10
|
-
result: TResult;
|
|
11
|
-
modelContent?: readonly ToolModelContentPart[];
|
|
12
|
-
};
|
|
13
|
-
export {};
|
|
14
|
-
//# sourceMappingURL=modelContentEnvelope.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"modelContentEnvelope.d.ts","sourceRoot":"","sources":["../../src/converters/modelContentEnvelope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,QAAA,MAAM,YAAY,uBAAuB,CAAC;AAE1C,MAAM,MAAM,oBAAoB,CAAC,OAAO,GAAG,OAAO,IAAI;IACpD,QAAQ,CAAC,CAAC,YAAY,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACzD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,OAAO,GAAG,OAAO,EACtD,KAAK,EAAE,OAAO,GAAG,oBAAoB,CAAC,OAAO,CAAC,GAC7C,KAAK,IAAI,oBAAoB,CAAC,OAAO,CAAC,CAOxC;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAC9C,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,SAAS,oBAAoB,EAAE,GAC5C,oBAAoB,CAAC,OAAO,CAAC,CAE/B;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAChD,MAAM,EAAE,OAAO,GAAG,oBAAoB,CAAC,OAAO,CAAC,GAC9C;IACD,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;CAChD,CAQA"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
//#region src/converters/modelContentEnvelope.ts
|
|
2
|
-
const ENVELOPE_KEY = "__aui_modelContent";
|
|
3
|
-
function isModelContentEnvelope(value) {
|
|
4
|
-
return value != null && typeof value === "object" && ENVELOPE_KEY in value && Array.isArray(value[ENVELOPE_KEY]);
|
|
5
|
-
}
|
|
6
|
-
function wrapModelContentEnvelope(result, modelContent) {
|
|
7
|
-
return {
|
|
8
|
-
[ENVELOPE_KEY]: modelContent,
|
|
9
|
-
value: result
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
function unwrapModelContentEnvelope(output) {
|
|
13
|
-
if (isModelContentEnvelope(output)) return {
|
|
14
|
-
result: output.value,
|
|
15
|
-
modelContent: output[ENVELOPE_KEY]
|
|
16
|
-
};
|
|
17
|
-
return { result: output };
|
|
18
|
-
}
|
|
19
|
-
//#endregion
|
|
20
|
-
export { isModelContentEnvelope, unwrapModelContentEnvelope, wrapModelContentEnvelope };
|
|
21
|
-
|
|
22
|
-
//# sourceMappingURL=modelContentEnvelope.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"modelContentEnvelope.js","names":["ToolModelContentPart","ENVELOPE_KEY","ModelContentEnvelope","value","TResult","isModelContentEnvelope","Array","isArray","Record","wrapModelContentEnvelope","result","modelContent","unwrapModelContentEnvelope","output"],"sources":["../../src/converters/modelContentEnvelope.ts"],"sourcesContent":["import type { ToolModelContentPart } from \"assistant-stream\";\n\nconst ENVELOPE_KEY = \"__aui_modelContent\";\n\nexport type ModelContentEnvelope<TResult = unknown> = {\n readonly [ENVELOPE_KEY]: readonly ToolModelContentPart[];\n readonly value: TResult;\n};\n\nexport function isModelContentEnvelope<TResult = unknown>(\n value: TResult | ModelContentEnvelope<TResult>,\n): value is ModelContentEnvelope<TResult> {\n return (\n value != null &&\n typeof value === \"object\" &&\n ENVELOPE_KEY in value &&\n Array.isArray((value as Record<string, unknown>)[ENVELOPE_KEY])\n );\n}\n\nexport function wrapModelContentEnvelope<TResult>(\n result: TResult,\n modelContent: readonly ToolModelContentPart[],\n): ModelContentEnvelope<TResult> {\n return { [ENVELOPE_KEY]: modelContent, value: result };\n}\n\nexport function unwrapModelContentEnvelope<TResult>(\n output: TResult | ModelContentEnvelope<TResult>,\n): {\n result: TResult;\n modelContent?: readonly ToolModelContentPart[];\n} {\n if (isModelContentEnvelope(output)) {\n return {\n result: output.value,\n modelContent: output[ENVELOPE_KEY],\n };\n }\n return { result: output };\n}\n"],"mappings":";AAEA,MAAMC,eAAe;AAOrB,SAAgBI,uBACdF,OACwC;CACxC,OACEA,SAAS,QACT,OAAOA,UAAU,YACjBF,gBAAgBE,SAChBG,MAAMC,QAASJ,MAAkCF,aAAa;AAElE;AAEA,SAAgBQ,yBACdC,QACAC,cAC+B;CAC/B,OAAO;GAAGV,eAAeU;EAAcR,OAAOO;CAAO;AACvD;AAEA,SAAgBE,2BACdC,QAIA;CACA,IAAIR,uBAAuBQ,MAAM,GAC/B,OAAO;EACLH,QAAQG,OAAOV;EACfQ,cAAcE,OAAOZ;CACvB;CAEF,OAAO,EAAES,QAAQG,OAAO;AAC1B"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { JSONValue } from "ai";
|
|
2
|
-
import type { ToolModelContentPart } from "assistant-stream";
|
|
3
|
-
export declare const toAISDKContent: (parts: readonly ToolModelContentPart[]) => {
|
|
4
|
-
type: "content";
|
|
5
|
-
value: ({
|
|
6
|
-
type: "text";
|
|
7
|
-
text: string;
|
|
8
|
-
} | {
|
|
9
|
-
filename?: string;
|
|
10
|
-
type: "file";
|
|
11
|
-
data: {
|
|
12
|
-
type: "data";
|
|
13
|
-
data: string;
|
|
14
|
-
};
|
|
15
|
-
mediaType: string;
|
|
16
|
-
text?: never;
|
|
17
|
-
})[];
|
|
18
|
-
};
|
|
19
|
-
export declare const toAISDKDefaultOutput: (output: unknown) => {
|
|
20
|
-
type: "text";
|
|
21
|
-
value: string;
|
|
22
|
-
} | {
|
|
23
|
-
type: "json";
|
|
24
|
-
value: JSONValue;
|
|
25
|
-
};
|
|
26
|
-
//# sourceMappingURL=toolOutputConversion.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"toolOutputConversion.d.ts","sourceRoot":"","sources":["../../src/converters/toolOutputConversion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS,oBAAoB,EAAE;;;;;;;;;;;;;;;CAiBnE,CAAC;AAEH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,OAAO;;;;;WAGM,SAAS;CAAE,CAAC"}
|