@assistant-ui/ai-sdk 0.0.11 → 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 +48 -22
- package/dist/converters/convertMessage.js.map +1 -1
- 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 -109
- 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 +5 -5
- 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 +11 -10
- package/src/converters/convertMessage.test.ts +120 -2
- package/src/converters/convertMessage.tool-args-status.test.tsx +185 -0
- package/src/converters/convertMessage.ts +60 -19
- package/src/converters/toCreateMessage.test.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 +111 -0
- package/src/runtime/useExternalHistory.ts +14 -210
- package/src/runtime/useStreamingTiming.ts +2 -2
- package/src/tools/generativeTools.test.ts +1 -1
- package/src/tools/generativeTools.ts +5 -6
- 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
|
@@ -5,13 +5,15 @@ import { type ReadonlyJSONObject } from "assistant-stream/utils";
|
|
|
5
5
|
export type AISDKMessageConverterMetadata = useExternalMessageConverter.Metadata & {
|
|
6
6
|
toolArgsKeyOrderCache?: Map<string, Map<string, string[]>>;
|
|
7
7
|
/**
|
|
8
|
-
* Frozen
|
|
9
|
-
* by call, since the text carries
|
|
10
|
-
* call/input pair skips serialization;
|
|
11
|
-
* the input is unreachable.
|
|
12
|
-
* deterministic key order.
|
|
8
|
+
* Frozen text and completion-marked args keyed weakly by a settled tool
|
|
9
|
+
* call's input object, then by call, since the text carries its streamed key
|
|
10
|
+
* order. A known call/input pair skips serialization and parsing; entries
|
|
11
|
+
* become collectible once the input is unreachable.
|
|
13
12
|
*/
|
|
14
|
-
toolArgsTextCache?: WeakMap<ReadonlyJSONObject, Map<string,
|
|
13
|
+
toolArgsTextCache?: WeakMap<ReadonlyJSONObject, Map<string, {
|
|
14
|
+
argsText: string;
|
|
15
|
+
args: ReadonlyJSONObject;
|
|
16
|
+
}>>;
|
|
15
17
|
toolLastInputCache?: Map<string, ReadonlyJSONObject>;
|
|
16
18
|
mcpAppMetadataCache?: Map<string, McpAppMetadata>;
|
|
17
19
|
toolArtifacts?: ReadonlyMap<string, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertMessage.d.ts","sourceRoot":"","sources":["../../src/converters/convertMessage.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"convertMessage.d.ts","sourceRoot":"","sources":["../../src/converters/convertMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,IAAI,CAAC;AACZ,OAAO,EAEL,KAAK,2BAA2B,EACjC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAcL,KAAK,cAAc,EAEnB,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EACjC,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,wBAAwB,CAAC;AA6BhC,MAAM,MAAM,6BAA6B,GACvC,2BAA2B,CAAC,QAAQ,GAAG;IACrC,qBAAqB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC3D;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CACzB,kBAAkB,EAClB,GAAG,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,kBAAkB,CAAA;KAAE,CAAC,CAC5D,CAAC;IACF,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACrD,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAClD,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IACpE,iCAAiC,CAAC,EAAE,OAAO,CAAC;IAC5C,qBAAqB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC;IAC1E,wBAAwB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/C,yBAAyB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChD,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C,CAAC;AAwpBJ,eAAO,MAAM,qBAAqB;;;;;;;;+HAltBd,qDAAyB;8HACqB,qDAC9C;;;CA+xBnB,CAAC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { normalizeToolApprovalAnswers } from "./toolApprovalAnswers.js";
|
|
2
|
-
import { unwrapModelContentEnvelope } from "./modelContentEnvelope.js";
|
|
3
2
|
import { stableStringifyToolArgs } from "@assistant-ui/core/internal";
|
|
4
3
|
import { getToolName, isCustomContentUIPart, isReasoningFileUIPart, isToolUIPart } from "ai";
|
|
5
4
|
import { createMessageConverter } from "@assistant-ui/core/react";
|
|
6
5
|
import { isMcpAppUri } from "@assistant-ui/core";
|
|
6
|
+
import { markPartialJsonObjectComplete, unwrapModelContentEnvelope } from "assistant-stream/internal";
|
|
7
7
|
import { parsePartialJsonObject } from "assistant-stream/utils";
|
|
8
8
|
//#region src/converters/convertMessage.ts
|
|
9
9
|
const THREAD_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -212,14 +212,27 @@ const uiPartStateToStatus = (state) => {
|
|
|
212
212
|
if (state === "streaming") return { type: "running" };
|
|
213
213
|
if (state === "done") return { type: "complete" };
|
|
214
214
|
};
|
|
215
|
+
const toSystemContent = (content) => {
|
|
216
|
+
const text = content.filter((part) => part.type === "text");
|
|
217
|
+
if (text.length === 1) return text;
|
|
218
|
+
const providerMetadata = text.reduce((merged, part) => part.providerMetadata != null ? {
|
|
219
|
+
...merged,
|
|
220
|
+
...part.providerMetadata
|
|
221
|
+
} : merged, {});
|
|
222
|
+
return [{
|
|
223
|
+
type: "text",
|
|
224
|
+
text: text.map((part) => part.text).join(""),
|
|
225
|
+
...Object.keys(providerMetadata).length > 0 && { providerMetadata }
|
|
226
|
+
}];
|
|
227
|
+
};
|
|
215
228
|
function convertParts(message, metadata) {
|
|
216
229
|
if (!message.parts || message.parts.length === 0) return [];
|
|
217
|
-
const converted = message.parts.filter((p) => p.type !== "step-start" && (message.role !== "user" || p.type !== "file")).map((part) => {
|
|
230
|
+
const converted = message.parts.filter((p) => typeof p?.type === "string" && p.type !== "step-start" && (message.role !== "user" || p.type !== "file")).map((part) => {
|
|
218
231
|
if (part.type === "text") {
|
|
219
232
|
const status = uiPartStateToStatus(part.state);
|
|
220
233
|
return {
|
|
221
234
|
type: "text",
|
|
222
|
-
text: part.text,
|
|
235
|
+
text: part.text ?? "",
|
|
223
236
|
...status != null ? { status } : void 0,
|
|
224
237
|
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : void 0
|
|
225
238
|
};
|
|
@@ -234,7 +247,7 @@ function convertParts(message, metadata) {
|
|
|
234
247
|
};
|
|
235
248
|
}
|
|
236
249
|
if (isToolUIPart(part)) {
|
|
237
|
-
const toolName = getToolName(part);
|
|
250
|
+
const toolName = getToolName(part) ?? "";
|
|
238
251
|
const toolCallId = part.toolCallId;
|
|
239
252
|
const argsKeyOrderCacheKey = `${message.id}:${toolCallId}`;
|
|
240
253
|
const rawInput = part.input ?? ("rawInput" in part ? part.rawInput : void 0);
|
|
@@ -263,12 +276,19 @@ function convertParts(message, metadata) {
|
|
|
263
276
|
argsText = stripClosingDelimiters(argsText);
|
|
264
277
|
args = parsePartialJsonObject(argsText) ?? args;
|
|
265
278
|
} else {
|
|
266
|
-
const
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
279
|
+
const inputArgs = args;
|
|
280
|
+
const frozen = metadata.toolArgsTextCache?.get(inputArgs) ?? /* @__PURE__ */ new Map();
|
|
281
|
+
const frozenEntry = frozen.get(argsKeyOrderCacheKey);
|
|
282
|
+
if (frozenEntry !== void 0) {
|
|
283
|
+
argsText = frozenEntry.argsText;
|
|
284
|
+
args = frozenEntry.args;
|
|
285
|
+
} else {
|
|
270
286
|
argsText = stableStringifyToolArgs(metadata.toolArgsKeyOrderCache, argsKeyOrderCacheKey, args);
|
|
271
|
-
|
|
287
|
+
args = markPartialJsonObjectComplete(args);
|
|
288
|
+
metadata.toolArgsTextCache?.set(inputArgs, frozen.set(argsKeyOrderCacheKey, {
|
|
289
|
+
argsText,
|
|
290
|
+
args
|
|
291
|
+
}));
|
|
272
292
|
}
|
|
273
293
|
metadata.toolArgsKeyOrderCache?.delete(argsKeyOrderCacheKey);
|
|
274
294
|
if (part.state === "output-available" || part.state === "output-error" || part.state === "output-denied") metadata.toolLastInputCache?.delete(argsKeyOrderCacheKey);
|
|
@@ -302,12 +322,15 @@ function convertParts(message, metadata) {
|
|
|
302
322
|
...part.title != null ? { title: part.title } : void 0,
|
|
303
323
|
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : void 0
|
|
304
324
|
};
|
|
305
|
-
if (part.type === "file")
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
325
|
+
if (part.type === "file") {
|
|
326
|
+
if (typeof part.url !== "string") return null;
|
|
327
|
+
return {
|
|
328
|
+
type: "file",
|
|
329
|
+
data: part.url,
|
|
330
|
+
mimeType: part.mediaType ?? "unknown/unknown",
|
|
331
|
+
...part.filename != null && { filename: part.filename }
|
|
332
|
+
};
|
|
333
|
+
}
|
|
311
334
|
if (part.type === "source-document") return {
|
|
312
335
|
type: "source",
|
|
313
336
|
sourceType: "document",
|
|
@@ -323,11 +346,14 @@ function convertParts(message, metadata) {
|
|
|
323
346
|
name: part.type.substring(5),
|
|
324
347
|
data: part.data
|
|
325
348
|
};
|
|
326
|
-
if (isReasoningFileUIPart(part))
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
349
|
+
if (isReasoningFileUIPart(part)) {
|
|
350
|
+
if (typeof part.url !== "string") return null;
|
|
351
|
+
return {
|
|
352
|
+
type: "file",
|
|
353
|
+
data: part.url,
|
|
354
|
+
mimeType: part.mediaType ?? "unknown/unknown"
|
|
355
|
+
};
|
|
356
|
+
}
|
|
331
357
|
if (isCustomContentUIPart(part)) return {
|
|
332
358
|
type: "data",
|
|
333
359
|
name: part.kind,
|
|
@@ -354,7 +380,7 @@ const AISDKMessageConverter = createMessageConverter((message, metadata) => {
|
|
|
354
380
|
id: message.id,
|
|
355
381
|
createdAt,
|
|
356
382
|
content,
|
|
357
|
-
attachments: message.parts?.filter((p) => p
|
|
383
|
+
attachments: message.parts?.filter((p) => p?.type === "file" && typeof p.url === "string").map((part, idx) => {
|
|
358
384
|
const mediaType = part.mediaType ?? "unknown/unknown";
|
|
359
385
|
const isImage = mediaType.startsWith("image/");
|
|
360
386
|
return {
|
|
@@ -385,7 +411,7 @@ const AISDKMessageConverter = createMessageConverter((message, metadata) => {
|
|
|
385
411
|
role: message.role,
|
|
386
412
|
id: message.id,
|
|
387
413
|
createdAt,
|
|
388
|
-
content,
|
|
414
|
+
content: message.role === "system" ? toSystemContent(content) : content,
|
|
389
415
|
...message.role === "assistant" && metadata.cancelledStatusMessageIds?.has(message.id) ? { status: {
|
|
390
416
|
type: "incomplete",
|
|
391
417
|
reason: "cancelled"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertMessage.js","names":["isToolUIPart","isReasoningFileUIPart","isCustomContentUIPart","getToolName","UIMessage","createMessageConverter","unstable_createMessageConverter","useExternalMessageConverter","isMcpAppUri","ReasoningMessagePart","ToolApprovalOption","ToolApprovalQuestion","ToolApprovalQuestionOption","ToolCallMessagePart","TextMessagePart","DataMessagePart","PartProviderMetadata","SourceMessagePart","SourceProviderMetadata","FileMessagePart","ThreadMessageLike","McpAppMetadata","MessagePartStreamStatus","RespondToToolApprovalOptions","Unstable_ToolInteractionLog","normalizeToolApprovalAnswers","stableStringifyToolArgs","parsePartialJsonObject","ReadonlyJSONObject","unwrapModelContentEnvelope","MessageMetadata","THREAD_METADATA_KEYS","Set","toThreadMetadata","metadata","undefined","result","Record","extra","Object","create","key","value","entries","has","keys","length","custom","AISDKMessageConverterMetadata","Metadata","toolArgsKeyOrderCache","Map","toolArgsTextCache","WeakMap","toolLastInputCache","mcpAppMetadataCache","toolArtifacts","ReadonlyMap","toolInteractions","supportsRichToolApprovalResponses","toolApprovalResponses","cancelledToolApprovalIds","ReadonlySet","cancelledStatusMessageIds","optimisticMessageId","stripClosingDelimiters","json","end","includes","slice","MCP_APP_METADATA_CACHE_MAX","extractMcpAppMetadata","part","cache","toolMetadata","toolApp","app","meta","callProviderMetadata","mcp","providerApp","apps","candidate","candidateApp","resourceUri","push","mimeType","Array","isArray","visibility","serverId","a","output","outMeta","_meta","ui","uiMeta","flat","cacheKey","cached","get","delete","set","out","K","filter","v","size","oldest","next","normalizeToolApprovalOptions","options","flatMap","option","id","kind","confirm","confirmDetails","label","description","grants","grant","title","normalizeToolApprovalQuestions","questions","question","prompt","header","multiple","allowFreeform","APPROVAL_DESCRIPTOR_FIELDS","const","readApprovalDescriptor","descriptor","fields","hasOwn","getToolApprovalAndInterrupt","approval","toolStatus","type","payload","NonNullable","interrupt","rawApproval","approved","resolution","response","reason","isAutomatic","display","dismissible","optionId","text","answers","additionalApprovalFields","normalizedOptions","normalizedQuestions","normalizedAnswers","requestReason","MessageContent","Exclude","uiPartStateToStatus","state","convertParts","message","parts","converted","p","role","map","status","providerMetadata","toolName","toolCallId","argsKeyOrderCacheKey","rawInput","input","args","modelContent","isError","unwrapped","error","errorText","argsText","frozen","frozenText","toolStatuses","mcpApp","artifact","interactions","unstable_interactions","preliminary","isPreliminary","sourceType","sourceId","url","data","mediaType","filename","startsWith","name","substring","console","warn","Boolean","seenToolCallIds","add","AISDKMessageConverter","createdAt","Date","content","attachments","idx","isImage","toString","image","contentType","timing","messageTiming","isOptimistic","unstable_createMessageConverter"],"sources":["../../src/converters/convertMessage.ts"],"sourcesContent":["import {\n isToolUIPart,\n isReasoningFileUIPart,\n isCustomContentUIPart,\n getToolName,\n type UIMessage,\n} from \"ai\";\nimport {\n createMessageConverter as unstable_createMessageConverter,\n type useExternalMessageConverter,\n} from \"@assistant-ui/core/react\";\nimport {\n isMcpAppUri,\n type ReasoningMessagePart,\n type ToolApprovalOption,\n type ToolApprovalQuestion,\n type ToolApprovalQuestionOption,\n type ToolCallMessagePart,\n type TextMessagePart,\n type DataMessagePart,\n type PartProviderMetadata,\n type SourceMessagePart,\n type SourceProviderMetadata,\n type FileMessagePart,\n type ThreadMessageLike,\n type McpAppMetadata,\n type MessagePartStreamStatus,\n type RespondToToolApprovalOptions,\n type Unstable_ToolInteractionLog,\n} from \"@assistant-ui/core\";\nimport { normalizeToolApprovalAnswers } from \"./toolApprovalAnswers\";\nimport { stableStringifyToolArgs } from \"@assistant-ui/core/internal\";\nimport {\n parsePartialJsonObject,\n type ReadonlyJSONObject,\n} from \"assistant-stream/utils\";\nimport { unwrapModelContentEnvelope } from \"./modelContentEnvelope\";\n\ntype MessageMetadata = ThreadMessageLike[\"metadata\"];\n\nconst THREAD_METADATA_KEYS = new Set([\n \"unstable_state\",\n \"unstable_annotations\",\n \"unstable_data\",\n \"steps\",\n \"timing\",\n \"submittedFeedback\",\n \"isOptimistic\",\n \"modality\",\n \"custom\",\n]);\n\nconst toThreadMetadata = (metadata: unknown): MessageMetadata => {\n if (!metadata || typeof metadata !== \"object\") return undefined;\n const result: Record<string, unknown> = {};\n const extra = Object.create(null) as Record<string, unknown>;\n for (const [key, value] of Object.entries(metadata)) {\n (THREAD_METADATA_KEYS.has(key) ? result : extra)[key] = value;\n }\n if (Object.keys(extra).length > 0) {\n result.custom = { ...extra, ...(result.custom as object | undefined) };\n }\n return result as MessageMetadata;\n};\nexport type AISDKMessageConverterMetadata =\n useExternalMessageConverter.Metadata & {\n toolArgsKeyOrderCache?: Map<string, Map<string, string[]>>;\n /**\n * Frozen `argsText` keyed weakly by a settled tool call's input object, then\n * by call, since the text carries the call's streamed key order. A known\n * call/input pair skips serialization; the entries become collectible once\n * the input is unreachable. A fresh input object re-serializes in its own\n * deterministic key order.\n */\n toolArgsTextCache?: WeakMap<ReadonlyJSONObject, Map<string, string>>;\n toolLastInputCache?: Map<string, ReadonlyJSONObject>;\n mcpAppMetadataCache?: Map<string, McpAppMetadata>;\n toolArtifacts?: ReadonlyMap<string, unknown>;\n toolInteractions?: ReadonlyMap<string, Unstable_ToolInteractionLog>;\n supportsRichToolApprovalResponses?: boolean;\n toolApprovalResponses?: ReadonlyMap<string, RespondToToolApprovalOptions>;\n cancelledToolApprovalIds?: ReadonlySet<string>;\n cancelledStatusMessageIds?: ReadonlySet<string>;\n /** Id of the currently-streaming message, flagged optimistic (#4037). */\n optimisticMessageId?: string | undefined;\n };\n\nfunction stripClosingDelimiters(json: string): string {\n let end = json.length;\n while (end > 0 && '}]\"'.includes(json[end - 1]!)) end--;\n return json.slice(0, end);\n}\n\nconst MCP_APP_METADATA_CACHE_MAX = 100;\n\nfunction extractMcpAppMetadata(\n part: unknown,\n cache: Map<string, McpAppMetadata> | undefined,\n): McpAppMetadata | undefined {\n if (!part || typeof part !== \"object\") return undefined;\n const toolMetadata = (part as { toolMetadata?: unknown }).toolMetadata;\n const toolApp =\n toolMetadata && typeof toolMetadata === \"object\"\n ? (toolMetadata as { app?: unknown }).app\n : undefined;\n const meta = (part as { callProviderMetadata?: unknown })\n .callProviderMetadata;\n const mcp =\n meta && typeof meta === \"object\"\n ? (meta as { mcp?: unknown }).mcp\n : undefined;\n const providerApp =\n mcp && typeof mcp === \"object\" ? (mcp as { app?: unknown }).app : undefined;\n\n const apps: Record<string, unknown>[] = [];\n for (const candidate of [toolApp, providerApp]) {\n if (!candidate || typeof candidate !== \"object\") continue;\n const candidateApp = candidate as Record<string, unknown>;\n const resourceUri = candidateApp[\"resourceUri\"];\n if (typeof resourceUri !== \"string\" || !isMcpAppUri(resourceUri)) continue;\n apps.push({\n resourceUri,\n ...(typeof candidateApp[\"mimeType\"] === \"string\" && {\n mimeType: candidateApp[\"mimeType\"],\n }),\n ...(Array.isArray(candidateApp[\"visibility\"]) && {\n visibility: candidateApp[\"visibility\"],\n }),\n ...(candidate === providerApp &&\n typeof candidateApp[\"serverId\"] === \"string\" &&\n candidateApp[\"serverId\"].length > 0 && {\n serverId: candidateApp[\"serverId\"],\n }),\n });\n }\n\n let a: Record<string, unknown>;\n if (apps.length > 0) {\n a = { ...(apps[1] ?? {}), ...apps[0]! };\n } else {\n // MCP-UI tools surface the pointer on result._meta: canonical nested\n // `ui.resourceUri`, or the deprecated flat `\"ui/resourceUri\"` key.\n const output = (part as { output?: unknown }).output;\n const outMeta =\n output && typeof output === \"object\"\n ? (output as { _meta?: unknown })._meta\n : undefined;\n const ui =\n outMeta && typeof outMeta === \"object\"\n ? (outMeta as Record<string, unknown>)[\"ui\"]\n : undefined;\n if (\n ui &&\n typeof ui === \"object\" &&\n typeof (ui as Record<string, unknown>)[\"resourceUri\"] === \"string\" &&\n isMcpAppUri((ui as Record<string, unknown>)[\"resourceUri\"] as string)\n ) {\n // Only the spec'd ui fields cross from the result body; serverId is a\n // routing key and stays transport-derived via callProviderMetadata.\n const uiMeta = ui as Record<string, unknown>;\n a = {\n resourceUri: uiMeta[\"resourceUri\"],\n ...(Array.isArray(uiMeta[\"visibility\"])\n ? { visibility: uiMeta[\"visibility\"] }\n : {}),\n };\n } else {\n const flat =\n outMeta && typeof outMeta === \"object\"\n ? (outMeta as Record<string, unknown>)[\"ui/resourceUri\"]\n : undefined;\n if (typeof flat !== \"string\" || !isMcpAppUri(flat)) return undefined;\n a = { resourceUri: flat };\n }\n }\n if (typeof a[\"resourceUri\"] !== \"string\") return undefined;\n if (!isMcpAppUri(a[\"resourceUri\"])) return undefined;\n const cacheKey = `${typeof a[\"serverId\"] === \"string\" ? a[\"serverId\"] : \"\"} ${a[\"resourceUri\"]}`;\n const cached = cache?.get(cacheKey);\n if (cached) {\n cache!.delete(cacheKey);\n cache!.set(cacheKey, cached);\n return cached;\n }\n const out: { -readonly [K in keyof McpAppMetadata]: McpAppMetadata[K] } = {\n resourceUri: a[\"resourceUri\"],\n };\n if (typeof a[\"mimeType\"] === \"string\") out.mimeType = a[\"mimeType\"];\n if (Array.isArray(a[\"visibility\"])) {\n out.visibility = a[\"visibility\"].filter(\n (v): v is \"model\" | \"app\" => v === \"model\" || v === \"app\",\n );\n }\n if (typeof a[\"serverId\"] === \"string\" && a[\"serverId\"].length > 0)\n out.serverId = a[\"serverId\"];\n if (cache) {\n if (cache.size >= MCP_APP_METADATA_CACHE_MAX) {\n const oldest = cache.keys().next().value;\n if (oldest !== undefined) cache.delete(oldest);\n }\n cache.set(cacheKey, out);\n }\n return out;\n}\n\nconst normalizeToolApprovalOptions = (\n options: unknown,\n): readonly ToolApprovalOption[] | undefined => {\n if (!Array.isArray(options)) return undefined;\n\n return options.flatMap<ToolApprovalOption>((value) => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return [];\n const option = value as Record<string, unknown>;\n if (typeof option.id !== \"string\" || typeof option.kind !== \"string\")\n return [];\n\n const confirm = option.confirm;\n const confirmDetails =\n confirm && typeof confirm === \"object\" && !Array.isArray(confirm)\n ? (confirm as Record<string, unknown>)\n : undefined;\n\n return [\n {\n id: option.id,\n kind: option.kind,\n ...(typeof option.label === \"string\" && { label: option.label }),\n ...(typeof option.description === \"string\" && {\n description: option.description,\n }),\n ...(Array.isArray(option.grants) && {\n grants: option.grants.filter(\n (grant): grant is string => typeof grant === \"string\",\n ),\n }),\n ...(typeof confirm === \"boolean\"\n ? { confirm }\n : confirmDetails\n ? {\n confirm: {\n ...(typeof confirmDetails.title === \"string\" && {\n title: confirmDetails.title,\n }),\n ...(typeof confirmDetails.description === \"string\" && {\n description: confirmDetails.description,\n }),\n },\n }\n : {}),\n },\n ];\n });\n};\n\nconst normalizeToolApprovalQuestions = (\n questions: unknown,\n): readonly ToolApprovalQuestion[] | undefined => {\n if (!Array.isArray(questions)) return undefined;\n\n return questions.flatMap<ToolApprovalQuestion>((value) => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return [];\n const question = value as Record<string, unknown>;\n if (typeof question.id !== \"string\" || typeof question.prompt !== \"string\")\n return [];\n const options = Array.isArray(question.options)\n ? question.options.flatMap<ToolApprovalQuestionOption>((option) => {\n if (!option || typeof option !== \"object\" || Array.isArray(option))\n return [];\n const { id, label, description } = option as Record<string, unknown>;\n if (typeof id !== \"string\" || typeof label !== \"string\") return [];\n return [\n {\n id,\n label,\n ...(typeof description === \"string\" && { description }),\n },\n ];\n })\n : undefined;\n\n return [\n {\n id: question.id,\n prompt: question.prompt,\n ...(typeof question.header === \"string\" && {\n header: question.header,\n }),\n ...(options && { options }),\n ...(typeof question.multiple === \"boolean\" && {\n multiple: question.multiple,\n }),\n ...(typeof question.allowFreeform === \"boolean\" && {\n allowFreeform: question.allowFreeform,\n }),\n },\n ];\n });\n};\n\nconst APPROVAL_DESCRIPTOR_FIELDS = [\n \"prompt\",\n \"display\",\n \"allowFreeform\",\n \"dismissible\",\n \"options\",\n \"optionId\",\n \"text\",\n \"questions\",\n \"answers\",\n \"resolution\",\n] as const;\n\n// The AI SDK's approval object declares none of the core request and answer\n// fields and `validateUIMessages` strips unknown ones, so a host streams or\n// persists them inside the opaque `approvalDescriptor`. Only those fields are\n// read from it: a descriptor cannot approve its own request.\nconst readApprovalDescriptor = (\n descriptor: unknown,\n): Record<string, unknown> => {\n if (\n !descriptor ||\n typeof descriptor !== \"object\" ||\n Array.isArray(descriptor)\n )\n return {};\n const fields: Record<string, unknown> = {};\n for (const key of APPROVAL_DESCRIPTOR_FIELDS) {\n if (Object.hasOwn(descriptor, key))\n fields[key] = (descriptor as Record<string, unknown>)[key];\n }\n return fields;\n};\n\nfunction getToolApprovalAndInterrupt(\n part: {\n approval?: Record<string, unknown> | undefined;\n },\n toolStatus: { type: string; payload?: unknown } | undefined,\n supportsRichToolApprovalResponses: boolean,\n toolApprovalResponses:\n | ReadonlyMap<string, RespondToToolApprovalOptions>\n | undefined,\n cancelledToolApprovalIds: ReadonlySet<string> | undefined,\n): {\n approval?: NonNullable<ToolCallMessagePart[\"approval\"]>;\n interrupt?: NonNullable<ToolCallMessagePart[\"interrupt\"]>;\n} {\n if (part.approval) {\n const rawApproval = {\n ...readApprovalDescriptor(part.approval.descriptor),\n ...part.approval,\n };\n const approval =\n typeof rawApproval.id === \"string\" &&\n rawApproval.approved === undefined &&\n rawApproval.resolution === undefined &&\n cancelledToolApprovalIds?.has(rawApproval.id)\n ? { ...rawApproval, resolution: \"cancelled\" as const }\n : rawApproval;\n const response =\n typeof approval.id === \"string\" &&\n approval.approved === undefined &&\n approval.resolution !== \"cancelled\" &&\n approval.resolution !== \"expired\"\n ? toolApprovalResponses?.get(approval.id)\n : undefined;\n // The built-in AI SDK channel sends only id, approved and reason back to\n // the server, so a request shape promising any other answer would render\n // controls whose response cannot travel.\n const {\n id,\n prompt,\n approved,\n reason,\n isAutomatic,\n resolution,\n display,\n allowFreeform,\n dismissible,\n options,\n optionId,\n text,\n questions,\n answers,\n ...additionalApprovalFields\n } = response\n ? {\n ...approval,\n approved: response.approved,\n ...(response.reason != null && { reason: response.reason }),\n ...(response.optionId != null && { optionId: response.optionId }),\n ...(response.text != null && { text: response.text }),\n ...(response.answers != null && { answers: response.answers }),\n }\n : approval;\n const normalizedOptions = supportsRichToolApprovalResponses\n ? normalizeToolApprovalOptions(options)\n : undefined;\n const normalizedQuestions = supportsRichToolApprovalResponses\n ? normalizeToolApprovalQuestions(questions)\n : undefined;\n const normalizedAnswers = supportsRichToolApprovalResponses\n ? normalizeToolApprovalAnswers(answers)\n : undefined;\n const requestReason = additionalApprovalFields.requestReason;\n if (typeof id === \"string\")\n return {\n approval: {\n ...additionalApprovalFields,\n id,\n ...(typeof prompt === \"string\"\n ? { prompt }\n : typeof requestReason === \"string\"\n ? { prompt: requestReason }\n : {}),\n ...(typeof approved === \"boolean\" && { approved }),\n ...(typeof reason === \"string\" && { reason }),\n ...(isAutomatic === true && { isAutomatic: true }),\n ...(supportsRichToolApprovalResponses && {\n ...((display === \"decision\" ||\n display === \"select\" ||\n display === \"text\" ||\n display === \"questions\") && { display }),\n ...(typeof allowFreeform === \"boolean\" && { allowFreeform }),\n ...(typeof dismissible === \"boolean\" && { dismissible }),\n ...(normalizedOptions && { options: normalizedOptions }),\n ...(typeof optionId === \"string\" && { optionId }),\n ...(typeof text === \"string\" && { text }),\n ...(normalizedQuestions && { questions: normalizedQuestions }),\n ...(normalizedAnswers && { answers: normalizedAnswers }),\n }),\n ...((resolution === \"cancelled\" || resolution === \"expired\") && {\n resolution,\n }),\n } as NonNullable<ToolCallMessagePart[\"approval\"]>,\n };\n }\n\n if (toolStatus?.type === \"interrupt\") {\n return {\n interrupt: toolStatus.payload as NonNullable<\n ToolCallMessagePart[\"interrupt\"]\n >,\n };\n }\n\n return {};\n}\n\ntype MessageContent = Exclude<ThreadMessageLike[\"content\"], string>;\n\nconst uiPartStateToStatus = (\n state: \"streaming\" | \"done\" | undefined,\n): MessagePartStreamStatus | undefined => {\n if (state === \"streaming\") return { type: \"running\" };\n if (state === \"done\") return { type: \"complete\" };\n return undefined;\n};\n\nfunction convertParts(\n message: UIMessage,\n metadata: AISDKMessageConverterMetadata,\n): MessageContent {\n if (!message.parts || message.parts.length === 0) {\n return [];\n }\n\n const converted = message.parts\n .filter(\n (p) =>\n p.type !== \"step-start\" &&\n (message.role !== \"user\" || p.type !== \"file\"),\n )\n .map((part) => {\n if (part.type === \"text\") {\n const status = uiPartStateToStatus(part.state);\n return {\n type: \"text\",\n text: part.text,\n ...(status != null ? { status } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata: part.providerMetadata as PartProviderMetadata,\n }\n : undefined),\n } satisfies TextMessagePart;\n }\n\n if (part.type === \"reasoning\") {\n const status = uiPartStateToStatus(part.state);\n return {\n type: \"reasoning\",\n text: part.text,\n ...(status != null ? { status } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata: part.providerMetadata as PartProviderMetadata,\n }\n : undefined),\n } satisfies ReasoningMessagePart;\n }\n\n if (isToolUIPart(part)) {\n const toolName = getToolName(part);\n const toolCallId = part.toolCallId;\n const argsKeyOrderCacheKey = `${message.id}:${toolCallId}`;\n\n // A tool call that streamed complete arguments then failed schema\n // validation keeps them in `rawInput`, not `input`; reading `input`\n // alone would convert the error snapshot to `{}` and hide the input.\n const rawInput = (part.input ??\n (\"rawInput\" in part ? part.rawInput : undefined)) as\n | ReadonlyJSONObject\n | null\n | undefined;\n let args: ReadonlyJSONObject;\n if (\n rawInput != null &&\n typeof rawInput === \"object\" &&\n !Array.isArray(rawInput)\n ) {\n args = rawInput;\n metadata.toolLastInputCache?.set(argsKeyOrderCacheKey, args);\n } else {\n args = metadata.toolLastInputCache?.get(argsKeyOrderCacheKey) ?? {};\n }\n\n let result: unknown;\n let modelContent: ToolCallMessagePart[\"modelContent\"];\n let isError = false;\n\n if (part.state === \"output-available\") {\n const unwrapped = unwrapModelContentEnvelope(part.output);\n result = unwrapped.result;\n modelContent = unwrapped.modelContent;\n } else if (part.state === \"output-error\") {\n isError = true;\n result = { error: part.errorText };\n } else if (part.state === \"output-denied\") {\n isError = true;\n result = {\n error:\n (part as { approval?: { reason?: string } }).approval?.reason ||\n \"Tool approval denied\",\n };\n }\n\n let argsText: string;\n if (part.state === \"input-streaming\") {\n argsText = stableStringifyToolArgs(\n metadata.toolArgsKeyOrderCache,\n argsKeyOrderCacheKey,\n args,\n );\n // strip closing delimiters added by the AI SDK's fix-json\n argsText = stripClosingDelimiters(argsText);\n // Re-parse so args carries the partial-JSON meta that marks which\n // field is still mid-arrival, like every argsText-based runtime.\n // The key-order cache appends new keys last, so the trailing field\n // of the stripped text is the streaming frontier.\n args = parsePartialJsonObject(argsText) ?? args;\n } else {\n // A settled part is re-converted whenever its message or the converter\n // metadata changes; the text frozen on its input object skips\n // re-serializing large args while the call keeps that input. Arrival\n // order only matters while args stream, so the key-order entry is\n // released.\n const frozen =\n metadata.toolArgsTextCache?.get(args) ?? new Map<string, string>();\n const frozenText = frozen.get(argsKeyOrderCacheKey);\n if (frozenText !== undefined) {\n argsText = frozenText;\n } else {\n argsText = stableStringifyToolArgs(\n metadata.toolArgsKeyOrderCache,\n argsKeyOrderCacheKey,\n args,\n );\n metadata.toolArgsTextCache?.set(\n args,\n frozen.set(argsKeyOrderCacheKey, argsText),\n );\n }\n metadata.toolArgsKeyOrderCache?.delete(argsKeyOrderCacheKey);\n if (\n part.state === \"output-available\" ||\n part.state === \"output-error\" ||\n part.state === \"output-denied\"\n ) {\n metadata.toolLastInputCache?.delete(argsKeyOrderCacheKey);\n }\n }\n\n const toolStatus = metadata.toolStatuses?.[toolCallId];\n const mcpApp = extractMcpAppMetadata(\n part,\n metadata.mcpAppMetadataCache,\n );\n const artifact = metadata.toolArtifacts?.get(toolCallId);\n const interactions = metadata.toolInteractions?.get(toolCallId);\n return {\n type: \"tool-call\",\n toolName,\n toolCallId,\n argsText,\n args,\n result,\n isError,\n ...(artifact !== undefined && { artifact }),\n ...(interactions !== undefined && {\n unstable_interactions: interactions,\n }),\n ...(part.state === \"output-available\" &&\n part.preliminary === true && { isPreliminary: true }),\n ...(modelContent !== undefined && { modelContent }),\n ...(mcpApp && { mcp: { app: mcpApp } }),\n ...(part.callProviderMetadata != null\n ? {\n providerMetadata:\n part.callProviderMetadata as PartProviderMetadata,\n }\n : undefined),\n ...getToolApprovalAndInterrupt(\n part,\n toolStatus,\n metadata.supportsRichToolApprovalResponses === true,\n metadata.toolApprovalResponses,\n metadata.cancelledToolApprovalIds,\n ),\n } satisfies ToolCallMessagePart;\n }\n\n if (part.type === \"source-url\") {\n return {\n type: \"source\",\n sourceType: \"url\",\n id: part.sourceId,\n url: part.url,\n ...(part.title != null ? { title: part.title } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata:\n part.providerMetadata as SourceProviderMetadata,\n }\n : undefined),\n } satisfies SourceMessagePart;\n }\n\n if (part.type === \"file\") {\n return {\n type: \"file\",\n data: part.url,\n mimeType: part.mediaType,\n ...(part.filename != null && { filename: part.filename }),\n } satisfies FileMessagePart;\n }\n\n if (part.type === \"source-document\") {\n return {\n type: \"source\",\n sourceType: \"document\",\n id: part.sourceId,\n title: part.title,\n mediaType: part.mediaType,\n ...(part.filename != null ? { filename: part.filename } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata:\n part.providerMetadata as SourceProviderMetadata,\n }\n : undefined),\n } satisfies SourceMessagePart;\n }\n\n if (part.type.startsWith(\"data-\")) {\n return {\n type: \"data\",\n ...(\"id\" in part && typeof part.id === \"string\"\n ? { id: part.id }\n : undefined),\n name: part.type.substring(5),\n data: (part as any).data,\n } satisfies DataMessagePart;\n }\n\n if (isReasoningFileUIPart(part)) {\n return {\n type: \"file\",\n data: part.url,\n mimeType: part.mediaType,\n } satisfies FileMessagePart;\n }\n\n if (isCustomContentUIPart(part)) {\n return {\n type: \"data\",\n name: part.kind,\n data: part.providerMetadata ?? null,\n } satisfies DataMessagePart;\n }\n\n console.warn(`Unsupported message part type: ${part.type}`);\n return null;\n })\n .filter(Boolean) as MessageContent[number][];\n\n const seenToolCallIds = new Set<string>();\n return converted.filter((part) => {\n if (part.type === \"tool-call\" && part.toolCallId != null) {\n if (seenToolCallIds.has(part.toolCallId)) return false;\n seenToolCallIds.add(part.toolCallId);\n }\n return true;\n });\n}\n\nexport const AISDKMessageConverter = unstable_createMessageConverter(\n (message: UIMessage, metadata: AISDKMessageConverterMetadata) => {\n const createdAt = new Date();\n const content = convertParts(message, metadata);\n\n switch (message.role) {\n case \"user\":\n return {\n role: \"user\",\n id: message.id,\n createdAt,\n content,\n attachments: message.parts\n ?.filter((p) => p.type === \"file\")\n .map((part, idx) => {\n const mediaType = part.mediaType ?? \"unknown/unknown\";\n const isImage = mediaType.startsWith(\"image/\");\n return {\n id: idx.toString(),\n type: isImage ? \"image\" : \"file\",\n name: part.filename ?? \"file\",\n content: [\n isImage\n ? {\n type: \"image\",\n image: part.url,\n filename: part.filename!,\n }\n : {\n type: \"file\",\n filename: part.filename!,\n data: part.url,\n mimeType: mediaType,\n },\n ],\n contentType: mediaType,\n status: { type: \"complete\" as const },\n };\n }),\n metadata: toThreadMetadata(message.metadata),\n };\n\n case \"system\":\n case \"assistant\": {\n const timing = metadata.messageTiming?.[message.id];\n const isOptimistic =\n message.role === \"assistant\" &&\n message.id === metadata.optimisticMessageId;\n return {\n role: message.role,\n id: message.id,\n createdAt,\n content,\n ...(message.role === \"assistant\" &&\n metadata.cancelledStatusMessageIds?.has(message.id)\n ? {\n status: {\n type: \"incomplete\" as const,\n reason: \"cancelled\" as const,\n },\n }\n : undefined),\n metadata: {\n ...toThreadMetadata(message.metadata),\n ...(timing && { timing }),\n ...(isOptimistic && { isOptimistic: true }),\n },\n };\n }\n\n default:\n console.warn(`Unsupported message role: ${message.role}`);\n return [];\n }\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"convertMessage.js","names":["isToolUIPart","isReasoningFileUIPart","isCustomContentUIPart","getToolName","FileUIPart","UIMessage","createMessageConverter","unstable_createMessageConverter","useExternalMessageConverter","isMcpAppUri","ReasoningMessagePart","ToolApprovalOption","ToolApprovalQuestion","ToolApprovalQuestionOption","ToolCallMessagePart","TextMessagePart","DataMessagePart","PartProviderMetadata","SourceMessagePart","SourceProviderMetadata","FileMessagePart","ThreadMessageLike","McpAppMetadata","MessagePartStreamStatus","RespondToToolApprovalOptions","Unstable_ToolInteractionLog","normalizeToolApprovalAnswers","stableStringifyToolArgs","markPartialJsonObjectComplete","parsePartialJsonObject","ReadonlyJSONObject","unwrapModelContentEnvelope","MessageMetadata","THREAD_METADATA_KEYS","Set","toThreadMetadata","metadata","undefined","result","Record","extra","Object","create","key","value","entries","has","keys","length","custom","AISDKMessageConverterMetadata","Metadata","toolArgsKeyOrderCache","Map","toolArgsTextCache","WeakMap","argsText","args","toolLastInputCache","mcpAppMetadataCache","toolArtifacts","ReadonlyMap","toolInteractions","supportsRichToolApprovalResponses","toolApprovalResponses","cancelledToolApprovalIds","ReadonlySet","cancelledStatusMessageIds","optimisticMessageId","stripClosingDelimiters","json","end","includes","slice","MCP_APP_METADATA_CACHE_MAX","extractMcpAppMetadata","part","cache","toolMetadata","toolApp","app","meta","callProviderMetadata","mcp","providerApp","apps","candidate","candidateApp","resourceUri","push","mimeType","Array","isArray","visibility","serverId","a","output","outMeta","_meta","ui","uiMeta","flat","cacheKey","cached","get","delete","set","out","K","filter","v","size","oldest","next","normalizeToolApprovalOptions","options","flatMap","option","id","kind","confirm","confirmDetails","label","description","grants","grant","title","normalizeToolApprovalQuestions","questions","question","prompt","header","multiple","allowFreeform","APPROVAL_DESCRIPTOR_FIELDS","const","readApprovalDescriptor","descriptor","fields","hasOwn","getToolApprovalAndInterrupt","approval","toolStatus","type","payload","NonNullable","interrupt","rawApproval","approved","resolution","response","reason","isAutomatic","display","dismissible","optionId","text","answers","additionalApprovalFields","normalizedOptions","normalizedQuestions","normalizedAnswers","requestReason","MessageContent","Exclude","uiPartStateToStatus","state","toSystemContent","content","providerMetadata","reduce","merged","map","join","convertParts","message","parts","converted","p","role","status","toolName","toolCallId","argsKeyOrderCacheKey","rawInput","input","modelContent","isError","unwrapped","error","errorText","inputArgs","frozen","frozenEntry","toolStatuses","mcpApp","artifact","interactions","unstable_interactions","preliminary","isPreliminary","sourceType","sourceId","url","data","mediaType","filename","startsWith","name","substring","console","warn","Boolean","seenToolCallIds","add","AISDKMessageConverter","createdAt","Date","attachments","idx","isImage","toString","image","contentType","timing","messageTiming","isOptimistic","unstable_createMessageConverter"],"sources":["../../src/converters/convertMessage.ts"],"sourcesContent":["import {\n isToolUIPart,\n isReasoningFileUIPart,\n isCustomContentUIPart,\n getToolName,\n type FileUIPart,\n type UIMessage,\n} from \"ai\";\nimport {\n createMessageConverter as unstable_createMessageConverter,\n type useExternalMessageConverter,\n} from \"@assistant-ui/core/react\";\nimport {\n isMcpAppUri,\n type ReasoningMessagePart,\n type ToolApprovalOption,\n type ToolApprovalQuestion,\n type ToolApprovalQuestionOption,\n type ToolCallMessagePart,\n type TextMessagePart,\n type DataMessagePart,\n type PartProviderMetadata,\n type SourceMessagePart,\n type SourceProviderMetadata,\n type FileMessagePart,\n type ThreadMessageLike,\n type McpAppMetadata,\n type MessagePartStreamStatus,\n type RespondToToolApprovalOptions,\n type Unstable_ToolInteractionLog,\n} from \"@assistant-ui/core\";\nimport { normalizeToolApprovalAnswers } from \"./toolApprovalAnswers\";\nimport { stableStringifyToolArgs } from \"@assistant-ui/core/internal\";\nimport { markPartialJsonObjectComplete } from \"assistant-stream/internal\";\nimport {\n parsePartialJsonObject,\n type ReadonlyJSONObject,\n} from \"assistant-stream/utils\";\nimport { unwrapModelContentEnvelope } from \"assistant-stream/internal\";\n\ntype MessageMetadata = ThreadMessageLike[\"metadata\"];\n\nconst THREAD_METADATA_KEYS = new Set([\n \"unstable_state\",\n \"unstable_annotations\",\n \"unstable_data\",\n \"steps\",\n \"timing\",\n \"submittedFeedback\",\n \"isOptimistic\",\n \"modality\",\n \"custom\",\n]);\n\nconst toThreadMetadata = (metadata: unknown): MessageMetadata => {\n if (!metadata || typeof metadata !== \"object\") return undefined;\n const result: Record<string, unknown> = {};\n const extra = Object.create(null) as Record<string, unknown>;\n for (const [key, value] of Object.entries(metadata)) {\n (THREAD_METADATA_KEYS.has(key) ? result : extra)[key] = value;\n }\n if (Object.keys(extra).length > 0) {\n result.custom = { ...extra, ...(result.custom as object | undefined) };\n }\n return result as MessageMetadata;\n};\nexport type AISDKMessageConverterMetadata =\n useExternalMessageConverter.Metadata & {\n toolArgsKeyOrderCache?: Map<string, Map<string, string[]>>;\n /**\n * Frozen text and completion-marked args keyed weakly by a settled tool\n * call's input object, then by call, since the text carries its streamed key\n * order. A known call/input pair skips serialization and parsing; entries\n * become collectible once the input is unreachable.\n */\n toolArgsTextCache?: WeakMap<\n ReadonlyJSONObject,\n Map<string, { argsText: string; args: ReadonlyJSONObject }>\n >;\n toolLastInputCache?: Map<string, ReadonlyJSONObject>;\n mcpAppMetadataCache?: Map<string, McpAppMetadata>;\n toolArtifacts?: ReadonlyMap<string, unknown>;\n toolInteractions?: ReadonlyMap<string, Unstable_ToolInteractionLog>;\n supportsRichToolApprovalResponses?: boolean;\n toolApprovalResponses?: ReadonlyMap<string, RespondToToolApprovalOptions>;\n cancelledToolApprovalIds?: ReadonlySet<string>;\n cancelledStatusMessageIds?: ReadonlySet<string>;\n /** Id of the currently-streaming message, flagged optimistic (#4037). */\n optimisticMessageId?: string | undefined;\n };\n\nfunction stripClosingDelimiters(json: string): string {\n let end = json.length;\n while (end > 0 && '}]\"'.includes(json[end - 1]!)) end--;\n return json.slice(0, end);\n}\n\nconst MCP_APP_METADATA_CACHE_MAX = 100;\n\nfunction extractMcpAppMetadata(\n part: unknown,\n cache: Map<string, McpAppMetadata> | undefined,\n): McpAppMetadata | undefined {\n if (!part || typeof part !== \"object\") return undefined;\n const toolMetadata = (part as { toolMetadata?: unknown }).toolMetadata;\n const toolApp =\n toolMetadata && typeof toolMetadata === \"object\"\n ? (toolMetadata as { app?: unknown }).app\n : undefined;\n const meta = (part as { callProviderMetadata?: unknown })\n .callProviderMetadata;\n const mcp =\n meta && typeof meta === \"object\"\n ? (meta as { mcp?: unknown }).mcp\n : undefined;\n const providerApp =\n mcp && typeof mcp === \"object\" ? (mcp as { app?: unknown }).app : undefined;\n\n const apps: Record<string, unknown>[] = [];\n for (const candidate of [toolApp, providerApp]) {\n if (!candidate || typeof candidate !== \"object\") continue;\n const candidateApp = candidate as Record<string, unknown>;\n const resourceUri = candidateApp[\"resourceUri\"];\n if (typeof resourceUri !== \"string\" || !isMcpAppUri(resourceUri)) continue;\n apps.push({\n resourceUri,\n ...(typeof candidateApp[\"mimeType\"] === \"string\" && {\n mimeType: candidateApp[\"mimeType\"],\n }),\n ...(Array.isArray(candidateApp[\"visibility\"]) && {\n visibility: candidateApp[\"visibility\"],\n }),\n ...(candidate === providerApp &&\n typeof candidateApp[\"serverId\"] === \"string\" &&\n candidateApp[\"serverId\"].length > 0 && {\n serverId: candidateApp[\"serverId\"],\n }),\n });\n }\n\n let a: Record<string, unknown>;\n if (apps.length > 0) {\n a = { ...(apps[1] ?? {}), ...apps[0]! };\n } else {\n // MCP-UI tools surface the pointer on result._meta: canonical nested\n // `ui.resourceUri`, or the deprecated flat `\"ui/resourceUri\"` key.\n const output = (part as { output?: unknown }).output;\n const outMeta =\n output && typeof output === \"object\"\n ? (output as { _meta?: unknown })._meta\n : undefined;\n const ui =\n outMeta && typeof outMeta === \"object\"\n ? (outMeta as Record<string, unknown>)[\"ui\"]\n : undefined;\n if (\n ui &&\n typeof ui === \"object\" &&\n typeof (ui as Record<string, unknown>)[\"resourceUri\"] === \"string\" &&\n isMcpAppUri((ui as Record<string, unknown>)[\"resourceUri\"] as string)\n ) {\n // Only the spec'd ui fields cross from the result body; serverId is a\n // routing key and stays transport-derived via callProviderMetadata.\n const uiMeta = ui as Record<string, unknown>;\n a = {\n resourceUri: uiMeta[\"resourceUri\"],\n ...(Array.isArray(uiMeta[\"visibility\"])\n ? { visibility: uiMeta[\"visibility\"] }\n : {}),\n };\n } else {\n const flat =\n outMeta && typeof outMeta === \"object\"\n ? (outMeta as Record<string, unknown>)[\"ui/resourceUri\"]\n : undefined;\n if (typeof flat !== \"string\" || !isMcpAppUri(flat)) return undefined;\n a = { resourceUri: flat };\n }\n }\n if (typeof a[\"resourceUri\"] !== \"string\") return undefined;\n if (!isMcpAppUri(a[\"resourceUri\"])) return undefined;\n const cacheKey = `${typeof a[\"serverId\"] === \"string\" ? a[\"serverId\"] : \"\"} ${a[\"resourceUri\"]}`;\n const cached = cache?.get(cacheKey);\n if (cached) {\n cache!.delete(cacheKey);\n cache!.set(cacheKey, cached);\n return cached;\n }\n const out: { -readonly [K in keyof McpAppMetadata]: McpAppMetadata[K] } = {\n resourceUri: a[\"resourceUri\"],\n };\n if (typeof a[\"mimeType\"] === \"string\") out.mimeType = a[\"mimeType\"];\n if (Array.isArray(a[\"visibility\"])) {\n out.visibility = a[\"visibility\"].filter(\n (v): v is \"model\" | \"app\" => v === \"model\" || v === \"app\",\n );\n }\n if (typeof a[\"serverId\"] === \"string\" && a[\"serverId\"].length > 0)\n out.serverId = a[\"serverId\"];\n if (cache) {\n if (cache.size >= MCP_APP_METADATA_CACHE_MAX) {\n const oldest = cache.keys().next().value;\n if (oldest !== undefined) cache.delete(oldest);\n }\n cache.set(cacheKey, out);\n }\n return out;\n}\n\nconst normalizeToolApprovalOptions = (\n options: unknown,\n): readonly ToolApprovalOption[] | undefined => {\n if (!Array.isArray(options)) return undefined;\n\n return options.flatMap<ToolApprovalOption>((value) => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return [];\n const option = value as Record<string, unknown>;\n if (typeof option.id !== \"string\" || typeof option.kind !== \"string\")\n return [];\n\n const confirm = option.confirm;\n const confirmDetails =\n confirm && typeof confirm === \"object\" && !Array.isArray(confirm)\n ? (confirm as Record<string, unknown>)\n : undefined;\n\n return [\n {\n id: option.id,\n kind: option.kind,\n ...(typeof option.label === \"string\" && { label: option.label }),\n ...(typeof option.description === \"string\" && {\n description: option.description,\n }),\n ...(Array.isArray(option.grants) && {\n grants: option.grants.filter(\n (grant): grant is string => typeof grant === \"string\",\n ),\n }),\n ...(typeof confirm === \"boolean\"\n ? { confirm }\n : confirmDetails\n ? {\n confirm: {\n ...(typeof confirmDetails.title === \"string\" && {\n title: confirmDetails.title,\n }),\n ...(typeof confirmDetails.description === \"string\" && {\n description: confirmDetails.description,\n }),\n },\n }\n : {}),\n },\n ];\n });\n};\n\nconst normalizeToolApprovalQuestions = (\n questions: unknown,\n): readonly ToolApprovalQuestion[] | undefined => {\n if (!Array.isArray(questions)) return undefined;\n\n return questions.flatMap<ToolApprovalQuestion>((value) => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return [];\n const question = value as Record<string, unknown>;\n if (typeof question.id !== \"string\" || typeof question.prompt !== \"string\")\n return [];\n const options = Array.isArray(question.options)\n ? question.options.flatMap<ToolApprovalQuestionOption>((option) => {\n if (!option || typeof option !== \"object\" || Array.isArray(option))\n return [];\n const { id, label, description } = option as Record<string, unknown>;\n if (typeof id !== \"string\" || typeof label !== \"string\") return [];\n return [\n {\n id,\n label,\n ...(typeof description === \"string\" && { description }),\n },\n ];\n })\n : undefined;\n\n return [\n {\n id: question.id,\n prompt: question.prompt,\n ...(typeof question.header === \"string\" && {\n header: question.header,\n }),\n ...(options && { options }),\n ...(typeof question.multiple === \"boolean\" && {\n multiple: question.multiple,\n }),\n ...(typeof question.allowFreeform === \"boolean\" && {\n allowFreeform: question.allowFreeform,\n }),\n },\n ];\n });\n};\n\nconst APPROVAL_DESCRIPTOR_FIELDS = [\n \"prompt\",\n \"display\",\n \"allowFreeform\",\n \"dismissible\",\n \"options\",\n \"optionId\",\n \"text\",\n \"questions\",\n \"answers\",\n \"resolution\",\n] as const;\n\n// The AI SDK's approval object declares none of the core request and answer\n// fields and `validateUIMessages` strips unknown ones, so a host streams or\n// persists them inside the opaque `approvalDescriptor`. Only those fields are\n// read from it: a descriptor cannot approve its own request.\nconst readApprovalDescriptor = (\n descriptor: unknown,\n): Record<string, unknown> => {\n if (\n !descriptor ||\n typeof descriptor !== \"object\" ||\n Array.isArray(descriptor)\n )\n return {};\n const fields: Record<string, unknown> = {};\n for (const key of APPROVAL_DESCRIPTOR_FIELDS) {\n if (Object.hasOwn(descriptor, key))\n fields[key] = (descriptor as Record<string, unknown>)[key];\n }\n return fields;\n};\n\nfunction getToolApprovalAndInterrupt(\n part: {\n approval?: Record<string, unknown> | undefined;\n },\n toolStatus: { type: string; payload?: unknown } | undefined,\n supportsRichToolApprovalResponses: boolean,\n toolApprovalResponses:\n | ReadonlyMap<string, RespondToToolApprovalOptions>\n | undefined,\n cancelledToolApprovalIds: ReadonlySet<string> | undefined,\n): {\n approval?: NonNullable<ToolCallMessagePart[\"approval\"]>;\n interrupt?: NonNullable<ToolCallMessagePart[\"interrupt\"]>;\n} {\n if (part.approval) {\n const rawApproval = {\n ...readApprovalDescriptor(part.approval.descriptor),\n ...part.approval,\n };\n const approval =\n typeof rawApproval.id === \"string\" &&\n rawApproval.approved === undefined &&\n rawApproval.resolution === undefined &&\n cancelledToolApprovalIds?.has(rawApproval.id)\n ? { ...rawApproval, resolution: \"cancelled\" as const }\n : rawApproval;\n const response =\n typeof approval.id === \"string\" &&\n approval.approved === undefined &&\n approval.resolution !== \"cancelled\" &&\n approval.resolution !== \"expired\"\n ? toolApprovalResponses?.get(approval.id)\n : undefined;\n // The built-in AI SDK channel sends only id, approved and reason back to\n // the server, so a request shape promising any other answer would render\n // controls whose response cannot travel.\n const {\n id,\n prompt,\n approved,\n reason,\n isAutomatic,\n resolution,\n display,\n allowFreeform,\n dismissible,\n options,\n optionId,\n text,\n questions,\n answers,\n ...additionalApprovalFields\n } = response\n ? {\n ...approval,\n approved: response.approved,\n ...(response.reason != null && { reason: response.reason }),\n ...(response.optionId != null && { optionId: response.optionId }),\n ...(response.text != null && { text: response.text }),\n ...(response.answers != null && { answers: response.answers }),\n }\n : approval;\n const normalizedOptions = supportsRichToolApprovalResponses\n ? normalizeToolApprovalOptions(options)\n : undefined;\n const normalizedQuestions = supportsRichToolApprovalResponses\n ? normalizeToolApprovalQuestions(questions)\n : undefined;\n const normalizedAnswers = supportsRichToolApprovalResponses\n ? normalizeToolApprovalAnswers(answers)\n : undefined;\n const requestReason = additionalApprovalFields.requestReason;\n if (typeof id === \"string\")\n return {\n approval: {\n ...additionalApprovalFields,\n id,\n ...(typeof prompt === \"string\"\n ? { prompt }\n : typeof requestReason === \"string\"\n ? { prompt: requestReason }\n : {}),\n ...(typeof approved === \"boolean\" && { approved }),\n ...(typeof reason === \"string\" && { reason }),\n ...(isAutomatic === true && { isAutomatic: true }),\n ...(supportsRichToolApprovalResponses && {\n ...((display === \"decision\" ||\n display === \"select\" ||\n display === \"text\" ||\n display === \"questions\") && { display }),\n ...(typeof allowFreeform === \"boolean\" && { allowFreeform }),\n ...(typeof dismissible === \"boolean\" && { dismissible }),\n ...(normalizedOptions && { options: normalizedOptions }),\n ...(typeof optionId === \"string\" && { optionId }),\n ...(typeof text === \"string\" && { text }),\n ...(normalizedQuestions && { questions: normalizedQuestions }),\n ...(normalizedAnswers && { answers: normalizedAnswers }),\n }),\n ...((resolution === \"cancelled\" || resolution === \"expired\") && {\n resolution,\n }),\n } as NonNullable<ToolCallMessagePart[\"approval\"]>,\n };\n }\n\n if (toolStatus?.type === \"interrupt\") {\n return {\n interrupt: toolStatus.payload as NonNullable<\n ToolCallMessagePart[\"interrupt\"]\n >,\n };\n }\n\n return {};\n}\n\ntype MessageContent = Exclude<ThreadMessageLike[\"content\"], string>;\n\nconst uiPartStateToStatus = (\n state: \"streaming\" | \"done\" | undefined,\n): MessagePartStreamStatus | undefined => {\n if (state === \"streaming\") return { type: \"running\" };\n if (state === \"done\") return { type: \"complete\" };\n return undefined;\n};\n\nconst toSystemContent = (content: MessageContent): MessageContent => {\n const text = content.filter((part) => part.type === \"text\");\n if (text.length === 1) return text;\n const providerMetadata = text.reduce<PartProviderMetadata>(\n (merged, part) =>\n part.providerMetadata != null\n ? { ...merged, ...part.providerMetadata }\n : merged,\n {},\n );\n return [\n {\n type: \"text\",\n text: text.map((part) => part.text).join(\"\"),\n ...(Object.keys(providerMetadata).length > 0 && { providerMetadata }),\n },\n ];\n};\n\nfunction convertParts(\n message: UIMessage,\n metadata: AISDKMessageConverterMetadata,\n): MessageContent {\n if (!message.parts || message.parts.length === 0) {\n return [];\n }\n\n const converted = message.parts\n .filter(\n (p) =>\n typeof p?.type === \"string\" &&\n p.type !== \"step-start\" &&\n (message.role !== \"user\" || p.type !== \"file\"),\n )\n .map((part) => {\n if (part.type === \"text\") {\n const status = uiPartStateToStatus(part.state);\n return {\n type: \"text\",\n text: part.text ?? \"\",\n ...(status != null ? { status } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata: part.providerMetadata as PartProviderMetadata,\n }\n : undefined),\n } satisfies TextMessagePart;\n }\n\n if (part.type === \"reasoning\") {\n const status = uiPartStateToStatus(part.state);\n return {\n type: \"reasoning\",\n text: part.text,\n ...(status != null ? { status } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata: part.providerMetadata as PartProviderMetadata,\n }\n : undefined),\n } satisfies ReasoningMessagePart;\n }\n\n if (isToolUIPart(part)) {\n const toolName = getToolName(part) ?? \"\";\n const toolCallId = part.toolCallId;\n const argsKeyOrderCacheKey = `${message.id}:${toolCallId}`;\n\n // A tool call that streamed complete arguments then failed schema\n // validation keeps them in `rawInput`, not `input`; reading `input`\n // alone would convert the error snapshot to `{}` and hide the input.\n const rawInput = (part.input ??\n (\"rawInput\" in part ? part.rawInput : undefined)) as\n | ReadonlyJSONObject\n | null\n | undefined;\n let args: ReadonlyJSONObject;\n if (\n rawInput != null &&\n typeof rawInput === \"object\" &&\n !Array.isArray(rawInput)\n ) {\n args = rawInput;\n metadata.toolLastInputCache?.set(argsKeyOrderCacheKey, args);\n } else {\n args = metadata.toolLastInputCache?.get(argsKeyOrderCacheKey) ?? {};\n }\n\n let result: unknown;\n let modelContent: ToolCallMessagePart[\"modelContent\"];\n let isError = false;\n\n if (part.state === \"output-available\") {\n const unwrapped = unwrapModelContentEnvelope(part.output);\n result = unwrapped.result;\n modelContent = unwrapped.modelContent;\n } else if (part.state === \"output-error\") {\n isError = true;\n result = { error: part.errorText };\n } else if (part.state === \"output-denied\") {\n isError = true;\n result = {\n error:\n (part as { approval?: { reason?: string } }).approval?.reason ||\n \"Tool approval denied\",\n };\n }\n\n let argsText: string;\n if (part.state === \"input-streaming\") {\n argsText = stableStringifyToolArgs(\n metadata.toolArgsKeyOrderCache,\n argsKeyOrderCacheKey,\n args,\n );\n // strip closing delimiters added by the AI SDK's fix-json\n argsText = stripClosingDelimiters(argsText);\n // Re-parse so args carries the partial-JSON meta that marks which\n // field is still mid-arrival, like every argsText-based runtime.\n // The key-order cache appends new keys last, so the trailing field\n // of the stripped text is the streaming frontier.\n args = parsePartialJsonObject(argsText) ?? args;\n } else {\n // A settled part is re-converted whenever its message or the converter\n // metadata changes; the text frozen on its input object skips\n // re-serializing large args while the call keeps that input. Arrival\n // order only matters while args stream, so the key-order entry is\n // released.\n const inputArgs = args;\n const frozen =\n metadata.toolArgsTextCache?.get(inputArgs) ??\n new Map<string, { argsText: string; args: ReadonlyJSONObject }>();\n const frozenEntry = frozen.get(argsKeyOrderCacheKey);\n if (frozenEntry !== undefined) {\n argsText = frozenEntry.argsText;\n args = frozenEntry.args;\n } else {\n argsText = stableStringifyToolArgs(\n metadata.toolArgsKeyOrderCache,\n argsKeyOrderCacheKey,\n args,\n );\n // The input is final even while execution keeps the part running.\n // Other runtimes can synthesize complete JSON text from an\n // accumulating snapshot, so only this converter supplies the\n // completion signal it knows from the AI SDK part state.\n // A complete root marker settles every field without parsing the\n // serialized text again. Keep the SDK input's nested identities\n // and own fields, including prototype-named JSON keys.\n args = markPartialJsonObjectComplete(args);\n metadata.toolArgsTextCache?.set(\n inputArgs,\n frozen.set(argsKeyOrderCacheKey, { argsText, args }),\n );\n }\n metadata.toolArgsKeyOrderCache?.delete(argsKeyOrderCacheKey);\n if (\n part.state === \"output-available\" ||\n part.state === \"output-error\" ||\n part.state === \"output-denied\"\n ) {\n metadata.toolLastInputCache?.delete(argsKeyOrderCacheKey);\n }\n }\n\n const toolStatus = metadata.toolStatuses?.[toolCallId];\n const mcpApp = extractMcpAppMetadata(\n part,\n metadata.mcpAppMetadataCache,\n );\n const artifact = metadata.toolArtifacts?.get(toolCallId);\n const interactions = metadata.toolInteractions?.get(toolCallId);\n return {\n type: \"tool-call\",\n toolName,\n toolCallId,\n argsText,\n args,\n result,\n isError,\n ...(artifact !== undefined && { artifact }),\n ...(interactions !== undefined && {\n unstable_interactions: interactions,\n }),\n ...(part.state === \"output-available\" &&\n part.preliminary === true && { isPreliminary: true }),\n ...(modelContent !== undefined && { modelContent }),\n ...(mcpApp && { mcp: { app: mcpApp } }),\n ...(part.callProviderMetadata != null\n ? {\n providerMetadata:\n part.callProviderMetadata as PartProviderMetadata,\n }\n : undefined),\n ...getToolApprovalAndInterrupt(\n part,\n toolStatus,\n metadata.supportsRichToolApprovalResponses === true,\n metadata.toolApprovalResponses,\n metadata.cancelledToolApprovalIds,\n ),\n } satisfies ToolCallMessagePart;\n }\n\n if (part.type === \"source-url\") {\n return {\n type: \"source\",\n sourceType: \"url\",\n id: part.sourceId,\n url: part.url,\n ...(part.title != null ? { title: part.title } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata:\n part.providerMetadata as SourceProviderMetadata,\n }\n : undefined),\n } satisfies SourceMessagePart;\n }\n\n if (part.type === \"file\") {\n if (typeof part.url !== \"string\") return null;\n return {\n type: \"file\",\n data: part.url,\n mimeType: part.mediaType ?? \"unknown/unknown\",\n ...(part.filename != null && { filename: part.filename }),\n } satisfies FileMessagePart;\n }\n\n if (part.type === \"source-document\") {\n return {\n type: \"source\",\n sourceType: \"document\",\n id: part.sourceId,\n title: part.title,\n mediaType: part.mediaType,\n ...(part.filename != null ? { filename: part.filename } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata:\n part.providerMetadata as SourceProviderMetadata,\n }\n : undefined),\n } satisfies SourceMessagePart;\n }\n\n if (part.type.startsWith(\"data-\")) {\n return {\n type: \"data\",\n ...(\"id\" in part && typeof part.id === \"string\"\n ? { id: part.id }\n : undefined),\n name: part.type.substring(5),\n data: (part as any).data,\n } satisfies DataMessagePart;\n }\n\n if (isReasoningFileUIPart(part)) {\n if (typeof part.url !== \"string\") return null;\n return {\n type: \"file\",\n data: part.url,\n mimeType: part.mediaType ?? \"unknown/unknown\",\n } satisfies FileMessagePart;\n }\n\n if (isCustomContentUIPart(part)) {\n return {\n type: \"data\",\n name: part.kind,\n data: part.providerMetadata ?? null,\n } satisfies DataMessagePart;\n }\n\n console.warn(`Unsupported message part type: ${part.type}`);\n return null;\n })\n .filter(Boolean) as MessageContent[number][];\n\n const seenToolCallIds = new Set<string>();\n return converted.filter((part) => {\n if (part.type === \"tool-call\" && part.toolCallId != null) {\n if (seenToolCallIds.has(part.toolCallId)) return false;\n seenToolCallIds.add(part.toolCallId);\n }\n return true;\n });\n}\n\nexport const AISDKMessageConverter = unstable_createMessageConverter(\n (message: UIMessage, metadata: AISDKMessageConverterMetadata) => {\n const createdAt = new Date();\n const content = convertParts(message, metadata);\n\n switch (message.role) {\n case \"user\":\n return {\n role: \"user\",\n id: message.id,\n createdAt,\n content,\n attachments: message.parts\n ?.filter(\n (p): p is FileUIPart =>\n p?.type === \"file\" && typeof p.url === \"string\",\n )\n .map((part, idx) => {\n const mediaType = part.mediaType ?? \"unknown/unknown\";\n const isImage = mediaType.startsWith(\"image/\");\n return {\n id: idx.toString(),\n type: isImage ? \"image\" : \"file\",\n name: part.filename ?? \"file\",\n content: [\n isImage\n ? {\n type: \"image\",\n image: part.url,\n filename: part.filename!,\n }\n : {\n type: \"file\",\n filename: part.filename!,\n data: part.url,\n mimeType: mediaType,\n },\n ],\n contentType: mediaType,\n status: { type: \"complete\" as const },\n };\n }),\n metadata: toThreadMetadata(message.metadata),\n };\n\n case \"system\":\n case \"assistant\": {\n const timing = metadata.messageTiming?.[message.id];\n const isOptimistic =\n message.role === \"assistant\" &&\n message.id === metadata.optimisticMessageId;\n return {\n role: message.role,\n id: message.id,\n createdAt,\n content:\n message.role === \"system\" ? toSystemContent(content) : content,\n ...(message.role === \"assistant\" &&\n metadata.cancelledStatusMessageIds?.has(message.id)\n ? {\n status: {\n type: \"incomplete\" as const,\n reason: \"cancelled\" as const,\n },\n }\n : undefined),\n metadata: {\n ...toThreadMetadata(message.metadata),\n ...(timing && { timing }),\n ...(isOptimistic && { isOptimistic: true }),\n },\n };\n }\n\n default:\n console.warn(`Unsupported message role: ${message.role}`);\n return [];\n }\n },\n);\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type { UseChatRuntimeOptions } from "./runtime/useChatRuntime.js";
|
|
|
5
5
|
export { AssistantChatTransport } from "./transport/AssistantChatTransport.js";
|
|
6
6
|
export { RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage, } from "./transport/resumable.js";
|
|
7
7
|
export type { AssistantChatResumableOptions, ResumableClientStorage, } from "./transport/resumable.js";
|
|
8
|
-
export { frontendTools, type FrontendTools } from "
|
|
8
|
+
export { frontendTools, type FrontendTools } from "assistant-stream/ai-sdk";
|
|
9
9
|
export { injectQuoteContext } from "./model-context/injectQuoteContext.js";
|
|
10
10
|
export { unstable_injectInteractableContext } from "./model-context/injectInteractableContext.js";
|
|
11
11
|
export type { ThreadTokenUsage, TokenUsageExtractableMessage } from "./usage.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,qCAAkC;AAC5D,OAAO,EAAE,cAAc,EAAE,oCAAiC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,oCAAiC;AACtE,OAAO,EAAE,sBAAsB,EAAE,8CAA2C;AAC5E,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,GAC9B,iCAA8B;AAC/B,YAAY,EACV,6BAA6B,EAC7B,sBAAsB,GACvB,iCAA8B;AAC/B,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,qCAAkC;AAC5D,OAAO,EAAE,cAAc,EAAE,oCAAiC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,oCAAiC;AACtE,OAAO,EAAE,sBAAsB,EAAE,8CAA2C;AAC5E,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,GAC9B,iCAA8B;AAC/B,YAAY,EACV,6BAA6B,EAC7B,sBAAsB,GACvB,iCAA8B;AAC/B,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,8CAA2C;AACxE,OAAO,EAAE,kCAAkC,EAAE,qDAAkD;AAC/F,YAAY,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,mBAAgB;AAC9E,OAAO,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,mBAAgB;AAC1E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,mBAAgB;AACtD,OAAO,EACL,YAAY,EACZ,eAAe,EACf,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,GAC5B,mCAAgC;AACjC,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,+BAA4B;AACvE,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,kCAA+B"}
|
package/dist/index.js
CHANGED
|
@@ -3,11 +3,11 @@ import { useAISDKRuntime } from "./runtime/useAISDKRuntime.js";
|
|
|
3
3
|
import { RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage } from "./transport/resumable.js";
|
|
4
4
|
import { AssistantChatTransport } from "./transport/AssistantChatTransport.js";
|
|
5
5
|
import { useChatRuntime } from "./runtime/useChatRuntime.js";
|
|
6
|
-
import { frontendTools } from "./tools/frontendTools.js";
|
|
7
6
|
import { injectQuoteContext } from "./model-context/injectQuoteContext.js";
|
|
8
7
|
import { unstable_injectInteractableContext } from "./model-context/injectInteractableContext.js";
|
|
9
8
|
import { getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
10
9
|
import { AISDKChat } from "./runtime/AISDKChat.js";
|
|
11
10
|
import { AISDKToolkit, generativeTools } from "./tools/generativeTools.js";
|
|
12
11
|
import { AISDKThreads } from "./runtime/AISDKThreads.js";
|
|
12
|
+
import { frontendTools } from "assistant-stream/ai-sdk";
|
|
13
13
|
export { AISDKChat, AISDKThreads, AISDKToolkit, AssistantChatTransport, RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage, frontendTools, generativeTools, getThreadMessageTokenUsage, injectQuoteContext, unstable_injectInteractableContext, useAISDKChat, useAISDKError, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
package/dist/index.native.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type { UseChatRuntimeOptions } from "./runtime/useChatRuntime.js";
|
|
|
5
5
|
export { AssistantChatTransport } from "./transport/AssistantChatTransport.js";
|
|
6
6
|
export { RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage, } from "./transport/resumable.js";
|
|
7
7
|
export type { AssistantChatResumableOptions, ResumableClientStorage, } from "./transport/resumable.js";
|
|
8
|
-
export { frontendTools, type FrontendTools } from "
|
|
8
|
+
export { frontendTools, type FrontendTools } from "assistant-stream/ai-sdk";
|
|
9
9
|
export { injectQuoteContext } from "./model-context/injectQuoteContext.js";
|
|
10
10
|
export { unstable_injectInteractableContext } from "./model-context/injectInteractableContext.js";
|
|
11
11
|
export type { ThreadTokenUsage, TokenUsageExtractableMessage } from "./usage.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.native.d.ts","sourceRoot":"","sources":["../src/index.native.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,qCAAkC;AAC5D,OAAO,EAAE,cAAc,EAAE,oCAAiC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,oCAAiC;AACtE,OAAO,EAAE,sBAAsB,EAAE,8CAA2C;AAC5E,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,GAC9B,iCAA8B;AAC/B,YAAY,EACV,6BAA6B,EAC7B,sBAAsB,GACvB,iCAA8B;AAC/B,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"index.native.d.ts","sourceRoot":"","sources":["../src/index.native.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,qCAAkC;AAC5D,OAAO,EAAE,cAAc,EAAE,oCAAiC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,oCAAiC;AACtE,OAAO,EAAE,sBAAsB,EAAE,8CAA2C;AAC5E,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,GAC9B,iCAA8B;AAC/B,YAAY,EACV,6BAA6B,EAC7B,sBAAsB,GACvB,iCAA8B;AAC/B,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,8CAA2C;AACxE,OAAO,EAAE,kCAAkC,EAAE,qDAAkD;AAC/F,YAAY,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,mBAAgB;AAC9E,OAAO,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,mBAAgB;AAC1E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,mBAAgB;AACtD,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,+BAA4B"}
|
package/dist/index.native.js
CHANGED
|
@@ -3,9 +3,9 @@ import { useAISDKRuntime } from "./runtime/useAISDKRuntime.js";
|
|
|
3
3
|
import { RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage } from "./transport/resumable.js";
|
|
4
4
|
import { AssistantChatTransport } from "./transport/AssistantChatTransport.js";
|
|
5
5
|
import { useChatRuntime } from "./runtime/useChatRuntime.js";
|
|
6
|
-
import { frontendTools } from "./tools/frontendTools.js";
|
|
7
6
|
import { injectQuoteContext } from "./model-context/injectQuoteContext.js";
|
|
8
7
|
import { unstable_injectInteractableContext } from "./model-context/injectInteractableContext.js";
|
|
9
8
|
import { getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
10
9
|
import { AISDKChat } from "./runtime/AISDKChat.js";
|
|
10
|
+
import { frontendTools } from "assistant-stream/ai-sdk";
|
|
11
11
|
export { AISDKChat, AssistantChatTransport, RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage, frontendTools, getThreadMessageTokenUsage, injectQuoteContext, unstable_injectInteractableContext, useAISDKChat, useAISDKError, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
|
@@ -15,6 +15,8 @@ import { type Unstable_InteractableSnapshotEntry } from "@assistant-ui/core";
|
|
|
15
15
|
* `format` must also handle entries with `partial: true`, whose `state` carries
|
|
16
16
|
* only the fields that changed since the model's last known state.
|
|
17
17
|
*
|
|
18
|
+
* @deprecated Experimental since 2026-06-23. Not scheduled for removal; the API may change in any release.
|
|
19
|
+
*
|
|
18
20
|
* @example
|
|
19
21
|
* ```ts
|
|
20
22
|
* import { convertToModelMessages, streamText } from "ai";
|
|
@@ -23,6 +25,7 @@ import { type Unstable_InteractableSnapshotEntry } from "@assistant-ui/core";
|
|
|
23
25
|
* export async function POST(req: Request) {
|
|
24
26
|
* const { messages } = await req.json();
|
|
25
27
|
* const result = streamText({
|
|
28
|
+
* abortSignal: req.signal,
|
|
26
29
|
* model: myModel,
|
|
27
30
|
* messages: await convertToModelMessages(unstable_injectInteractableContext(messages)),
|
|
28
31
|
* });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injectInteractableContext.d.ts","sourceRoot":"","sources":["../../src/model-context/injectInteractableContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAGL,KAAK,kCAAkC,EACxC,MAAM,oBAAoB,CAAC;AAE5B
|
|
1
|
+
{"version":3,"file":"injectInteractableContext.d.ts","sourceRoot":"","sources":["../../src/model-context/injectInteractableContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAGL,KAAK,kCAAkC,EACxC,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,SAAS,EAAE,EACrB,MAAM,GAAE,CACN,IAAI,EAAE,kCAAkC,KACrC,MAA4C,GAChD,SAAS,EAAE,CAkBb"}
|
|
@@ -15,6 +15,8 @@ import { unstable_formatInteractableSnapshot, unstable_getInteractableSnapshots
|
|
|
15
15
|
* `format` must also handle entries with `partial: true`, whose `state` carries
|
|
16
16
|
* only the fields that changed since the model's last known state.
|
|
17
17
|
*
|
|
18
|
+
* @deprecated Experimental since 2026-06-23. Not scheduled for removal; the API may change in any release.
|
|
19
|
+
*
|
|
18
20
|
* @example
|
|
19
21
|
* ```ts
|
|
20
22
|
* import { convertToModelMessages, streamText } from "ai";
|
|
@@ -23,6 +25,7 @@ import { unstable_formatInteractableSnapshot, unstable_getInteractableSnapshots
|
|
|
23
25
|
* export async function POST(req: Request) {
|
|
24
26
|
* const { messages } = await req.json();
|
|
25
27
|
* const result = streamText({
|
|
28
|
+
* abortSignal: req.signal,
|
|
26
29
|
* model: myModel,
|
|
27
30
|
* messages: await convertToModelMessages(unstable_injectInteractableContext(messages)),
|
|
28
31
|
* });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injectInteractableContext.js","names":["UIMessage","unstable_formatInteractableSnapshot","unstable_getInteractableSnapshots","Unstable_InteractableSnapshotEntry","unstable_injectInteractableContext","messages","format","item","map","msg","role","items","length","text","join","alreadyInjected","parts","type","const"],"sources":["../../src/model-context/injectInteractableContext.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\nimport {\n unstable_formatInteractableSnapshot,\n unstable_getInteractableSnapshots,\n type Unstable_InteractableSnapshotEntry,\n} from \"@assistant-ui/core\";\n\n/**\n * Injects interactable state snapshots into messages as model-visible text.\n *\n * Mirrors {@link injectQuoteContext}: reads the frozen snapshot stamped on a user\n * message's `metadata.custom.interactables` (by the interactables scope at send\n * time) and prepends a text part. Run this in your route handler before\n * `convertToModelMessages`, which otherwise ignores `metadata.custom`.\n *\n * Wording is consumer-owned — pass `format` to control how each snapshot reads.\n * A snapshot may originate from a user edit or an agent `update_*` call, so the\n * default phrasing is neutral. Keep the instance id visible in custom wording:\n * the model needs it to address the `update_*` tool's `id` parameter. A custom\n * `format` must also handle entries with `partial: true`, whose `state` carries\n * only the fields that changed since the model's last known state.\n *\n * @example\n * ```ts\n * import { convertToModelMessages, streamText } from \"ai\";\n * import { unstable_injectInteractableContext } from \"@assistant-ui/ai-sdk\";\n *\n * export async function POST(req: Request) {\n * const { messages } = await req.json();\n * const result = streamText({\n * model: myModel,\n * messages: await convertToModelMessages(unstable_injectInteractableContext(messages)),\n * });\n * return result.toUIMessageStreamResponse();\n * }\n * ```\n */\nexport function unstable_injectInteractableContext(\n messages: UIMessage[],\n format: (\n item: Unstable_InteractableSnapshotEntry,\n ) => string = unstable_formatInteractableSnapshot,\n): UIMessage[] {\n return messages.map((msg) => {\n if (msg.role !== \"user\") return msg;\n\n const items = unstable_getInteractableSnapshots(msg);\n if (!items?.length) return msg;\n\n const text = `${items.map(format).join(\"\\n\")}\\n\\n`;\n\n const alreadyInjected =\n msg.parts?.[0]?.type === \"text\" && msg.parts[0].text === text;\n if (alreadyInjected) return msg;\n\n return {\n ...msg,\n parts: [{ type: \"text\" as const, text }, ...(msg.parts ?? [])],\n };\n });\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"injectInteractableContext.js","names":["UIMessage","unstable_formatInteractableSnapshot","unstable_getInteractableSnapshots","Unstable_InteractableSnapshotEntry","unstable_injectInteractableContext","messages","format","item","map","msg","role","items","length","text","join","alreadyInjected","parts","type","const"],"sources":["../../src/model-context/injectInteractableContext.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\nimport {\n unstable_formatInteractableSnapshot,\n unstable_getInteractableSnapshots,\n type Unstable_InteractableSnapshotEntry,\n} from \"@assistant-ui/core\";\n\n/**\n * Injects interactable state snapshots into messages as model-visible text.\n *\n * Mirrors {@link injectQuoteContext}: reads the frozen snapshot stamped on a user\n * message's `metadata.custom.interactables` (by the interactables scope at send\n * time) and prepends a text part. Run this in your route handler before\n * `convertToModelMessages`, which otherwise ignores `metadata.custom`.\n *\n * Wording is consumer-owned — pass `format` to control how each snapshot reads.\n * A snapshot may originate from a user edit or an agent `update_*` call, so the\n * default phrasing is neutral. Keep the instance id visible in custom wording:\n * the model needs it to address the `update_*` tool's `id` parameter. A custom\n * `format` must also handle entries with `partial: true`, whose `state` carries\n * only the fields that changed since the model's last known state.\n *\n * @deprecated Experimental since 2026-06-23. Not scheduled for removal; the API may change in any release.\n *\n * @example\n * ```ts\n * import { convertToModelMessages, streamText } from \"ai\";\n * import { unstable_injectInteractableContext } from \"@assistant-ui/ai-sdk\";\n *\n * export async function POST(req: Request) {\n * const { messages } = await req.json();\n * const result = streamText({\n * abortSignal: req.signal,\n * model: myModel,\n * messages: await convertToModelMessages(unstable_injectInteractableContext(messages)),\n * });\n * return result.toUIMessageStreamResponse();\n * }\n * ```\n */\nexport function unstable_injectInteractableContext(\n messages: UIMessage[],\n format: (\n item: Unstable_InteractableSnapshotEntry,\n ) => string = unstable_formatInteractableSnapshot,\n): UIMessage[] {\n return messages.map((msg) => {\n if (msg.role !== \"user\") return msg;\n\n const items = unstable_getInteractableSnapshots(msg);\n if (!items?.length) return msg;\n\n const text = `${items.map(format).join(\"\\n\")}\\n\\n`;\n\n const alreadyInjected =\n msg.parts?.[0]?.type === \"text\" && msg.parts[0].text === text;\n if (alreadyInjected) return msg;\n\n return {\n ...msg,\n parts: [{ type: \"text\" as const, text }, ...(msg.parts ?? [])],\n };\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgBI,mCACdC,UACAC,SAEcL,qCACD;CACb,OAAOI,SAASG,KAAKC,QAAQ;EAC3B,IAAIA,IAAIC,SAAS,QAAQ,OAAOD;EAEhC,MAAME,QAAQT,kCAAkCO,GAAG;EACnD,IAAI,CAACE,OAAOC,QAAQ,OAAOH;EAE3B,MAAMI,OAAO,GAAGF,MAAMH,IAAIF,MAAM,CAAC,CAACQ,KAAK,IAAI,EAAC;EAI5C,IADEL,IAAIO,QAAQ,EAAE,EAAEC,SAAS,UAAUR,IAAIO,MAAM,EAAE,CAACH,SAASA,MACtC,OAAOJ;EAE5B,OAAO;GACL,GAAGA;GACHO,OAAO,CAAC;IAAEC,MAAM;IAAiBJ;GAAK,GAAG,GAAIJ,IAAIO,SAAS,CAAA,CAAG;EAC/D;CACF,CAAC;AACH"}
|
|
@@ -13,6 +13,7 @@ import type { UIMessage } from "ai";
|
|
|
13
13
|
* export async function POST(req: Request) {
|
|
14
14
|
* const { messages } = await req.json();
|
|
15
15
|
* const result = streamText({
|
|
16
|
+
* abortSignal: req.signal,
|
|
16
17
|
* model: myModel,
|
|
17
18
|
* messages: await convertToModelMessages(injectQuoteContext(messages)),
|
|
18
19
|
* });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injectQuoteContext.d.ts","sourceRoot":"","sources":["../../src/model-context/injectQuoteContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAepC
|
|
1
|
+
{"version":3,"file":"injectQuoteContext.d.ts","sourceRoot":"","sources":["../../src/model-context/injectQuoteContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAepC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAyBrE"}
|
|
@@ -22,6 +22,7 @@ const getQuoteText = (metadata) => {
|
|
|
22
22
|
* export async function POST(req: Request) {
|
|
23
23
|
* const { messages } = await req.json();
|
|
24
24
|
* const result = streamText({
|
|
25
|
+
* abortSignal: req.signal,
|
|
25
26
|
* model: myModel,
|
|
26
27
|
* messages: await convertToModelMessages(injectQuoteContext(messages)),
|
|
27
28
|
* });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injectQuoteContext.js","names":["UIMessage","getQuoteText","metadata","undefined","custom","Record","quote","text","injectQuoteContext","messages","map","msg","role","blockquote","split","line","join","alreadyInjected","parts","type","const"],"sources":["../../src/model-context/injectQuoteContext.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\n\nconst getQuoteText = (metadata: unknown): string | undefined => {\n if (!metadata || typeof metadata !== \"object\") return undefined;\n\n const custom = (metadata as Record<string, unknown>).custom;\n if (!custom || typeof custom !== \"object\") return undefined;\n\n const quote = (custom as Record<string, unknown>).quote;\n if (!quote || typeof quote !== \"object\") return undefined;\n\n const text = (quote as Record<string, unknown>).text;\n return typeof text === \"string\" ? text : undefined;\n};\n\n/**\n * Injects quote context into messages as markdown blockquotes.\n *\n * Use this in your route handler before `convertToModelMessages` so the LLM\n * sees the quoted text that the user is referring to.\n *\n * @example\n * ```ts\n * import { convertToModelMessages, streamText } from \"ai\";\n * import { injectQuoteContext } from \"@assistant-ui/ai-sdk\";\n *\n * export async function POST(req: Request) {\n * const { messages } = await req.json();\n * const result = streamText({\n * model: myModel,\n * messages: await convertToModelMessages(injectQuoteContext(messages)),\n * });\n * return result.toUIMessageStreamResponse();\n * }\n * ```\n */\nexport function injectQuoteContext(messages: UIMessage[]): UIMessage[] {\n return messages.map((msg) => {\n if (msg.role !== \"user\") return msg;\n\n const text = getQuoteText(msg.metadata);\n if (!text) return msg;\n\n const blockquote = text\n .split(/\\r?\\n/)\n .map((line) => `> ${line}`)\n .join(\"\\n\");\n\n const alreadyInjected =\n msg.parts?.[0]?.type === \"text\" &&\n msg.parts[0].text === `${blockquote}\\n\\n`;\n if (alreadyInjected) return msg;\n\n return {\n ...msg,\n parts: [\n { type: \"text\" as const, text: `${blockquote}\\n\\n` },\n ...(msg.parts ?? []),\n ],\n };\n });\n}\n"],"mappings":";AAEA,MAAMC,gBAAgBC,aAA0C;CAC9D,IAAI,CAACA,YAAY,OAAOA,aAAa,UAAU,OAAOC,KAAAA;CAEtD,MAAMC,SAAUF,SAAqCE;CACrD,IAAI,CAACA,UAAU,OAAOA,WAAW,UAAU,OAAOD,KAAAA;CAElD,MAAMG,QAASF,OAAmCE;CAClD,IAAI,CAACA,SAAS,OAAOA,UAAU,UAAU,OAAOH,KAAAA;CAEhD,MAAMI,OAAQD,MAAkCC;CAChD,OAAO,OAAOA,SAAS,WAAWA,OAAOJ,KAAAA;AAC3C
|
|
1
|
+
{"version":3,"file":"injectQuoteContext.js","names":["UIMessage","getQuoteText","metadata","undefined","custom","Record","quote","text","injectQuoteContext","messages","map","msg","role","blockquote","split","line","join","alreadyInjected","parts","type","const"],"sources":["../../src/model-context/injectQuoteContext.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\n\nconst getQuoteText = (metadata: unknown): string | undefined => {\n if (!metadata || typeof metadata !== \"object\") return undefined;\n\n const custom = (metadata as Record<string, unknown>).custom;\n if (!custom || typeof custom !== \"object\") return undefined;\n\n const quote = (custom as Record<string, unknown>).quote;\n if (!quote || typeof quote !== \"object\") return undefined;\n\n const text = (quote as Record<string, unknown>).text;\n return typeof text === \"string\" ? text : undefined;\n};\n\n/**\n * Injects quote context into messages as markdown blockquotes.\n *\n * Use this in your route handler before `convertToModelMessages` so the LLM\n * sees the quoted text that the user is referring to.\n *\n * @example\n * ```ts\n * import { convertToModelMessages, streamText } from \"ai\";\n * import { injectQuoteContext } from \"@assistant-ui/ai-sdk\";\n *\n * export async function POST(req: Request) {\n * const { messages } = await req.json();\n * const result = streamText({\n * abortSignal: req.signal,\n * model: myModel,\n * messages: await convertToModelMessages(injectQuoteContext(messages)),\n * });\n * return result.toUIMessageStreamResponse();\n * }\n * ```\n */\nexport function injectQuoteContext(messages: UIMessage[]): UIMessage[] {\n return messages.map((msg) => {\n if (msg.role !== \"user\") return msg;\n\n const text = getQuoteText(msg.metadata);\n if (!text) return msg;\n\n const blockquote = text\n .split(/\\r?\\n/)\n .map((line) => `> ${line}`)\n .join(\"\\n\");\n\n const alreadyInjected =\n msg.parts?.[0]?.type === \"text\" &&\n msg.parts[0].text === `${blockquote}\\n\\n`;\n if (alreadyInjected) return msg;\n\n return {\n ...msg,\n parts: [\n { type: \"text\" as const, text: `${blockquote}\\n\\n` },\n ...(msg.parts ?? []),\n ],\n };\n });\n}\n"],"mappings":";AAEA,MAAMC,gBAAgBC,aAA0C;CAC9D,IAAI,CAACA,YAAY,OAAOA,aAAa,UAAU,OAAOC,KAAAA;CAEtD,MAAMC,SAAUF,SAAqCE;CACrD,IAAI,CAACA,UAAU,OAAOA,WAAW,UAAU,OAAOD,KAAAA;CAElD,MAAMG,QAASF,OAAmCE;CAClD,IAAI,CAACA,SAAS,OAAOA,UAAU,UAAU,OAAOH,KAAAA;CAEhD,MAAMI,OAAQD,MAAkCC;CAChD,OAAO,OAAOA,SAAS,WAAWA,OAAOJ,KAAAA;AAC3C;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgBK,mBAAmBC,UAAoC;CACrE,OAAOA,SAASC,KAAKC,QAAQ;EAC3B,IAAIA,IAAIC,SAAS,QAAQ,OAAOD;EAEhC,MAAMJ,OAAON,aAAaU,IAAIT,QAAQ;EACtC,IAAI,CAACK,MAAM,OAAOI;EAElB,MAAME,aAAaN,KAChBO,MAAM,OAAO,CAAC,CACdJ,KAAKK,SAAS,KAAKA,MAAM,CAAC,CAC1BC,KAAK,IAAI;EAKZ,IAFEL,IAAIO,QAAQ,EAAE,EAAEC,SAAS,UACzBR,IAAIO,MAAM,EAAE,CAACX,SAAS,GAAGM,WAAU,OAChB,OAAOF;EAE5B,OAAO;GACL,GAAGA;GACHO,OAAO,CACL;IAAEC,MAAM;IAAiBZ,MAAM,GAAGM,WAAU;GAAO,GACnD,GAAIF,IAAIO,SAAS,CAAA,CAAG;EAExB;CACF,CAAC;AACH"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useChatThread } from "./useChatThread.js";
|
|
3
3
|
import { generateId } from "ai";
|
|
4
|
-
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
5
4
|
import { useState } from "@assistant-ui/tap/react-shim";
|
|
5
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
6
6
|
import { resource, useResource } from "@assistant-ui/tap";
|
|
7
7
|
import { RuntimeAdapter, runtimeAdapterTransformScopes } from "@assistant-ui/core/store";
|
|
8
8
|
import { attachTransformScopes } from "@assistant-ui/store/client";
|
|
@@ -18,6 +18,11 @@ export type AISDKThreadsOptions<UI_MESSAGE extends UIMessage = UIMessage> = Omit
|
|
|
18
18
|
* switch and stops on delete; per-thread history loads once per thread.
|
|
19
19
|
*/
|
|
20
20
|
cloud?: AssistantCloud | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Stable identity for the account or workspace owning Cloud runtime state.
|
|
23
|
+
* Provide it from the first render and change it when that scope changes.
|
|
24
|
+
*/
|
|
25
|
+
scopeId?: string | undefined;
|
|
21
26
|
/**
|
|
22
27
|
* Controlled thread id for the cloud list. Ignored without `cloud`.
|
|
23
28
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AISDKThreads.d.ts","sourceRoot":"","sources":["../../src/runtime/AISDKThreads.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAQ,SAAS,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAetD,OAAO,EAIL,KAAK,iBAAiB,EACvB,2BAAwB;AAKzB,MAAM,MAAM,mBAAmB,CAAC,UAAU,SAAS,SAAS,GAAG,SAAS,IACtE,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,UAAU,CAAC,GAAG;IACrE;;;;;;OAMG;IACH,SAAS,CAAC,EACN,aAAa,CAAC,UAAU,CAAC,GACzB,CAAC,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC,GACjC,SAAS,CAAC;IACd;;;;;OAKG;IACH,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACzE,CAAC;
|
|
1
|
+
{"version":3,"file":"AISDKThreads.d.ts","sourceRoot":"","sources":["../../src/runtime/AISDKThreads.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAQ,SAAS,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAetD,OAAO,EAIL,KAAK,iBAAiB,EACvB,2BAAwB;AAKzB,MAAM,MAAM,mBAAmB,CAAC,UAAU,SAAS,SAAS,GAAG,SAAS,IACtE,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,UAAU,CAAC,GAAG;IACrE;;;;;;OAMG;IACH,SAAS,CAAC,EACN,aAAa,CAAC,UAAU,CAAC,GACzB,CAAC,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC,GACjC,SAAS,CAAC;IACd;;;;;OAKG;IACH,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACzE,CAAC;AAoMJ;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,GAvFA,UAAU,SAAS,SAAS,mOAuFA,CAAC"}
|