@mastra/core
Version:
Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.
1,001 lines (998 loc) • 39.9 kB
JavaScript
import { MastraFGAPermissions } from './chunk-FALOO3J7.js';
import { ToolStream } from './chunk-DD2VNRQM.js';
import { Tool, isVercelTool, isProviderDefinedTool, validateToolInput, validateToolOutput, validateToolSuspendData } from './chunk-6FFXBNBE.js';
import { standardSchemaToJSONSchema, toStandardSchema, isStandardSchemaWithJSON } from './chunk-6SRTDZ7S.js';
import { isZodObject } from './chunk-RT2LCNDN.js';
import { wrapMastra, createObservabilityContext } from './chunk-4ZCIE3Q5.js';
import { getOrCreateSpan, executeWithContext } from './chunk-MJEXAXIO.js';
import { EntityType } from './chunk-QAXRURAT.js';
import { backgroundOverrideZodSchema, backgroundOverrideJsonSchema } from './chunk-QOKJTCIS.js';
import { MastraBase } from './chunk-WENZPAHS.js';
import { MastraError } from './chunk-FJEVLHJT.js';
import { RequestContext } from './chunk-BBVL3KAA.js';
import { createHash } from 'crypto';
import { jsonSchemaToZod } from '@mastra/schema-compat/json-to-zod';
import { z } from 'zod/v4';
import { convertZodSchemaToAISDKSchema, OpenAIReasoningSchemaCompatLayer, OpenAISchemaCompatLayer, GoogleSchemaCompatLayer, AnthropicSchemaCompatLayer, DeepSeekSchemaCompatLayer, MetaSchemaCompatLayer, jsonSchema, applyCompatLayer } from '@mastra/schema-compat';
var CoreToolBuilder = class extends MastraBase {
originalTool;
options;
logType;
constructor(input) {
super({ name: "CoreToolBuilder" });
this.originalTool = input.originalTool;
this.options = input.options;
this.logType = input.logType;
const isBackgroundEligible = !!input.backgroundTaskEnabled;
const isResumableTool = input.autoResumeSuspendedTools || this.originalTool.id?.startsWith("agent-") || this.originalTool.id?.startsWith("workflow-");
if (!isVercelTool(this.originalTool) && !isProviderDefinedTool(this.originalTool)) {
if (isBackgroundEligible || isResumableTool) {
let schema = this.originalTool.inputSchema;
if (typeof schema === "function") {
schema = schema();
}
if (!schema) {
schema = z.object({});
}
if (isZodObject(schema)) {
let nextSchema = schema;
if (isBackgroundEligible) {
nextSchema = nextSchema.extend({
_background: backgroundOverrideZodSchema
});
}
if (isResumableTool) {
nextSchema = nextSchema.extend({
suspendedToolRunId: z.string().describe("The runId of the suspended tool").nullable().optional(),
resumeData: z.any().describe("The resumeData object created from the resumeSchema of suspended tool").optional()
});
}
this.originalTool.inputSchema = nextSchema;
} else {
const jsonSchema2 = standardSchemaToJSONSchema(schema, { io: "input" });
if (jsonSchema2 && typeof jsonSchema2 === "object" && jsonSchema2.type === "object") {
if (isBackgroundEligible) {
jsonSchema2.properties = {
...jsonSchema2.properties,
_background: backgroundOverrideJsonSchema
};
}
if (isResumableTool) {
jsonSchema2.properties = {
...jsonSchema2.properties,
suspendedToolRunId: {
type: ["string", "null"],
description: "The runId of the suspended tool"
},
resumeData: {
description: "The resumeData object created from the resumeSchema of suspended tool"
}
};
}
this.originalTool.inputSchema = toStandardSchema(jsonSchema2);
}
}
}
}
}
// Helper to get parameters based on tool type
getParameters = () => {
if (isVercelTool(this.originalTool)) {
let schema2 = this.originalTool.parameters ?? ("inputSchema" in this.originalTool ? this.originalTool.inputSchema : void 0) ?? z.object({});
if (typeof schema2 === "function") {
schema2 = schema2();
}
return schema2;
}
let schema = this.originalTool.inputSchema;
if (isStandardSchemaWithJSON(schema)) {
return schema;
}
if (typeof schema === "function") {
schema = schema();
}
return schema;
};
getOutputSchema = () => {
if ("outputSchema" in this.originalTool) {
let schema = this.originalTool.outputSchema;
if (isStandardSchemaWithJSON(schema)) {
return schema;
}
if (typeof schema === "function") {
schema = schema();
}
return schema;
}
return null;
};
getResumeSchema = () => {
if ("resumeSchema" in this.originalTool) {
let schema = this.originalTool.resumeSchema;
if (typeof schema === "function") {
schema = schema();
}
return schema;
}
return null;
};
getSuspendSchema = () => {
if ("suspendSchema" in this.originalTool) {
let schema = this.originalTool.suspendSchema;
if (typeof schema === "function") {
schema = schema();
}
return schema;
}
return null;
};
// For provider-defined tools, we need to include all required properties
// AI SDK v5 uses type: 'provider-defined', AI SDK v6 uses type: 'provider'
buildProviderTool(tool) {
if ("type" in tool && (tool.type === "provider-defined" || tool.type === "provider") && "id" in tool && typeof tool.id === "string" && tool.id.includes(".")) {
let parameters = "parameters" in tool ? tool.parameters : "inputSchema" in tool ? tool.inputSchema : void 0;
if (typeof parameters === "function") {
parameters = parameters();
}
let outputSchema = "outputSchema" in tool ? tool.outputSchema : void 0;
if (typeof outputSchema === "function") {
outputSchema = outputSchema();
}
let processedParameters;
if (parameters !== void 0 && parameters !== null) {
if (typeof parameters === "object" && "jsonSchema" in parameters) {
processedParameters = parameters;
} else if (isStandardSchemaWithJSON(parameters)) {
const jsonSchema2 = standardSchemaToJSONSchema(parameters, { io: "input" });
processedParameters = { jsonSchema: jsonSchema2 };
} else {
processedParameters = convertZodSchemaToAISDKSchema(parameters);
}
} else {
processedParameters = {
jsonSchema: {
type: "object",
properties: {},
additionalProperties: false
}
};
}
let processedOutputSchema;
if (outputSchema !== void 0 && outputSchema !== null) {
if (typeof outputSchema === "object" && "jsonSchema" in outputSchema) {
processedOutputSchema = outputSchema;
} else if (isStandardSchemaWithJSON(outputSchema)) {
const jsonSchema2 = standardSchemaToJSONSchema(outputSchema);
processedOutputSchema = { jsonSchema: jsonSchema2 };
} else {
processedOutputSchema = convertZodSchemaToAISDKSchema(outputSchema);
}
}
return {
...processedOutputSchema ? { outputSchema: processedOutputSchema } : {},
type: "provider-defined",
id: tool.id,
// V5 SDK factories set a hardcoded `name` (e.g. "web_search" for
// anthropic.web_search_20250305). Preserve it so that when this tool
// is later used with a V6 provider, the bidirectional toolNameMapping
// resolves the correct model-facing name instead of the versioned ID.
..."name" in tool && typeof tool.name === "string" ? { name: tool.name } : {},
args: "args" in this.originalTool ? this.originalTool.args : {},
description: tool.description,
parameters: processedParameters,
execute: this.originalTool.execute ? this.createExecute(
this.originalTool,
{ ...this.options, description: this.originalTool.description },
this.logType
) : void 0,
toModelOutput: "toModelOutput" in this.originalTool ? this.originalTool.toModelOutput : void 0,
transform: "transform" in this.originalTool ? this.originalTool.transform : void 0,
inputExamples: "inputExamples" in this.originalTool ? this.originalTool.inputExamples : void 0
};
}
return void 0;
}
createLogMessageOptions({ agentName, toolName, type }) {
const toolType = type === "toolset" ? "toolset" : "tool";
return {
start: `Executing ${toolType}`,
error: `Failed ${toolType} execution`,
logData: { agent: agentName, tool: toolName }
};
}
createExecute(tool, options, logType) {
const {
logger,
mastra: _mastra,
memory: _memory,
requestContext,
model,
tracingContext: _tracingContext,
tracingPolicy: _tracingPolicy,
...rest
} = options;
const logModelObject = {
modelId: model?.modelId,
provider: model?.provider,
specificationVersion: model?.specificationVersion
};
const { start, logData } = this.createLogMessageOptions({
agentName: options.agentName,
toolName: options.name,
type: logType
});
const mcpMeta = !isVercelTool(tool) && "mcpMetadata" in tool ? tool.mcpMetadata : void 0;
const execFunction = async (args, execOptions, toolSpan) => {
try {
let result;
let suspendData = null;
if (isVercelTool(tool)) {
result = await executeWithContext({
span: toolSpan,
fn: async () => tool?.execute?.(args, execOptions)
});
} else {
const wrappedMastra = options.mastra ? wrapMastra(options.mastra, { currentSpan: toolSpan }) : options.mastra;
const resumeSchema = this.getResumeSchema();
const baseContext = {
threadId: options.threadId,
resourceId: options.resourceId,
mastra: wrappedMastra,
memory: options.memory,
runId: options.runId,
requestContext: execOptions.requestContext ?? options.requestContext ?? new RequestContext(),
// Workspace for file operations and command execution
// Execution-time workspace (from prepareStep/processInputStep) takes precedence over build-time workspace
workspace: execOptions.workspace ?? options.workspace,
// Browser for web automation (lazily initialized on first use)
browser: options.browser,
writer: new ToolStream(
{
prefix: "tool",
callId: execOptions.toolCallId,
name: options.name,
runId: options.runId
},
options.outputWriter || execOptions.outputWriter
),
...createObservabilityContext({ currentSpan: toolSpan }),
abortSignal: execOptions.abortSignal,
suspend: (args2, suspendOptions) => {
suspendData = args2;
const newSuspendOptions = {
...suspendOptions ?? {},
resumeSchema: suspendOptions?.resumeSchema ?? (resumeSchema ? JSON.stringify(standardSchemaToJSONSchema(toStandardSchema(resumeSchema), { io: "input" })) : void 0)
};
return execOptions.suspend?.(args2, newSuspendOptions);
},
resumeData: execOptions.resumeData
};
const isAgentExecution = execOptions.toolCallId && execOptions.messages || options.agentName && options.threadId && !options.workflowId;
const isWorkflowExecution = !isAgentExecution && (options.workflow || options.workflowId);
let toolContext;
if (isAgentExecution) {
const { suspend, resumeData: resumeData2, threadId, resourceId, ...restBaseContext } = baseContext;
toolContext = {
...restBaseContext,
agent: {
agentId: options.agentId || "",
toolCallId: execOptions.toolCallId || "",
messages: execOptions.messages || [],
suspend,
resumeData: resumeData2,
threadId,
resourceId,
outputWriter: execOptions.outputWriter,
flushMessages: execOptions.flushMessages
}
};
} else if (isWorkflowExecution) {
const { suspend, resumeData: resumeData2, ...restBaseContext } = baseContext;
toolContext = {
...restBaseContext,
workflow: options.workflow || {
runId: options.runId,
workflowId: options.workflowId,
state: options.state,
setState: options.setState,
suspend,
resumeData: resumeData2
}
};
} else if (execOptions.mcp) {
toolContext = {
...baseContext,
mcp: execOptions.mcp
};
} else {
toolContext = baseContext;
}
const resumeData = execOptions.resumeData;
if (resumeData) {
const resumeValidation = validateToolInput(resumeSchema, resumeData, options.name);
if (resumeValidation.error) {
logger?.warn(resumeValidation.error.message);
toolSpan?.end({ output: resumeValidation.error, attributes: { success: false } });
return resumeValidation.error;
}
}
result = await executeWithContext({ span: toolSpan, fn: async () => tool?.execute?.(args, toolContext) });
}
if (suspendData) {
const suspendSchema = this.getSuspendSchema();
const suspendValidation = validateToolSuspendData(suspendSchema, suspendData, options.name);
if (suspendValidation.error) {
logger?.warn(suspendValidation.error.message);
toolSpan?.end({ output: suspendValidation.error, attributes: { success: false } });
return suspendValidation.error;
}
}
const shouldSkipValidation = typeof result === "undefined" && !!suspendData;
if (shouldSkipValidation) {
toolSpan?.end({ output: result, attributes: { success: true } });
return result;
}
if (isVercelTool(tool)) {
const outputSchema = this.getOutputSchema();
const outputValidation = validateToolOutput(outputSchema, result, options.name, false);
if (outputValidation.error) {
logger?.warn(outputValidation.error.message);
toolSpan?.end({ output: outputValidation.error, attributes: { success: false } });
return outputValidation.error;
}
result = outputValidation.data;
}
toolSpan?.end({ output: result, attributes: { success: true } });
return result;
} catch (error) {
toolSpan?.error({ error, attributes: { success: false } });
throw error;
}
};
return async (args, execOptions) => {
let logger2 = options.logger || this.logger;
const tracingContext = execOptions?.tracingContext || options.tracingContext;
const toolRequestContext = execOptions?.requestContext ?? options.requestContext;
const toolSpan = getOrCreateSpan({
type: mcpMeta ? "mcp_tool_call" /* MCP_TOOL_CALL */ : "tool_call" /* TOOL_CALL */,
name: mcpMeta ? `mcp_tool: '${options.name}' on '${mcpMeta.serverName}'` : `tool: '${options.name}'`,
input: args,
entityType: EntityType.TOOL,
entityId: options.name,
entityName: options.name,
attributes: mcpMeta ? {
mcpServer: mcpMeta.serverName,
serverVersion: mcpMeta.serverVersion,
toolDescription: options.description
} : {
toolDescription: options.description,
toolType: logType || "tool"
},
tracingPolicy: options.tracingPolicy,
tracingContext,
requestContext: toolRequestContext,
mastra: options.mastra && "observability" in options.mastra ? options.mastra : void 0
});
const fgaProvider = options.mastra?.getServer?.()?.fga;
const user = toolRequestContext?.get("user");
if (fgaProvider) {
const { getAgentToolFGAResourceId, getMCPToolFGAResourceId, getStandaloneToolFGAResourceId, requireFGA } = await import('./fga-check-Q36KXW34.js');
const toolResourceId = mcpMeta?.serverName ? getMCPToolFGAResourceId(mcpMeta.serverName, options.name) : options.agentId ? getAgentToolFGAResourceId(options.agentId, options.name) : getStandaloneToolFGAResourceId(options.name);
await requireFGA({
fgaProvider,
user,
resource: { type: "tool", id: toolResourceId },
permission: MastraFGAPermissions.TOOLS_EXECUTE,
requestContext: toolRequestContext,
context: {
resourceId: options.resourceId
},
metadata: {
toolName: options.name,
agentId: options.agentId,
agentName: options.agentName,
runId: options.runId,
threadId: options.threadId,
executionResourceId: options.resourceId,
mcpMetadata: mcpMeta
}
});
}
try {
logger2.debug(start, { ...logData, ...rest, model: logModelObject, args });
const parameters = this.getParameters();
const { data, error } = validateToolInput(parameters, args, options.name);
const suspendedToolRunIdErrToIgnore = error?.message?.includes("suspendedToolRunId: Required") && !args?.resumeData;
if (error && !suspendedToolRunIdErrToIgnore) {
logger2.warn("Tool input validation failed", { ...logData, validationError: error.message });
toolSpan?.end({ output: error, attributes: { success: false } });
return error;
}
args = data;
return await new Promise((resolve, reject) => {
setImmediate(async () => {
try {
const result = await execFunction(args, execOptions, toolSpan);
resolve(result);
} catch (err) {
reject(err);
}
});
});
} catch (err) {
const mastraError = new MastraError(
{
id: "TOOL_EXECUTION_FAILED",
domain: "TOOL" /* TOOL */,
category: "USER" /* USER */,
details: {
errorMessage: String(err),
argsJson: safeStringify(args),
model: model?.modelId ?? ""
}
},
err
);
toolSpan?.error({ error: mastraError, attributes: { success: false } });
logger2.trackException(mastraError, { ...logData, ...rest, model: logModelObject, args });
throw mastraError;
}
};
}
buildV5() {
const builtTool = this.build();
if (!builtTool.parameters) {
throw new Error("Tool parameters are required");
}
const base = {
...builtTool,
inputSchema: builtTool.parameters,
onInputStart: "onInputStart" in this.originalTool ? this.originalTool.onInputStart : void 0,
onInputDelta: "onInputDelta" in this.originalTool ? this.originalTool.onInputDelta : void 0,
onInputAvailable: "onInputAvailable" in this.originalTool ? this.originalTool.onInputAvailable : void 0,
onOutput: "onOutput" in this.originalTool ? this.originalTool.onOutput : void 0
};
if (builtTool.type === "provider-defined") {
const { execute, parameters, ...rest } = base;
const name = ("name" in builtTool && typeof builtTool.name === "string" ? builtTool.name : null) || builtTool.id.split(".")[1] || builtTool.id;
return {
...rest,
type: builtTool.type,
id: builtTool.id,
name,
args: builtTool.args
};
}
return base;
}
build() {
const providerTool = this.buildProviderTool(this.originalTool);
if (providerTool) {
return providerTool;
}
const model = this.options.model;
const schemaCompatLayers = [];
if (model) {
const supportsStructuredOutputs = "supportsStructuredOutputs" in model ? model.supportsStructuredOutputs ?? false : false;
const modelInfo = {
modelId: model.modelId,
supportsStructuredOutputs,
provider: model.provider
};
schemaCompatLayers.push(
new OpenAIReasoningSchemaCompatLayer(modelInfo),
new OpenAISchemaCompatLayer(modelInfo),
new GoogleSchemaCompatLayer(modelInfo),
new AnthropicSchemaCompatLayer(modelInfo),
new DeepSeekSchemaCompatLayer(modelInfo),
new MetaSchemaCompatLayer(modelInfo)
);
}
const originalSchema = this.getParameters();
let processedInputSchema;
if (originalSchema) {
if (isStandardSchemaWithJSON(originalSchema)) {
const applicableLayer = schemaCompatLayers.find((layer) => layer.shouldApply());
let schemaToUse;
if (applicableLayer) {
schemaToUse = applicableLayer.processToCompatSchema(originalSchema);
} else {
schemaToUse = toStandardSchema(originalSchema);
}
processedInputSchema = jsonSchema(
standardSchemaToJSONSchema(schemaToUse, {
io: "input"
}),
{
validate: (value) => {
const result = schemaToUse["~standard"].validate(value);
if (result instanceof Promise) {
return result.then((r) => {
if ("issues" in r && r.issues) {
return {
success: false,
error: new Error(r.issues.map((i) => i.message).join(", "))
};
}
return { success: true, value: r.value };
});
}
if ("issues" in result && result.issues) {
return {
success: false,
error: new Error(result.issues.map((i) => i.message).join(", "))
};
}
return { success: true, value: result.value };
}
}
);
} else {
processedInputSchema = applyCompatLayer({
schema: originalSchema,
compatLayers: schemaCompatLayers,
mode: "aiSdkSchema"
});
}
}
const outputSchema = this.getOutputSchema();
let processedOutputSchema;
if (outputSchema) {
if (isStandardSchemaWithJSON(outputSchema)) {
processedOutputSchema = standardSchemaToJSONSchema(outputSchema, { io: "output" });
} else {
processedOutputSchema = applyCompatLayer({
schema: outputSchema,
compatLayers: [],
mode: "aiSdkSchema"
});
}
}
let requireApproval = false;
let needsApprovalFn;
if (typeof this.options.requireApproval === "function") {
requireApproval = true;
needsApprovalFn = this.options.requireApproval;
} else if (typeof this.options.requireApproval === "boolean") {
requireApproval = this.options.requireApproval;
needsApprovalFn = void 0;
}
if (isVercelTool(this.originalTool) && "needsApproval" in this.originalTool) {
const needsApproval = this.originalTool.needsApproval;
if (typeof needsApproval === "boolean") {
requireApproval = needsApproval;
needsApprovalFn = void 0;
} else if (typeof needsApproval === "function") {
needsApprovalFn = needsApproval;
requireApproval = true;
}
}
const definition = {
type: "function",
description: this.originalTool.description,
requireApproval,
needsApprovalFn,
hasSuspendSchema: !!this.getSuspendSchema(),
execute: this.originalTool.execute ? this.createExecute(
this.originalTool,
{ ...this.options, description: this.originalTool.description },
this.logType
) : void 0
};
return {
...definition,
id: "id" in this.originalTool ? this.originalTool.id : void 0,
parameters: processedInputSchema ?? z.object({}),
outputSchema: processedOutputSchema,
strict: "strict" in this.originalTool ? this.originalTool.strict : void 0,
providerOptions: "providerOptions" in this.originalTool ? this.originalTool.providerOptions : void 0,
mcp: "mcp" in this.originalTool ? this.originalTool.mcp : void 0,
toModelOutput: "toModelOutput" in this.originalTool ? this.originalTool.toModelOutput : void 0,
transform: "transform" in this.originalTool ? this.originalTool.transform : void 0,
inputExamples: "inputExamples" in this.originalTool ? this.originalTool.inputExamples : void 0,
onInputStart: "onInputStart" in this.originalTool ? this.originalTool.onInputStart : void 0,
onInputDelta: "onInputDelta" in this.originalTool ? this.originalTool.onInputDelta : void 0,
onInputAvailable: "onInputAvailable" in this.originalTool ? this.originalTool.onInputAvailable : void 0,
onOutput: "onOutput" in this.originalTool ? this.originalTool.onOutput : void 0,
// Preserve tool-level background config so the agentic loop can pick it up
// from the converted CoreTool at dispatch time.
backgroundConfig: this.options.backgroundConfig
};
}
};
// src/utils.ts
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
function safeStringify(value, space) {
const stack = [];
return JSON.stringify(
value,
function(_key, val) {
if (typeof val === "bigint") return val.toString();
if (val !== null && typeof val === "object") {
while (stack.length > 0 && stack[stack.length - 1] !== this) {
stack.pop();
}
if (stack.includes(val)) return "[Circular]";
stack.push(val);
}
return val;
},
space
);
}
function ensureSerializable(value) {
if (value === null || typeof value !== "object") return value;
try {
JSON.stringify(value);
return value;
} catch {
return JSON.parse(safeStringify(value));
}
}
function isPlainObject(value) {
if (value === null || typeof value !== "object") return false;
const proto = Object.getPrototypeOf(value);
return proto === Object.prototype || proto === null;
}
function deepMerge(target, source) {
const output = { ...target };
if (!source) return output;
Object.keys(source).forEach((key) => {
const targetValue = output[key];
const sourceValue = source[key];
if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {
output[key] = deepMerge(targetValue, sourceValue);
} else if (sourceValue !== void 0) {
output[key] = sourceValue;
}
});
return output;
}
function deepEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return a === b;
if (typeof a !== typeof b) return false;
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) return false;
return a.every((item, index) => deepEqual(item, b[index]));
}
if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime();
}
if (typeof a === "object" && typeof b === "object") {
const aObj = a;
const bObj = b;
const aKeys = Object.keys(aObj);
const bKeys = Object.keys(bObj);
if (aKeys.length !== bKeys.length) return false;
return aKeys.every((key) => Object.prototype.hasOwnProperty.call(bObj, key) && deepEqual(aObj[key], bObj[key]));
}
return false;
}
function generateEmptyFromSchema(schema) {
try {
const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
if (!parsedSchema || parsedSchema.type !== "object" || !parsedSchema.properties) return {};
const obj = {};
for (const [key, prop] of Object.entries(
parsedSchema.properties
)) {
if (prop.default !== void 0) {
obj[key] = typeof prop.default === "object" && prop.default !== null ? JSON.parse(JSON.stringify(prop.default)) : prop.default;
} else if (prop.type === "object" && prop.properties) {
obj[key] = generateEmptyFromSchema(prop);
} else if (prop.type === "object") {
obj[key] = {};
} else if (prop.type === "string") {
obj[key] = "";
} else if (prop.type === "array") {
obj[key] = [];
} else if (prop.type === "number" || prop.type === "integer") {
obj[key] = 0;
} else if (prop.type === "boolean") {
obj[key] = false;
} else {
obj[key] = null;
}
}
return obj;
} catch {
return {};
}
}
async function* maskStreamTags(stream, tag, options = {}) {
const { onStart, onEnd, onMask } = options;
const openTag = `<${tag}>`;
const closeTag = `</${tag}>`;
let buffer = "";
let fullContent = "";
let isMasking = false;
let isBuffering = false;
const trimOutsideDelimiter = (text, delimiter, trim) => {
if (!text.includes(delimiter)) {
return text;
}
const parts = text.split(delimiter);
if (trim === `before-start`) {
return `${delimiter}${parts[1]}`;
}
return `${parts[0]}${delimiter}`;
};
const startsWith = (text, pattern) => {
if (pattern.includes(openTag.substring(0, 3))) {
pattern = trimOutsideDelimiter(pattern, `<`, `before-start`);
}
return text.trim().startsWith(pattern.trim());
};
for await (const chunk of stream) {
fullContent += chunk;
if (isBuffering) buffer += chunk;
const chunkHasTag = startsWith(chunk, openTag);
const bufferHasTag = !chunkHasTag && isBuffering && startsWith(openTag, buffer);
let toYieldBeforeMaskedStartTag = ``;
if (!isMasking && (chunkHasTag || bufferHasTag)) {
isMasking = true;
isBuffering = false;
const taggedTextToMask = trimOutsideDelimiter(buffer, `<`, `before-start`);
if (taggedTextToMask !== buffer.trim()) {
toYieldBeforeMaskedStartTag = buffer.replace(taggedTextToMask, ``);
}
buffer = "";
onStart?.();
}
if (!isMasking && !isBuffering && startsWith(openTag, chunk) && chunk.trim() !== "") {
isBuffering = true;
buffer += chunk;
continue;
}
if (isBuffering && buffer && !startsWith(openTag, buffer)) {
yield buffer;
buffer = "";
isBuffering = false;
continue;
}
if (isMasking && fullContent.includes(closeTag)) {
onMask?.(chunk);
onEnd?.();
isMasking = false;
const lastFullContent = fullContent;
fullContent = ``;
const textUntilEndTag = trimOutsideDelimiter(lastFullContent, closeTag, "after-end");
if (textUntilEndTag !== lastFullContent) {
yield lastFullContent.replace(textUntilEndTag, ``);
}
continue;
}
if (isMasking) {
onMask?.(chunk);
if (toYieldBeforeMaskedStartTag) {
yield toYieldBeforeMaskedStartTag;
}
continue;
}
yield chunk;
}
}
function resolveSerializedZodOutput(schema) {
return Function("z", `"use strict";return (${schema});`)(z);
}
function isZodType(value) {
return typeof value === "object" && value !== null && "_def" in value && "parse" in value && typeof value.parse === "function" && "safeParse" in value && typeof value.safeParse === "function";
}
function createDeterministicId(input) {
return createHash("sha256").update(input).digest("hex").slice(0, 8);
}
function setVercelToolProperties(tool) {
const inputSchema = "inputSchema" in tool ? tool.inputSchema : convertVercelToolParameters(tool);
const toolId = !("id" in tool) ? tool.description ? `tool-${createDeterministicId(tool.description)}` : `tool-${Math.random().toString(36).substring(2, 9)}` : tool.id;
return {
...tool,
id: toolId,
inputSchema
};
}
function ensureToolProperties(tools) {
const toolsWithProperties = Object.keys(tools).reduce((acc, key) => {
const tool = tools?.[key];
if (tool) {
if (typeof tool === "function" && !(tool instanceof Tool) && !isVercelTool(tool)) {
throw new MastraError({
id: "TOOL_INVALID_FORMAT",
domain: "TOOL" /* TOOL */,
category: "USER" /* USER */,
text: `Tool "${key}" is not a valid tool format. Tools must be created using createTool() or be a valid Vercel AI SDK tool. Received a function.`
});
}
if (isVercelTool(tool)) {
acc[key] = setVercelToolProperties(tool);
} else {
acc[key] = tool;
}
}
return acc;
}, {});
return toolsWithProperties;
}
function convertVercelToolParameters(tool) {
let schema = tool.parameters ?? z.object({});
if (typeof schema === "function") {
schema = schema();
}
return isZodType(schema) ? schema : resolveSerializedZodOutput(jsonSchemaToZod(schema));
}
function makeCoreTool(originalTool, options, logType, autoResumeSuspendedTools, backgroundTaskEnabled) {
return new CoreToolBuilder({
originalTool,
options,
logType,
autoResumeSuspendedTools,
backgroundTaskEnabled
}).build();
}
function makeCoreToolV5(originalTool, options, logType, autoResumeSuspendedTools, backgroundTaskEnabled) {
return new CoreToolBuilder({
originalTool,
options,
logType,
autoResumeSuspendedTools,
backgroundTaskEnabled
}).buildV5();
}
function createMastraProxy({ mastra, logger }) {
return new Proxy(mastra, {
get(target, prop) {
const hasProp = Reflect.has(target, prop);
if (hasProp) {
const value = Reflect.get(target, prop);
const isFunction = typeof value === "function";
if (isFunction) {
return value.bind(target);
}
return value;
}
if (prop === "logger") {
logger.warn("Please use 'getLogger' instead, logger is deprecated");
return Reflect.apply(target.getLogger, target, []);
}
if (prop === "storage") {
logger.warn("Please use 'getStorage' instead, storage is deprecated");
return Reflect.get(target, "storage");
}
if (prop === "agents") {
logger.warn("Please use 'listAgents' instead, agents is deprecated");
return Reflect.apply(target.listAgents, target, []);
}
if (prop === "tts") {
logger.warn("Please use 'getTTS' instead, tts is deprecated");
return Reflect.apply(target.getTTS, target, []);
}
if (prop === "vectors") {
logger.warn("Please use 'getVectors' instead, vectors is deprecated");
return Reflect.apply(target.getVectors, target, []);
}
if (prop === "memory") {
logger.warn("Please use 'getMemory' instead, memory is deprecated");
return Reflect.get(target, "memory");
}
return Reflect.get(target, prop);
}
});
}
function checkEvalStorageFields(traceObject, logger) {
const missingFields = [];
if (!traceObject.input) missingFields.push("input");
if (!traceObject.output) missingFields.push("output");
if (!traceObject.agentName) missingFields.push("agent_name");
if (!traceObject.metricName) missingFields.push("metric_name");
if (!traceObject.instructions) missingFields.push("instructions");
if (!traceObject.globalRunId) missingFields.push("global_run_id");
if (!traceObject.runId) missingFields.push("run_id");
if (missingFields.length > 0) {
if (logger) {
logger.warn("Skipping evaluation storage due to missing required fields", {
missingFields,
runId: traceObject.runId,
agentName: traceObject.agentName
});
} else {
console.warn("Skipping evaluation storage due to missing required fields", {
missingFields,
runId: traceObject.runId,
agentName: traceObject.agentName
});
}
return false;
}
return true;
}
function detectSingleMessageCharacteristics(message) {
if (typeof message === "object" && message !== null && (message.role === "function" || // UI-only role
message.role === "data" || // UI-only role
"toolInvocations" in message || // UI-specific field
"parts" in message || // UI-specific field
"experimental_attachments" in message)) {
return "has-ui-specific-parts";
} else if (typeof message === "object" && message !== null && "content" in message && (Array.isArray(message.content) || // Core messages can have array content
"experimental_providerMetadata" in message || "providerOptions" in message)) {
return "has-core-specific-parts";
} else if (typeof message === "object" && message !== null && "role" in message && "content" in message && typeof message.content === "string" && ["system", "user", "assistant", "tool"].includes(message.role)) {
return "message";
} else {
return "other";
}
}
function isUiMessage(message) {
return detectSingleMessageCharacteristics(message) === `has-ui-specific-parts`;
}
function isCoreMessage(message) {
return [`has-core-specific-parts`, `message`].includes(detectSingleMessageCharacteristics(message));
}
var SQL_IDENTIFIER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
function parseSqlIdentifier(name, kind = "identifier") {
if (!SQL_IDENTIFIER_PATTERN.test(name) || name.length > 63) {
throw new Error(
`Invalid ${kind}: ${name}. Must start with a letter or underscore, contain only letters, numbers, or underscores, and be at most 63 characters long.`
);
}
return name;
}
function parseFieldKey(key) {
if (!key) throw new Error("Field key cannot be empty");
const segments = key.split(".");
for (const segment of segments) {
if (!SQL_IDENTIFIER_PATTERN.test(segment) || segment.length > 63) {
throw new Error(`Invalid field key segment: ${segment} in ${key}`);
}
}
return key;
}
function omitKeys(obj, keysToOmit) {
return Object.fromEntries(Object.entries(obj).filter(([key]) => !keysToOmit.includes(key)));
}
function selectFields(obj, fields) {
if (!obj || typeof obj !== "object") {
return obj;
}
const result = {};
for (const field of fields) {
const value = getNestedValue(obj, field);
if (value !== void 0) {
setNestedValue(result, field, value);
}
}
return result;
}
function getNestedValue(obj, path) {
return path.split(".").reduce((current, key) => {
return current && typeof current === "object" ? current[key] : void 0;
}, obj);
}
function setNestedValue(obj, path, value) {
const keys = path.split(".");
const lastKey = keys.pop();
if (!lastKey) return;
for (const key of keys) {
if (key === "__proto__" || key === "constructor" || key === "prototype") {
return;
}
}
if (lastKey === "__proto__" || lastKey === "constructor" || lastKey === "prototype") {
return;
}
let current = obj;
for (const key of keys) {
const existing = Object.prototype.hasOwnProperty.call(current, key) ? current[key] : void 0;
if (existing === null || typeof existing !== "object") {
const container = /* @__PURE__ */ Object.create(null);
Object.defineProperty(current, key, { value: container, writable: true, enumerable: true, configurable: true });
}
current = current[key];
}
Object.defineProperty(current, lastKey, { value, writable: true, enumerable: true, configurable: true });
}
var removeUndefinedValues = (obj) => {
return Object.fromEntries(Object.entries(obj).filter(([_, value]) => value !== void 0));
};
export { checkEvalStorageFields, createMastraProxy, deepEqual, deepMerge, delay, ensureSerializable, ensureToolProperties, generateEmptyFromSchema, getNestedValue, isCoreMessage, isUiMessage, isZodType, makeCoreTool, makeCoreToolV5, maskStreamTags, omitKeys, parseFieldKey, parseSqlIdentifier, removeUndefinedValues, resolveSerializedZodOutput, safeStringify, selectFields, setNestedValue };
//# sourceMappingURL=chunk-K3E3M5U5.js.map
//# sourceMappingURL=chunk-K3E3M5U5.js.map