@mastra/core
Version:
Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.
1,327 lines (1,317 loc) • 219 kB
JavaScript
'use strict';
var chunkLKGJVPW6_cjs = require('./chunk-LKGJVPW6.cjs');
var chunkVPZGHUNF_cjs = require('./chunk-VPZGHUNF.cjs');
var chunkXDKZ76SF_cjs = require('./chunk-XDKZ76SF.cjs');
var chunkY3T2Q2HR_cjs = require('./chunk-Y3T2Q2HR.cjs');
var chunkPAMAGEYY_cjs = require('./chunk-PAMAGEYY.cjs');
var chunk4U7ZLI36_cjs = require('./chunk-4U7ZLI36.cjs');
var uuid = require('@lukeed/uuid');
var providerUtilsV5 = require('@ai-sdk/provider-utils-v5');
function convertDataContentToBase64String(content) {
if (typeof content === "string") {
return content;
}
if (content instanceof ArrayBuffer) {
return providerUtilsV5.convertUint8ArrayToBase64(new Uint8Array(content));
}
return providerUtilsV5.convertUint8ArrayToBase64(content);
}
// src/agent/signals.ts
function isMastraSignalMessage(message) {
return message.role === "signal";
}
function normalizeSignal(signal) {
return {
...signal,
id: signal.id ?? crypto.randomUUID(),
createdAt: signal.createdAt instanceof Date ? signal.createdAt : signal.createdAt ? new Date(signal.createdAt) : /* @__PURE__ */ new Date(),
acceptedAt: signal.acceptedAt instanceof Date ? signal.acceptedAt : signal.acceptedAt ? new Date(signal.acceptedAt) : void 0
};
}
function escapeXml(value) {
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
}
function escapeXmlAttribute(value) {
return escapeXml(value).replaceAll('"', """);
}
var XML_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_.-]*$/;
function assertXmlName(name, label) {
if (!XML_NAME_PATTERN.test(name)) {
throw new Error(`Invalid signal XML ${label}: ${name}`);
}
}
function signalAttributesToXml(attributes) {
if (!attributes) {
return "";
}
const serialized = Object.entries(attributes).filter((entry) => entry[1] !== null && entry[1] !== void 0).map(([key, value]) => {
assertXmlName(key, "attribute name");
return `${key}="${escapeXmlAttribute(String(value))}"`;
}).join(" ");
return serialized ? ` ${serialized}` : "";
}
function signalToXmlMarkup(signal) {
assertXmlName(signal.type, "tag name");
const attributesXml = signalAttributesToXml(signal.attributes);
if (!signal.contents) return `<${signal.type}${attributesXml} />`;
return `<${signal.type}${attributesXml}>${escapeXml(signal.contents)}</${signal.type}>`;
}
function legacyContentsToSignalContents(value) {
if (typeof value === "string") return value;
if (Array.isArray(value)) {
const parts = [];
for (const entry of value) {
if (typeof entry === "string") {
parts.push({ type: "text", text: entry });
continue;
}
const decoded2 = legacyEntryToParts(entry);
if (!decoded2) return void 0;
parts.push(...decoded2);
}
return collapseLegacyParts(parts);
}
const decoded = legacyEntryToParts(value);
return decoded ? collapseLegacyParts(decoded) : void 0;
}
function legacyEntryToParts(entry) {
if (!entry || typeof entry !== "object") return void 0;
const record = entry;
if (record.role === "user" && "content" in record) {
const content = record.content;
if (typeof content === "string") return [{ type: "text", text: content }];
if (Array.isArray(content)) {
const inner = [];
for (const part2 of content) {
const decoded = legacyPartToSignalPart(part2);
if (!decoded) return void 0;
inner.push(decoded);
}
return inner;
}
return void 0;
}
const part = legacyPartToSignalPart(record);
return part ? [part] : void 0;
}
function legacyPartToSignalPart(part) {
if (!part || typeof part !== "object") return void 0;
const record = part;
const providerOptions = record.providerOptions && typeof record.providerOptions === "object" && !Array.isArray(record.providerOptions) ? record.providerOptions : void 0;
if (record.type === "text" && typeof record.text === "string") {
return { type: "text", text: record.text, ...providerOptions ? { providerOptions } : {} };
}
if (record.type === "file" || record.type === "image") {
const data = record.type === "image" ? record.image ?? record.data : record.data;
if (typeof data !== "string") return void 0;
const mediaType = typeof record.mediaType === "string" ? record.mediaType : typeof record.mimeType === "string" ? record.mimeType : record.type === "image" ? "image/png" : "";
if (!mediaType) return void 0;
return {
type: "file",
data,
mediaType,
...typeof record.filename === "string" ? { filename: record.filename } : {},
...providerOptions ? { providerOptions } : {}
};
}
return void 0;
}
function collapseLegacyParts(parts) {
if (parts.length === 0) return void 0;
const first = parts[0];
if (parts.length === 1 && first?.type === "text") return first.text;
return parts;
}
function contentsToSignalParts(contents) {
if (typeof contents === "string") return [{ type: "text", text: contents }];
return contents.map((part) => {
if (part.type === "file") {
const data = part.data instanceof URL ? part.data.toString() : convertDataContentToBase64String(part.data);
return {
type: "file",
data,
mediaType: part.mediaType,
...part.filename ? { filename: part.filename } : {},
...part.providerOptions ? { providerOptions: part.providerOptions } : {}
};
}
return {
type: "text",
text: part.text,
...part.providerOptions ? { providerOptions: part.providerOptions } : {}
};
});
}
function storagePartsToSignalParts(parts) {
const out = [];
for (const part of parts) {
const providerOptions = part.providerMetadata;
if (part.type === "text") {
out.push({
type: "text",
text: part.text,
...providerOptions ? { providerOptions } : {}
});
} else if (part.type === "file" && typeof part.data === "string") {
const file = part;
out.push({
type: "file",
data: file.data,
mediaType: typeof file.mimeType === "string" ? file.mimeType : "",
...typeof file.filename === "string" ? { filename: file.filename } : {},
...providerOptions ? { providerOptions } : {}
});
}
}
return out;
}
function partsToSignalContents(parts) {
if (parts.length === 1 && parts[0]?.type === "text" && !parts[0].providerOptions) return parts[0].text;
return parts.map(
(part) => part.type === "file" ? {
type: "file",
data: part.data,
mediaType: part.mediaType,
...part.filename ? { filename: part.filename } : {},
...part.providerOptions ? { providerOptions: part.providerOptions } : {}
} : {
type: "text",
text: part.text,
...part.providerOptions ? { providerOptions: part.providerOptions } : {}
}
);
}
function hasMeaningfulAttributes(attributes) {
if (!attributes) return false;
return Object.keys(attributes).some((key) => {
const value = attributes[key];
return value !== null && value !== void 0;
});
}
function injectMarkerInline(signal, parts) {
let wrapped = false;
const out = [];
for (const part of parts) {
if (!wrapped && part.type === "text") {
wrapped = true;
out.push({ ...part, text: signalToXmlMarkup({ ...signal, contents: part.text }) });
} else {
out.push(part);
}
}
if (!wrapped) {
const markerText = signalToXmlMarkup({ type: signal.type, attributes: signal.attributes });
out.unshift({ type: "text", text: markerText });
}
return out;
}
function signalToLLMMessage(signal, parts) {
const isUserMessage = signal.type === "user-message";
const hasAttrs = hasMeaningfulAttributes(signal.attributes);
const anyPartProviderOptions = parts.some((part) => part.providerOptions);
let content;
if (isUserMessage && !hasAttrs) {
content = parts.length === 1 && parts[0]?.type === "text" && !parts[0].providerOptions ? parts[0].text : parts;
} else if (parts.every((part) => part.type === "text") && !anyPartProviderOptions) {
content = signalToXmlMarkup({ ...signal, contents: parts.map((part) => part.text).join("\n") });
} else {
content = injectMarkerInline(signal, parts);
}
return {
role: "user",
content,
...signal.providerOptions ? { providerOptions: signal.providerOptions } : {}
};
}
function signalToDataPart(signal, parts) {
return {
type: `data-${signal.type}`,
data: {
id: signal.id,
type: signal.type,
contents: partsToSignalContents(parts),
createdAt: signal.createdAt.toISOString(),
...signal.acceptedAt ? { acceptedAt: signal.acceptedAt.toISOString() } : {},
...signal.attributes ? { attributes: signal.attributes } : {},
...signal.metadata ? { metadata: signal.metadata } : {}
}
};
}
function signalToDBMessage(signal, parts, options) {
const storageParts = parts.length > 0 ? parts.map(
(part) => part.type === "file" ? {
type: "file",
data: part.data,
mimeType: part.mediaType,
...part.filename ? { filename: part.filename } : {},
...part.providerOptions ? { providerMetadata: part.providerOptions } : {}
} : {
type: "text",
text: part.text,
...part.providerOptions ? { providerMetadata: part.providerOptions } : {}
}
) : [{ type: "text", text: "" }];
return {
id: signal.id,
role: "signal",
createdAt: signal.createdAt,
threadId: options?.threadId,
resourceId: options?.resourceId,
type: signal.type,
content: {
format: 2,
parts: storageParts,
...signal.providerOptions ? { providerMetadata: signal.providerOptions } : {},
metadata: {
signal: {
id: signal.id,
type: signal.type,
createdAt: signal.createdAt.toISOString(),
...signal.acceptedAt ? { acceptedAt: signal.acceptedAt.toISOString() } : {},
...signal.attributes ? { attributes: signal.attributes } : {},
...signal.metadata ? { metadata: signal.metadata } : {}
}
}
}
};
}
function isCreatedAgentSignal(input) {
if (!input || typeof input !== "object" || Array.isArray(input)) return false;
const candidate = input;
return candidate.__isCreatedSignal === true;
}
function createSignal(input) {
const signal = normalizeSignal(input);
const parts = contentsToSignalParts(signal.contents);
return {
...signal,
__isCreatedSignal: true,
toDBMessage: (options) => signalToDBMessage(signal, parts, options),
toLLMMessage: () => signalToLLMMessage(signal, parts),
toDataPart: () => signalToDataPart(signal, parts)
};
}
function signalToMessage(signal) {
return createSignal(signal).toLLMMessage();
}
function signalToMastraDBMessage(signal, options) {
return createSignal(signal).toDBMessage(options);
}
function signalToDataPartFormat(signal) {
return createSignal(signal).toDataPart();
}
function mastraDBMessageToSignal(message) {
const metadataSignal = message.content.metadata?.signal;
const signalMetadata = metadataSignal && typeof metadataSignal === "object" && !Array.isArray(metadataSignal) ? metadataSignal : void 0;
const type = typeof signalMetadata?.type === "string" ? signalMetadata.type : message.type ?? "user-message";
const rawLegacyContents = signalMetadata && "contents" in signalMetadata ? signalMetadata.contents : void 0;
const legacyContents = legacyContentsToSignalContents(rawLegacyContents);
const partsContents = partsToSignalContents(storagePartsToSignalParts(message.content.parts));
const contents = legacyContents ?? partsContents;
const providerMetadata = message.content.providerMetadata;
const base = {
id: typeof signalMetadata?.id === "string" ? signalMetadata.id : message.id,
createdAt: typeof signalMetadata?.createdAt === "string" ? signalMetadata.createdAt : message.createdAt,
acceptedAt: typeof signalMetadata?.acceptedAt === "string" ? signalMetadata.acceptedAt : void 0,
attributes: signalMetadata?.attributes && typeof signalMetadata.attributes === "object" && !Array.isArray(signalMetadata.attributes) ? signalMetadata.attributes : void 0,
metadata: signalMetadata?.metadata && typeof signalMetadata.metadata === "object" && !Array.isArray(signalMetadata.metadata) ? signalMetadata.metadata : void 0,
providerOptions: providerMetadata && typeof providerMetadata === "object" && !Array.isArray(providerMetadata) ? providerMetadata : void 0
};
return createSignal({ ...base, type, contents });
}
function dataPartToSignal(part) {
return createSignal(part.data);
}
// src/agent/message-list/detection/TypeDetector.ts
var TypeDetector = class _TypeDetector {
/**
* Check if a message is a MastraDBMessage (format 2)
*/
static isMastraDBMessage(msg) {
return Boolean(
"content" in msg && msg.content && !Array.isArray(msg.content) && typeof msg.content !== "string" && "format" in msg.content && msg.content.format === 2
);
}
/**
* Check if a message is a MastraMessageV1 (legacy format)
*/
static isMastraMessageV1(msg) {
return !_TypeDetector.isMastraDBMessage(msg) && ("threadId" in msg || "resourceId" in msg);
}
/**
* Check if a message is either Mastra format (V1 or V2/DB)
*/
static isMastraMessage(msg) {
return _TypeDetector.isMastraDBMessage(msg) || _TypeDetector.isMastraMessageV1(msg);
}
/**
* Check if a message is an AIV4 UIMessage
*/
static isAIV4UIMessage(msg) {
return !_TypeDetector.isMastraMessage(msg) && !_TypeDetector.isAIV4CoreMessage(msg) && "parts" in msg && !_TypeDetector.hasAIV5UIMessageCharacteristics(msg);
}
/**
* Check if a message is an AIV6 UIMessage.
*
* At runtime, the v5 and v6 UI shapes overlap heavily. We only treat a
* message as distinctly v6 if it uses v6-only parts or tool states.
*/
static isAIV6UIMessage(msg) {
return !_TypeDetector.isMastraMessage(msg) && !_TypeDetector.isAIV4CoreMessage(msg) && "parts" in msg && _TypeDetector.hasAIV6UIMessageCharacteristics(
msg
);
}
/**
* Check if a message is an AIV5 UIMessage
*/
static isAIV5UIMessage(msg) {
return !_TypeDetector.isMastraMessage(msg) && !_TypeDetector.isAIV6UIMessage(msg) && !_TypeDetector.isAIV5CoreMessage(msg) && "parts" in msg && _TypeDetector.hasAIV5UIMessageCharacteristics(msg);
}
/**
* Check if a message is an AIV4 CoreMessage
*/
static isAIV4CoreMessage(msg) {
return !_TypeDetector.isMastraMessage(msg) && !("parts" in msg) && "content" in msg && !_TypeDetector.hasAIV5CoreMessageCharacteristics(msg);
}
/**
* Check if a message is an AIV6 ModelMessage (CoreMessage equivalent).
*/
static isAIV6CoreMessage(msg) {
return !_TypeDetector.isMastraMessage(msg) && !("parts" in msg) && "content" in msg && _TypeDetector.hasAIV6CoreMessageCharacteristics(
msg
);
}
/**
* Check if a message is an AIV5 ModelMessage (CoreMessage equivalent)
*/
static isAIV5CoreMessage(msg) {
return !_TypeDetector.isMastraMessage(msg) && !_TypeDetector.isAIV6CoreMessage(msg) && !("parts" in msg) && "content" in msg && _TypeDetector.hasAIV5CoreMessageCharacteristics(msg);
}
/**
* Check if a message has AIV6-only UI characteristics.
*/
static hasAIV6UIMessageCharacteristics(msg) {
if (!("parts" in msg) || !msg.parts) return false;
for (const part of msg.parts) {
if (part.type === "source-document") return true;
if (part.type === "dynamic-tool") return true;
if ("toolCallId" in part && "state" in part && (part.state === "approval-requested" || part.state === "approval-responded" || part.state === "output-denied")) {
return true;
}
}
return false;
}
/**
* Check if a message has AIV5 UIMessage characteristics
*
* V5 UIMessages have specific part types and field names that differ from V4.
*/
static hasAIV5UIMessageCharacteristics(msg) {
if ("toolInvocations" in msg || "reasoning" in msg || "experimental_attachments" in msg || "data" in msg || "annotations" in msg)
return false;
if (!msg.parts) return false;
for (const part of msg.parts) {
if ("metadata" in part) return true;
if ("toolInvocation" in part) return false;
if ("toolCallId" in part) return true;
if (part.type === "source") return false;
if (part.type === "source-url") return true;
if (part.type === "reasoning") {
if ("state" in part || "text" in part) return true;
if ("reasoning" in part || "details" in part) return false;
}
if (part.type === "file" && "mediaType" in part) return true;
}
return false;
}
/**
* Check if a message has AIV6-only core characteristics.
*/
static hasAIV6CoreMessageCharacteristics(msg) {
if ("parts" in msg || typeof msg.content === "string") return false;
return msg.content.some((part) => part.type === "tool-approval-request" || part.type === "tool-approval-response");
}
/**
* Check if a message has AIV5 CoreMessage characteristics
*
* V5 ModelMessages use different field names from v4
* (for example `output` vs `result`, `input` vs `args`,
* `mediaType` vs `mimeType`).
*/
static hasAIV5CoreMessageCharacteristics(msg) {
if ("experimental_providerMetadata" in msg) return false;
if (typeof msg.content === "string") return true;
for (const part of msg.content) {
if (part.type === "tool-result" && "output" in part) return true;
if (part.type === "tool-call" && "input" in part) return true;
if (part.type === "tool-result" && "result" in part) return false;
if (part.type === "tool-call" && "args" in part) return false;
if ("mediaType" in part) return true;
if ("mimeType" in part) return false;
if ("experimental_providerMetadata" in part) return false;
if (part.type === "reasoning" && "signature" in part) return false;
if (part.type === "redacted-reasoning") return false;
}
return true;
}
/**
* Get the normalized role for a message
* Maps `tool` to `assistant` because tool messages are displayed as part of
* the assistant conversation.
*/
static getRole(message) {
if (message.role === "assistant" || message.role === "tool") return "assistant";
if (message.role === "user") return "user";
if (message.role === "system") return "system";
throw new Error(
`BUG: add handling for message role ${message.role} in message ${JSON.stringify(message, null, 2)}`
);
}
};
// src/agent/message-list/prompt/image-utils.ts
function parseDataUri(dataUri) {
if (!dataUri.startsWith("data:")) {
return {
isDataUri: false,
base64Content: dataUri
};
}
const base64Index = dataUri.indexOf(",");
if (base64Index === -1) {
return {
isDataUri: true,
base64Content: dataUri
};
}
const header = dataUri.substring(5, base64Index);
const base64Content = dataUri.substring(base64Index + 1);
const semicolonIndex = header.indexOf(";");
const mimeType = semicolonIndex !== -1 ? header.substring(0, semicolonIndex) : header;
return {
isDataUri: true,
mimeType: mimeType || void 0,
base64Content
};
}
function createDataUri(base64Content, mimeType = "application/octet-stream") {
if (base64Content.startsWith("data:")) {
return base64Content;
}
return `data:${mimeType};base64,${base64Content}`;
}
function imageContentToString(image, fallbackMimeType) {
if (typeof image === "string") {
return image;
}
if (image instanceof URL) {
return image.toString();
}
if (image instanceof Uint8Array || image instanceof ArrayBuffer || globalThis.Buffer && Buffer.isBuffer(image)) {
const base64 = convertDataContentToBase64String(image);
return base64;
}
return String(image);
}
function getImageCacheKey(image) {
if (image instanceof URL) {
return image.toString();
}
if (typeof image === "string") {
return image.length;
}
if (image instanceof Uint8Array) {
return image.byteLength;
}
if (image instanceof ArrayBuffer) {
return image.byteLength;
}
return image;
}
function isValidUrl(str) {
try {
new URL(str);
return true;
} catch {
if (str.startsWith("//")) {
try {
new URL(`https:${str}`);
return true;
} catch {
return false;
}
}
return false;
}
}
function categorizeFileData(data, fallbackMimeType) {
const parsed = parseDataUri(data);
const mimeType = parsed.isDataUri && parsed.mimeType ? parsed.mimeType : fallbackMimeType;
if (parsed.isDataUri) {
return {
type: "dataUri",
mimeType,
data
};
}
if (isValidUrl(data)) {
return {
type: "url",
mimeType,
data
};
}
return {
type: "raw",
mimeType,
data
};
}
// src/agent/message-list/utils/response-item-metadata.ts
var RESPONSE_ITEM_ID_PROVIDERS = ["openai", "azure"];
function formatResponseProviderItemKey(provider, itemId) {
return `${provider}:${itemId}`;
}
function getResponseProviderItemId(providerMetadata) {
return getResponseProviderItemIds(providerMetadata)[0];
}
function getResponseProviderItemKey(providerMetadata) {
const item = getResponseProviderItemId(providerMetadata);
return item ? formatResponseProviderItemKey(item.provider, item.itemId) : void 0;
}
function getResponseProviderItemIds(providerMetadata) {
if (!providerMetadata) return [];
const azureMetadata = providerMetadata.azure;
const azureItemId = azureMetadata?.itemId;
const openaiMetadata = providerMetadata.openai;
const openaiItemId = openaiMetadata?.itemId;
if (typeof azureItemId === "string" && azureItemId === openaiItemId) {
return [{ provider: "azure", itemId: azureItemId }];
}
return RESPONSE_ITEM_ID_PROVIDERS.flatMap((provider) => {
const metadata = providerMetadata[provider];
const itemId = metadata?.itemId;
return typeof itemId === "string" ? [{ provider, itemId }] : [];
});
}
function getResponseProviderItemKeys(providerMetadata) {
return getResponseProviderItemIds(providerMetadata).map(
({ provider, itemId }) => formatResponseProviderItemKey(provider, itemId)
);
}
// src/agent/message-list/utils/provider-compat.ts
function ensureGeminiCompatibleMessages(messages, logger) {
const result = [...messages];
const firstNonSystemIndex = result.findIndex((m) => m.role !== "system");
if (firstNonSystemIndex === -1) {
if (result.length > 0) {
logger?.warn(
"No user or assistant messages in the request. Some providers (e.g. Gemini) require at least one user message to generate a response."
);
}
} else if (result[firstNonSystemIndex]?.role === "assistant") {
result.splice(firstNonSystemIndex, 0, {
role: "user",
content: "."
});
}
return result;
}
function ensureAnthropicCompatibleMessages(messages, dbMessages) {
return messages.map((msg) => enrichToolResultsWithInput(msg, dbMessages));
}
function sanitizeOrphanedToolPairs(messages) {
const filteredContents = messages.map((m) => Array.isArray(m.content) ? [...m.content] : null);
for (let i = 0; i < messages.length; i++) {
const current = messages[i];
if (current.role === "assistant" && Array.isArray(current.content)) {
const useIds = /* @__PURE__ */ new Set();
const inlineResultIds = /* @__PURE__ */ new Set();
for (const part of current.content) {
if (part.type === "tool-call") useIds.add(part.toolCallId);
else if (part.type === "tool-result") inlineResultIds.add(part.toolCallId);
}
const next = messages[i + 1];
const nextResultIds = /* @__PURE__ */ new Set();
if (next && next.role === "tool" && Array.isArray(next.content)) {
for (const part of next.content) {
if (part.type === "tool-result") nextResultIds.add(part.toolCallId);
}
}
const validPairs = new Set([...useIds].filter((id) => inlineResultIds.has(id) || nextResultIds.has(id)));
filteredContents[i] = filteredContents[i].filter((p) => {
if (p.type !== "tool-call") return true;
const tc = p;
return tc.providerExecuted === true || validPairs.has(tc.toolCallId);
});
if (next && next.role === "tool" && Array.isArray(next.content)) {
filteredContents[i + 1] = filteredContents[i + 1].filter(
(p) => p.type !== "tool-result" || validPairs.has(p.toolCallId)
);
}
} else if (current.role === "tool" && Array.isArray(current.content)) {
const prev = messages[i - 1];
if (!prev || prev.role !== "assistant" || !Array.isArray(prev.content)) {
filteredContents[i] = filteredContents[i].filter((p) => p.type !== "tool-result");
}
}
}
const result = [];
for (let i = 0; i < messages.length; i++) {
const original = messages[i];
const filtered = filteredContents[i];
if (filtered == null) {
result.push(original);
continue;
}
if (filtered.length === 0) continue;
if (Array.isArray(original.content) && filtered.length === original.content.length) {
result.push(original);
continue;
}
result.push({ ...original, content: filtered });
}
return result;
}
function enrichToolResultsWithInput(message, dbMessages) {
if (message.role !== "tool" || !Array.isArray(message.content)) {
return message;
}
return {
...message,
content: message.content.map((part) => {
if (part.type === "tool-result") {
return {
...part,
input: findToolCallArgs(dbMessages, part.toolCallId)
};
}
return part;
})
};
}
function hasOpenAIReasoningItemId(part) {
return Boolean(getOpenAIReasoningItemId(part));
}
function hasResponseProviderItemId(part) {
return Boolean(getResponseProviderItemIdFromPart(part));
}
function getOpenAIReasoningItemId(part) {
if (!part || typeof part !== "object") return void 0;
const partAny = part;
const providerMetadata = partAny.providerMetadata;
const openaiMetadata = providerMetadata?.openai;
return typeof openaiMetadata?.itemId === "string" ? openaiMetadata.itemId : void 0;
}
function getResponseProviderItemIdFromPart(part) {
if (!part || typeof part !== "object") return void 0;
const partAny = part;
return getResponseProviderItemId(partAny.providerMetadata) || getResponseProviderItemId(partAny.providerOptions);
}
function findToolCallArgs(messages, toolCallId) {
for (let i = messages.length - 1; i >= 0; i--) {
const msg = messages[i];
if (!msg || msg.role !== "assistant") {
continue;
}
if (msg.content.parts) {
const toolCallPart = msg.content.parts.find(
(p) => p.type === "tool-invocation" && p.toolInvocation.toolCallId === toolCallId
);
if (toolCallPart && toolCallPart.type === "tool-invocation") {
const args = toolCallPart.toolInvocation.args || {};
if (typeof args === "object" && Object.keys(args).length > 0) {
return args;
}
}
}
if (msg.content.toolInvocations) {
const toolInvocation = msg.content.toolInvocations.find((inv) => inv.toolCallId === toolCallId);
if (toolInvocation) {
const args = toolInvocation.args || {};
if (typeof args === "object" && Object.keys(args).length > 0) {
return args;
}
}
}
}
return {};
}
// src/agent/message-list/adapters/AIV4Adapter.ts
function getDisplayTransform(providerMetadata, phase, fallback, enabled = true) {
if (!enabled) {
return fallback;
}
const transform = chunkVPZGHUNF_cjs.getTransformedToolPayload(providerMetadata, "display", phase);
return chunkVPZGHUNF_cjs.hasTransformedToolPayload(transform) ? transform.transformed : fallback;
}
function transformV4ToolInvocationForDisplay(invocation, providerMetadata, enabled) {
return {
...invocation,
args: getDisplayTransform(providerMetadata, "input-available", invocation.args, enabled),
...invocation.state === "result" ? {
result: getDisplayTransform(
providerMetadata,
"output-available",
getDisplayTransform(providerMetadata, "error", invocation.result, enabled),
enabled
)
} : {}
};
}
function preserveExtendedParts(parts) {
return parts;
}
function filterEmptyTextParts(parts) {
const hasNonEmptyParts = parts.some((part) => !(part.type === "text" && part.text === ""));
if (!hasNonEmptyParts) return parts;
return parts.filter((part) => {
if (part.type === "text") {
return part.text !== "";
}
return true;
});
}
function getSignalType(message) {
const signal = message.content.metadata?.signal;
if (signal && typeof signal === "object" && !Array.isArray(signal)) {
const type = signal.type;
return typeof type === "string" ? type : message.type;
}
return message.type;
}
function toSignalDataPart(message, contents) {
const signal = message.content.metadata?.signal && typeof message.content.metadata.signal === "object" ? message.content.metadata.signal : {};
const metadata = signal.metadata && typeof signal.metadata === "object" && !Array.isArray(signal.metadata) ? signal.metadata : {};
return {
type: `data-${getSignalType(message) ?? "signal"}`,
data: {
id: typeof signal.id === "string" ? signal.id : message.id,
type: getSignalType(message) ?? "signal",
contents: "contents" in signal ? signal.contents : contents,
createdAt: typeof signal.createdAt === "string" ? signal.createdAt : message.createdAt.toISOString(),
...Object.keys(metadata).length ? { metadata } : {}
}
};
}
var AIV4Adapter = class {
/**
* Convert MastraDBMessage to AI SDK V4 UIMessage
*/
static toUIMessage(m, options) {
const transformToolPayloads = options?.transformToolPayloads ?? true;
const experimentalAttachments = m.content.experimental_attachments ? [...m.content.experimental_attachments] : [];
const contentString = typeof m.content.content === `string` && m.content.content !== "" ? m.content.content : (m.content.parts ?? []).reduce((prev, part) => {
if (part.type === `text`) {
return part.text;
}
return prev;
}, "");
const parts = [];
const sourceParts = m.content.parts ?? [];
if (sourceParts.length) {
for (const part of sourceParts) {
if (part.type === `file`) {
let normalizedUrl;
if (typeof part.data === "string") {
const categorized = categorizeFileData(part.data, part.mimeType);
if (categorized.type === "raw") {
normalizedUrl = createDataUri(part.data, part.mimeType || "application/octet-stream");
} else {
normalizedUrl = part.data;
}
} else {
normalizedUrl = part.data;
}
experimentalAttachments.push({
contentType: part.mimeType,
url: normalizedUrl
});
} else if (part.type === "tool-invocation" && (part.toolInvocation.state === "call" || part.toolInvocation.state === "partial-call")) {
continue;
} else if (part.type === "tool-invocation") {
const toolInvocation = {
...part.toolInvocation,
args: getDisplayTransform(
part.providerMetadata,
"input-available",
part.toolInvocation.args,
transformToolPayloads
),
...part.toolInvocation.state === "result" ? {
result: getDisplayTransform(
part.providerMetadata,
"output-available",
getDisplayTransform(
part.providerMetadata,
"error",
part.toolInvocation.result,
transformToolPayloads
),
transformToolPayloads
)
} : {}
};
let currentStep = -1;
let toolStep = -1;
for (const innerPart of sourceParts) {
if (innerPart.type === `step-start`) currentStep++;
if (innerPart.type === `tool-invocation` && innerPart.toolInvocation.toolCallId === part.toolInvocation.toolCallId) {
toolStep = currentStep;
break;
}
}
if (toolStep >= 0) {
const preparedInvocation = {
step: toolStep,
...toolInvocation
};
parts.push({
type: "tool-invocation",
toolInvocation: preparedInvocation
});
} else {
parts.push({
type: "tool-invocation",
toolInvocation
});
}
} else {
parts.push(part);
}
}
}
if (parts.length === 0 && experimentalAttachments.length > 0) {
parts.push({ type: "text", text: "" });
}
const signalType = m.role === "signal" ? getSignalType(m) : void 0;
const isUserMessageSignal = signalType === "user-message";
const v4Parts = preserveExtendedParts(
m.role === "signal" && !isUserMessageSignal ? [toSignalDataPart(m, m.content.content || contentString)] : parts
);
if (m.role === `user`) {
const uiMessage2 = {
id: m.id,
role: m.role,
content: m.content.content || contentString,
createdAt: m.createdAt,
parts: v4Parts,
experimental_attachments: experimentalAttachments
};
if (m.content.metadata) {
uiMessage2.metadata = m.content.metadata;
}
return uiMessage2;
} else if (m.role === `assistant`) {
const isSingleTextContentArray = Array.isArray(m.content.content) && m.content.content.length === 1 && m.content.content[0].type === `text`;
const uiMessage2 = {
id: m.id,
role: m.role,
content: isSingleTextContentArray ? contentString : m.content.content || contentString,
createdAt: m.createdAt,
parts: v4Parts,
reasoning: void 0,
toolInvocations: `toolInvocations` in m.content ? m.content.toolInvocations?.filter((t) => t.state === "result").map((toolInvocation) => {
const partProviderMetadata = m.content.parts?.find(
(part) => part.type === "tool-invocation" && part.toolInvocation.toolCallId === toolInvocation.toolCallId
)?.providerMetadata;
return transformV4ToolInvocationForDisplay(
toolInvocation,
partProviderMetadata,
transformToolPayloads
);
}) : void 0
};
if (m.content.metadata) {
uiMessage2.metadata = m.content.metadata;
}
return uiMessage2;
}
const uiMessage = {
id: m.id,
role: m.role === "signal" ? isUserMessageSignal ? "user" : "system" : m.role,
content: m.role === "signal" && !isUserMessageSignal ? "" : m.content.content || contentString,
createdAt: m.createdAt,
parts: v4Parts,
experimental_attachments: experimentalAttachments
};
if (m.content.metadata) {
uiMessage.metadata = m.content.metadata;
}
return uiMessage;
}
/**
* Converts a MastraDBMessage system message directly to AIV4 CoreMessage format
*/
static systemToV4Core(message) {
if (message.role !== `system` || !message.content.content)
throw new chunk4U7ZLI36_cjs.MastraError({
id: "INVALID_SYSTEM_MESSAGE_FORMAT",
domain: "AGENT" /* AGENT */,
category: "USER" /* USER */,
text: `Invalid system message format. System messages must include 'role' and 'content' properties. The content should be a string.`,
details: {
receivedMessage: JSON.stringify(message, null, 2)
}
});
const coreMessage = { role: "system", content: message.content.content };
if (message.content.providerMetadata) {
coreMessage.experimental_providerMetadata = message.content.providerMetadata;
}
return coreMessage;
}
/**
* Convert AI SDK V4 UIMessage to MastraDBMessage
*/
static fromUIMessage(message, ctx, messageSource) {
const filteredParts = message.parts ? filterEmptyTextParts(message.parts) : [];
const content = {
format: 2,
parts: filteredParts
};
if (message.toolInvocations) content.toolInvocations = message.toolInvocations;
if (message.reasoning) content.reasoning = message.reasoning;
if (message.annotations) content.annotations = message.annotations;
if (message.experimental_attachments) {
content.experimental_attachments = message.experimental_attachments;
}
if ("metadata" in message && message.metadata !== null && message.metadata !== void 0) {
content.metadata = message.metadata;
}
return {
id: message.id || ctx.newMessageId(),
role: TypeDetector.getRole(message),
createdAt: ctx.generateCreatedAt(messageSource, message.createdAt),
threadId: ctx.memoryInfo?.threadId,
resourceId: ctx.memoryInfo?.resourceId,
content
};
}
/**
* Convert AI SDK V4 CoreMessage to MastraDBMessage
*/
static fromCoreMessage(coreMessage, ctx, messageSource) {
const id = `id` in coreMessage ? coreMessage.id : ctx.newMessageId();
const parts = [];
const experimentalAttachments = [];
const toolInvocations = [];
const isSingleTextContent = messageSource === `response` && Array.isArray(coreMessage.content) && coreMessage.content.length === 1 && coreMessage.content[0] && coreMessage.content[0].type === `text` && `text` in coreMessage.content[0] && coreMessage.content[0].text;
if (isSingleTextContent && messageSource === `response`) {
coreMessage.content = isSingleTextContent;
}
if (typeof coreMessage.content === "string") {
parts.push({
type: "text",
text: coreMessage.content
});
} else if (Array.isArray(coreMessage.content)) {
for (const aiV4Part of coreMessage.content) {
switch (aiV4Part.type) {
case "text": {
const prevPart = parts.at(-1);
if (coreMessage.role === "assistant" && prevPart && prevPart.type === "tool-invocation") {
parts.push({ type: "step-start" });
}
const part = {
type: "text",
text: aiV4Part.text
};
if (aiV4Part.providerOptions) {
part.providerMetadata = aiV4Part.providerOptions;
}
parts.push(part);
break;
}
case "tool-call": {
const part = {
type: "tool-invocation",
toolInvocation: {
state: "call",
toolCallId: aiV4Part.toolCallId,
toolName: aiV4Part.toolName,
args: aiV4Part.args
}
};
if (aiV4Part.providerOptions) {
part.providerMetadata = aiV4Part.providerOptions;
}
parts.push(part);
break;
}
case "tool-result":
{
let toolArgs = {};
const toolCallInSameMsg = coreMessage.content.find(
(p) => p.type === "tool-call" && p.toolCallId === aiV4Part.toolCallId
);
if (toolCallInSameMsg && toolCallInSameMsg.type === "tool-call") {
toolArgs = toolCallInSameMsg.args;
}
if (Object.keys(toolArgs).length === 0 && ctx.dbMessages) {
toolArgs = findToolCallArgs(ctx.dbMessages, aiV4Part.toolCallId);
}
const invocation = {
state: "result",
toolCallId: aiV4Part.toolCallId,
toolName: aiV4Part.toolName,
result: aiV4Part.result ?? "",
args: toolArgs
};
const part = {
type: "tool-invocation",
toolInvocation: invocation
};
if (aiV4Part.providerOptions) {
part.providerMetadata = aiV4Part.providerOptions;
}
parts.push(part);
toolInvocations.push(invocation);
}
break;
case "reasoning":
{
const part = {
type: "reasoning",
reasoning: "",
details: [{ type: "text", text: aiV4Part.text, signature: aiV4Part.signature }]
};
if (aiV4Part.providerOptions) {
part.providerMetadata = aiV4Part.providerOptions;
}
parts.push(part);
}
break;
case "redacted-reasoning":
{
const part = {
type: "reasoning",
reasoning: "",
details: [{ type: "redacted", data: aiV4Part.data }]
};
if (aiV4Part.providerOptions) {
part.providerMetadata = aiV4Part.providerOptions;
}
parts.push(part);
}
break;
case "image": {
const part = {
type: "file",
data: imageContentToString(aiV4Part.image),
mimeType: aiV4Part.mimeType
};
if (aiV4Part.providerOptions) {
part.providerMetadata = aiV4Part.providerOptions;
}
parts.push(part);
break;
}
case "file": {
if (aiV4Part.data instanceof URL) {
const part = {
type: "file",
data: aiV4Part.data.toString(),
mimeType: aiV4Part.mimeType
};
if (aiV4Part.providerOptions) {
part.providerMetadata = aiV4Part.providerOptions;
}
if (aiV4Part.filename) {
part.filename = aiV4Part.filename;
}
parts.push(part);
} else if (typeof aiV4Part.data === "string") {
const categorized = categorizeFileData(aiV4Part.data, aiV4Part.mimeType);
if (categorized.type === "url" || categorized.type === "dataUri") {
const part = {
type: "file",
data: aiV4Part.data,
mimeType: categorized.mimeType || "image/png"
};
if (aiV4Part.providerOptions) {
part.providerMetadata = aiV4Part.providerOptions;
}
if (aiV4Part.filename) {
part.filename = aiV4Part.filename;
}
parts.push(part);
} else {
try {
const part = {
type: "file",
mimeType: categorized.mimeType || "image/png",
data: convertDataContentToBase64String(aiV4Part.data)
};
if (aiV4Part.providerOptions) {
part.providerMetadata = aiV4Part.providerOptions;
}
if (aiV4Part.filename) {
part.filename = aiV4Part.filename;
}
parts.push(part);
} catch (error) {
console.error(`Failed to convert binary data to base64 in CoreMessage file part: ${error}`, error);
}
}
} else {
try {
const part = {
type: "file",
mimeType: aiV4Part.mimeType,
data: convertDataContentToBase64String(aiV4Part.data)
};
if (aiV4Part.providerOptions) {
part.providerMetadata = aiV4Part.providerOptions;
}
if (aiV4Part.filename) {
part.filename = aiV4Part.filename;
}
parts.push(part);
} catch (error) {
console.error(`Failed to convert binary data to base64 in CoreMessage file part: ${error}`, error);
}
}
break;
}
}
}
}
const filteredParts = filterEmptyTextParts(parts);
const content = {
format: 2,
parts: filteredParts
};
if (toolInvocations.length) content.toolInvocations = toolInvocations;
if (typeof coreMessage.content === `string`) content.content = coreMessage.content;
if (experimentalAttachments.length) content.experimental_attachments = experimentalAttachments;
if (coreMessage.providerOptions) {
content.providerMetadata = coreMessage.providerOptions;
} else if ("experimental_providerMetadata" in coreMessage && coreMessage.experimental_providerMetadata) {
content.providerMetadata = coreMessage.experimental_providerMetadata;
}
if ("metadata" in coreMessage && coreMessage.metadata !== null && coreMessage.metadata !== void 0) {
content.metadata = coreMessage.metadata;
}
const rawCreatedAt = "metadata" in coreMessage && coreMessage.metadata && typeof coreMessage.metadata === "object" && "createdAt" in coreMessage.metadata ? coreMessage.metadata.createdAt : void 0;
return {
id,
role: TypeDetector.getRole(coreMessage),
createdAt: ctx.generateCreatedAt(messageSource, rawCreatedAt),
threadId: ctx.memoryInfo?.threadId,
resourceId: ctx.memoryInfo?.resourceId,
content
};
}
};
// src/agent/message-list/utils/tool-name.ts
var TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
var FALLBACK_TOOL_NAME = "unknown_tool";
function sanitizeToolName(toolName) {
if (typeof toolName !== "string") {
return FALLBACK_TOOL_NAME;
}
return TOOL_NAME_PATTERN.test(toolName) ? toolName : FALLBACK_TOOL_NAME;
}
// src/agent/message-list/adapters/AIV5Adapter.ts
function filterEmptyTextParts2(parts) {
const hasNonEmptyParts = parts.some((part) => !(part.type === "text" && part.text === ""));
if (!hasNonEmptyParts) return parts;
return parts.filter((part) => {
if (part.type === "text") {
return part.text !== "";
}
return true;
});
}
function getSignalType2(message) {
const signal = message.content.metadata?.signal;
if (signal && typeof signal === "object" && !Array.isArray(signal)) {
const type = signal.type;
return typeof type === "string" ? type : message.type;
}
return message.type;
}
function getTextContent(message) {
return typeof message.content.content === "string" ? message.content.content : message.content.parts.find((part) => part.type === "text")?.text ?? "";
}
function toSignalDataPart2(message) {
const signal = message.content.metadata?.signal && typeof message.content.metadata.signal === "object" ? message.content.metadata.signal : {};
const metadata = signal.metadata && typeof signal.metadata === "object" && !Array.isArray(signal.metadata) ? signal.metadata : {};
const type = getSignalType2(message) ?? "signal";
return {
type: `data-${type}`,
data: {
id: typeof signal.id === "string" ? signal.id : message.id,
type,
contents: "contents" in signal ? signal.contents : getTextContent(message),
createdAt: typeof signal.createdAt === "string" ? signal.createdAt : message.createdAt.toISOString(),
...Object.keys(metadata).length ? { metadata } : {}
}
};
}
function getToolName(type) {
if (typeof type === "object" && type && "type" in type) {
type = type.type;
}
if (typeof type !== "string") {
return sanitizeToolName(type);
}
if (type === "dynamic-tool") {
return "dynamic-tool";
}
if (type.startsWith("tool-")) {
return sanitizeToolName(type.slice("tool-".length));
}
return sanitizeToolName(type);
}
function mergeMastraCreatedAt(metadata, createdAt) {
if (createdAt == null) {
return metadata;
}
return {
...metadata || {},
mastra: {
...(metadata || {}).mastra || {},
createdAt
}
};
}
function getMastraCreatedAt(providerMetadata) {
const value = providerMetadata?.mastra;
if (!value || typeof value !== "object") {
return void 0;
}
const createdAt = value.createdAt;
return typeof createdAt === "number" ? createdAt : void 0;
}
function getDisplayTransform2(providerMetadata, phase, fallback, enabled = true) {
if (!enabled) {
return fallback;
}
const transform = chunkVPZGHUNF_cjs.getTransformedToolPayload(providerMetadata, "display", phase);
return chunkVPZGHUNF_cjs.hasTransformedToolPayload(transform) ? transform.transformed : fallback;
}
function transformToolStateDataForDisplay(data, phase, enabled = true) {
if (!enabled) {
return data;
}
if (!data || typeof data !== "object") {
return data;
}
const stateData = data;
const metadata = stateData.metadata ?? stateData.providerMetadata;
const argsTransform = chunkVPZGHUNF_cjs.getTransformedToolPayload(metadata, "display", phase);
const inputTransform = chunkVPZGHUNF_cjs.getTransformedToolPayload(metadata, "display", "input-available");
const transformedArgs = phase === "approval" ? chunkVPZGHUNF_cjs.hasTransformedToolPayload(argsTransform) ? argsTransform.transformed : chunkVPZGHUNF_cjs.hasTransformedToolPayload(inputTransform) ? inputTransform.transformed : void 0 : chunkVPZGHUNF_cjs.hasTransformedToolPayload(inputTransform) ? inputTransform.transformed : chunkVPZGHUNF_cjs.hasTransformedToolPayload(argsTransform) ? argsTransform.transformed : void 0;
const transformedSuspendPayload = phase === "suspend" && chunkVPZGHUNF_cjs.hasTransformedToolPayload(argsTransform) ? argsTransform.transformed : void 0;
return {
...stateData,
...transformedArgs !== void 0 ? { args: transformedArgs } : {},
...transformedSuspendPayload !== void 0 ? { suspendPayload: transformedSuspendPayload } : {}
};
}
var AIV5Adapter = class {
/**
* Direct conversion from MastraDBMessage to AIV5 UIMessage
*/
static toUIMessage(dbMsg, options) {
const signalType = dbMsg.role === "signal" ?