import { standardSchemaToJSONSchema, toStandardSchema } from './chunk-6SRTDZ7S.js';
import { unwrapZodType, isZodObject, getZodTypeName, isZodArray } from './chunk-RT2LCNDN.js';
import { RequestContext } from './chunk-AJVVIFTH.js';

// src/tools/validation.ts
function safeValidate(schema, data) {
  try {
    const result = schema["~standard"].validate(data);
    if (result instanceof Promise) {
      throw new Error("Your schema is async, which is not supported. Please use a sync schema.");
    }
    return result;
  } catch (err) {
    if (err instanceof TypeError && err.message.includes("Cannot read properties of undefined")) {
      throw new Error(
        `Schema validation failed due to an invalid schema definition. This often happens when a union schema (z.union or z.or) has undefined options. Please check that all schema options are properly defined. Original error: ${err.message}`
      );
    }
    throw err;
  }
}
function isValidationError(value) {
  return value !== null && typeof value === "object" && "error" in value && value.error === true && "validationErrors" in value;
}
function getPathKey(segment) {
  if (typeof segment === "object" && segment !== null && "key" in segment) {
    return String(segment.key);
  }
  return String(segment);
}
function createEmptyErrors() {
  return { errors: [], fields: {} };
}
function buildFormattedErrors(issues) {
  const result = createEmptyErrors();
  for (const issue of issues) {
    if (!issue.path || issue.path.length === 0) {
      result.errors.push(issue.message);
    } else {
      let current = result;
      for (let i = 0; i < issue.path.length; i++) {
        const key = getPathKey(issue.path[i]);
        if (i === issue.path.length - 1) {
          if (!current.fields[key]) {
            current.fields[key] = createEmptyErrors();
          }
          current.fields[key].errors.push(issue.message);
        } else {
          if (!current.fields[key]) {
            current.fields[key] = createEmptyErrors();
          }
          current = current.fields[key];
        }
      }
    }
  }
  return result;
}
function truncateForLogging(data, maxLength = 200) {
  try {
    const stringified = JSON.stringify(data, null, 2);
    if (stringified.length <= maxLength) {
      return stringified;
    }
    return stringified.slice(0, maxLength) + "... (truncated)";
  } catch {
    return "[Unable to serialize data]";
  }
}
function validateToolSuspendData(schema, suspendData, toolId) {
  if (!schema || !("~standard" in schema)) {
    return { data: suspendData };
  }
  const validation = safeValidate(schema, suspendData);
  if ("value" in validation) {
    return { data: validation.value };
  }
  const errorMessages = validation.issues.map((e) => `- ${e.path?.join(".") || "root"}: ${e.message}`).join("\n");
  const error = {
    error: true,
    message: `Tool suspension data validation failed${toolId ? ` for ${toolId}` : ""}. Please fix the following errors and try again:
${errorMessages}

Provided arguments: ${truncateForLogging(suspendData)}`,
    validationErrors: buildFormattedErrors(validation.issues)
  };
  return { error };
}
function normalizeNullishInput(schema, input) {
  if (typeof input !== "undefined" && input !== null) {
    return input;
  }
  const jsonSchema = standardSchemaToJSONSchema(schema, { io: "input" });
  if (jsonSchema.type === "array") {
    return [];
  }
  if (jsonSchema.type === "object") {
    return {};
  }
  return input;
}
function isPlainObject(value) {
  if (value === null || typeof value !== "object") {
    return false;
  }
  const proto = Object.getPrototypeOf(value);
  return proto === Object.prototype || proto === null;
}
function convertUndefinedToNull(input) {
  if (input === void 0) {
    return null;
  }
  if (input === null || typeof input !== "object") {
    return input;
  }
  if (Array.isArray(input)) {
    return input.map(convertUndefinedToNull);
  }
  if (!isPlainObject(input)) {
    return input;
  }
  const result = {};
  for (const [key, value] of Object.entries(input)) {
    result[key] = convertUndefinedToNull(value);
  }
  return result;
}
function stripNullishValues(input) {
  if (input === null || input === void 0) {
    return void 0;
  }
  if (typeof input !== "object") {
    return input;
  }
  if (Array.isArray(input)) {
    return input.map((item) => item === null ? null : stripNullishValues(item));
  }
  if (!isPlainObject(input)) {
    return input;
  }
  const result = {};
  for (const [key, value] of Object.entries(input)) {
    if (value === null || value === void 0) {
      continue;
    }
    result[key] = stripNullishValues(value);
  }
  return result;
}
function stripNullishValuesAtPaths(input, paths, currentPath = "") {
  if (input === null || input === void 0) {
    return paths.has(currentPath) ? void 0 : input;
  }
  if (typeof input !== "object") {
    return input;
  }
  if (Array.isArray(input)) {
    return input.map(
      (item, i) => stripNullishValuesAtPaths(item, paths, currentPath ? `${currentPath}.${i}` : String(i))
    );
  }
  if (!isPlainObject(input)) {
    return input;
  }
  const result = {};
  for (const [key, value] of Object.entries(input)) {
    const fieldPath = currentPath ? `${currentPath}.${key}` : key;
    if ((value === null || value === void 0) && paths.has(fieldPath)) {
      continue;
    }
    result[key] = stripNullishValuesAtPaths(value, paths, fieldPath);
  }
  return result;
}
var PATH_NOT_FOUND = /* @__PURE__ */ Symbol("PATH_NOT_FOUND");
function getValueAtPath(obj, pathSegments) {
  let current = obj;
  for (const segment of pathSegments) {
    if (current === null || current === void 0 || typeof current !== "object") {
      return PATH_NOT_FOUND;
    }
    const key = typeof segment === "object" && segment !== null && "key" in segment ? String(segment.key) : String(segment);
    current = current[key];
  }
  return current;
}
function coerceStringifiedJsonValues(schema, input) {
  if (!isPlainObject(input)) {
    return input;
  }
  const unwrapped = unwrapZodType(schema);
  if (!isZodObject(unwrapped)) {
    return input;
  }
  const shape = unwrapped.shape;
  if (!shape || typeof shape !== "object") {
    return input;
  }
  let changed = false;
  const result = { ...input };
  for (const [key, value] of Object.entries(input)) {
    if (typeof value !== "string") {
      continue;
    }
    const fieldSchema = shape[key];
    if (!fieldSchema) {
      continue;
    }
    const baseFieldSchema = unwrapZodType(fieldSchema);
    if (getZodTypeName(baseFieldSchema) === "ZodString") {
      continue;
    }
    const trimmed = value.trim();
    if (isZodArray(baseFieldSchema) && trimmed.startsWith("[") || isZodObject(baseFieldSchema) && trimmed.startsWith("{")) {
      try {
        const parsed = JSON.parse(value);
        if (isZodArray(baseFieldSchema) && Array.isArray(parsed) || isZodObject(baseFieldSchema) && isPlainObject(parsed)) {
          result[key] = parsed;
          changed = true;
        }
      } catch {
      }
    }
  }
  return changed ? result : input;
}
function validateToolInput(schema, input, toolId) {
  if (!schema || !("~standard" in schema)) {
    return { data: input };
  }
  let normalizedInput = normalizeNullishInput(schema, input);
  normalizedInput = convertUndefinedToNull(normalizedInput);
  const validation = safeValidate(schema, normalizedInput);
  if ("value" in validation) {
    return { data: validation.value };
  }
  const coercedInput = coerceStringifiedJsonValues(schema, normalizedInput);
  if (coercedInput !== normalizedInput) {
    const coercedValidation = safeValidate(schema, coercedInput);
    if ("value" in coercedValidation) {
      return { data: coercedValidation.value };
    }
  }
  const failingNullPaths = new Set(
    validation.issues.filter((issue) => {
      if (!issue.path || issue.path.length === 0) return false;
      const value = getValueAtPath(normalizedInput, issue.path);
      return value === null || value === void 0;
    }).map((issue) => issue.path?.map((p) => typeof p === "object" && "key" in p ? String(p.key) : String(p)).join(".")).filter((p) => !!p)
  );
  const strippedInput = failingNullPaths.size > 0 ? stripNullishValuesAtPaths(input, failingNullPaths) : stripNullishValues(input);
  const normalizedStripped = normalizeNullishInput(schema, strippedInput);
  const retryValidation = safeValidate(schema, normalizedStripped);
  if ("value" in retryValidation) {
    return { data: retryValidation.value };
  }
  const promptJsonSchema = standardSchemaToJSONSchema(schema, { io: "input" });
  const schemaExpectsPrompt = promptJsonSchema.type === "object" && promptJsonSchema.properties != null && "prompt" in promptJsonSchema.properties;
  if (schemaExpectsPrompt && normalizedInput != null && typeof normalizedInput === "object" && !Array.isArray(normalizedInput)) {
    const obj = normalizedInput;
    if (obj.prompt == null) {
      const alias = [obj.query, obj.message, obj.input].find((v) => typeof v === "string");
      if (alias !== void 0) {
        const coercedPromptInput = { ...obj, prompt: alias };
        const coercedPromptValidation = safeValidate(schema, coercedPromptInput);
        if ("value" in coercedPromptValidation) {
          return { data: coercedPromptValidation.value };
        }
      }
    }
  }
  const errorMessages = validation.issues.map((e) => `- ${e.path?.join(".") || "root"}: ${e.message}`).join("\n");
  const error = {
    error: true,
    message: `Tool input validation failed${toolId ? ` for ${toolId}` : ""}. Please fix the following errors and try again:
${errorMessages}

Provided arguments: ${truncateForLogging(input)}`,
    validationErrors: buildFormattedErrors(validation.issues)
  };
  return { error };
}
function validateToolOutput(schema, output, toolId, suspendCalled) {
  if (!schema || !("~standard" in schema) || suspendCalled) {
    return { data: output };
  }
  const validation = safeValidate(schema, output);
  if ("value" in validation) {
    return { data: validation.value };
  }
  const errorMessages = validation.issues.map((e) => `- ${e.path?.join(".") || "root"}: ${e.message}`).join("\n");
  const error = {
    error: true,
    message: `Tool output validation failed${toolId ? ` for ${toolId}` : ""}. The tool returned invalid output:
${errorMessages}

Returned output: ${truncateForLogging(output)}`,
    validationErrors: buildFormattedErrors(validation.issues)
  };
  return { error };
}
var SENSITIVE_KEYS = ["password", "secret", "token", "apiKey", "api_key", "auth", "credential"];
function redactSensitiveKeys(obj) {
  if (obj === null || typeof obj !== "object") {
    return obj;
  }
  if (Array.isArray(obj)) {
    return obj.map(redactSensitiveKeys);
  }
  const result = {};
  for (const [key, value] of Object.entries(obj)) {
    if (SENSITIVE_KEYS.some((sensitive) => key.toLowerCase().includes(sensitive.toLowerCase()))) {
      result[key] = "[REDACTED]";
    } else if (typeof value === "object" && value !== null) {
      result[key] = redactSensitiveKeys(value);
    } else {
      result[key] = value;
    }
  }
  return result;
}
function validateRequestContext(schema, requestContext, identifier) {
  if (!schema) {
    return { data: requestContext?.all ?? {} };
  }
  const contextValues = requestContext?.all ?? {};
  const standardSchema = toStandardSchema(schema);
  const validation = standardSchema["~standard"].validate(contextValues);
  if (validation instanceof Promise) {
    throw new Error("Your schema is async, which is not supported. Please use a sync schema.");
  }
  if ("value" in validation) {
    return { data: validation.value };
  }
  const errorMessages = validation.issues.map((e) => `- ${e.path?.join(".") || "root"}: ${e.message}`).join("\n");
  const redactedContext = redactSensitiveKeys(contextValues);
  const error = {
    error: true,
    message: `Request context validation failed${identifier ? ` for ${identifier}` : ""}. Please fix the following errors and try again:
${errorMessages}

Provided request context: ${truncateForLogging(redactedContext)}`,
    validationErrors: buildFormattedErrors(validation.issues)
  };
  return { data: contextValues, error };
}

// src/tools/tool.ts
var MASTRA_TOOL_MARKER = /* @__PURE__ */ Symbol.for("mastra.core.tool.Tool");
var Tool = class {
  /** Unique identifier for the tool */
  id;
  /** Description of what the tool does */
  description;
  /** Schema for validating input parameters */
  inputSchema;
  /** Schema for validating output structure */
  outputSchema;
  /** Schema for suspend operation data */
  suspendSchema;
  /** Schema for resume operation data */
  resumeSchema;
  /**
   * Schema for validating request context values.
   * When provided, the request context will be validated against this schema before tool execution.
   */
  requestContextSchema;
  /**
   * Tool execution function
   * @param inputData - The raw, validated input data
   * @param context - Optional execution context with metadata
   * @returns Promise resolving to tool output or a ValidationError if input validation fails
   */
  execute;
  /** Parent Mastra instance for accessing shared resources */
  mastra;
  /**
   * Whether the tool requires explicit user approval before execution.
   * Accepts a boolean for static behavior, or a function evaluated per-call
   * for conditional approval.
   * @example
   * ```typescript
   * // Static
   * requireApproval: true
   *
   * // Conditional — only require approval for non-dry-run calls
   * requireApproval: async ({ isDryRun }) => !isDryRun
   * ```
   */
  requireApproval;
  /**
   * Enables strict tool input generation for providers that support it.
   */
  strict;
  /**
   * Provider-specific options passed to the model when this tool is used.
   * Keys are provider names (e.g., 'anthropic', 'openai'), values are provider-specific configs.
   * @example
   * ```typescript
   * providerOptions: {
   *   anthropic: {
   *     cacheControl: { type: 'ephemeral' }
   *   }
   * }
   * ```
   */
  providerOptions;
  /**
   * Optional function to transform the tool's raw output before sending it to the model.
   * The raw result is still available for application logic; only the model sees the transformed version.
   */
  toModelOutput;
  /**
   * Optional MCP-specific properties including annotations and metadata.
   * Only relevant when the tool is being used in an MCP context.
   * @example
   * ```typescript
   * mcp: {
   *   annotations: {
   *     title: 'Weather Lookup',
   *     readOnlyHint: true,
   *     destructiveHint: false
   *   },
   *   _meta: {
   *     version: '1.0.0',
   *     author: 'team@example.com'
   *   }
   * }
   * ```
   */
  mcp;
  onInputStart;
  onInputDelta;
  onInputAvailable;
  onOutput;
  /**
   * Examples of valid tool inputs passed through to the AI SDK.
   */
  inputExamples;
  /**
   * Metadata identifying this tool as originating from an MCP server.
   * Set automatically by the MCP client when creating tools.
   */
  mcpMetadata;
  /**
   * Creates a new Tool instance with input validation wrapper.
   *
   * @param opts - Tool configuration and execute function
   * @example
   * ```typescript
   * const tool = new Tool({
   *   id: 'my-tool',
   *   description: 'Does something useful',
   *   inputSchema: z.object({ name: z.string() }),
   *   execute: async (inputData) => ({ greeting: `Hello ${inputData.name}` })
   * });
   * ```
   */
  constructor(opts) {
    this[MASTRA_TOOL_MARKER] = true;
    this.id = opts.id;
    this.description = opts.description;
    this.inputSchema = opts.inputSchema ? toStandardSchema(opts.inputSchema) : void 0;
    this.outputSchema = opts.outputSchema ? toStandardSchema(opts.outputSchema) : void 0;
    this.suspendSchema = opts.suspendSchema ? toStandardSchema(opts.suspendSchema) : void 0;
    this.resumeSchema = opts.resumeSchema ? toStandardSchema(opts.resumeSchema) : void 0;
    this.requestContextSchema = opts.requestContextSchema;
    this.mastra = opts.mastra;
    this.requireApproval = opts.requireApproval || false;
    this.strict = opts.strict;
    this.providerOptions = opts.providerOptions;
    this.toModelOutput = opts.toModelOutput;
    this.inputExamples = opts.inputExamples;
    this.mcp = opts.mcp;
    this.mcpMetadata = opts.mcpMetadata;
    this.onInputStart = opts.onInputStart;
    this.onInputDelta = opts.onInputDelta;
    this.onInputAvailable = opts.onInputAvailable;
    this.onOutput = opts.onOutput;
    if (opts.execute) {
      const originalExecute = opts.execute;
      this.execute = async (inputData, context) => {
        const { data, error } = validateToolInput(this.inputSchema, inputData, this.id);
        if (error) {
          return error;
        }
        const { error: requestContextError } = validateRequestContext(
          this.requestContextSchema,
          context?.requestContext,
          this.id
        );
        if (requestContextError) {
          return requestContextError;
        }
        let suspendData = null;
        const baseContext = context ? {
          ...context,
          ...context.suspend ? {
            suspend: (args, suspendOptions) => {
              suspendData = args;
              return context.suspend?.(args, suspendOptions);
            }
          } : {}
        } : {};
        let organizedContext = baseContext;
        if (!context) {
          organizedContext = {
            requestContext: new RequestContext(),
            mastra: void 0
          };
        } else {
          const isAgentExecution = baseContext.toolCallId && baseContext.messages;
          const isWorkflowExecution = !isAgentExecution && (baseContext.workflow || baseContext.workflowId);
          if (isAgentExecution && !baseContext.agent) {
            const {
              agentId,
              toolCallId,
              messages,
              suspend,
              resumeData: resumeData2,
              threadId,
              resourceId,
              writableStream,
              ...rest
            } = baseContext;
            organizedContext = {
              ...rest,
              agent: {
                agentId: agentId || "",
                toolCallId,
                messages,
                suspend,
                resumeData: resumeData2,
                threadId,
                resourceId,
                writableStream
              },
              // Ensure requestContext is always present
              requestContext: rest.requestContext || new RequestContext()
            };
          } else if (isWorkflowExecution && !baseContext.workflow) {
            const { workflowId, runId, state, setState, suspend, resumeData: resumeData2, ...rest } = baseContext;
            organizedContext = {
              ...rest,
              workflow: {
                workflowId,
                runId,
                state,
                setState,
                suspend,
                resumeData: resumeData2
              },
              // Ensure requestContext is always present
              requestContext: rest.requestContext || new RequestContext()
            };
          } else {
            organizedContext = {
              ...baseContext,
              agent: baseContext.agent ? {
                ...baseContext.agent,
                agentId: baseContext.agent.agentId ?? "",
                suspend: (args, suspendOptions) => {
                  suspendData = args;
                  return baseContext.agent?.suspend?.(args, suspendOptions);
                }
              } : baseContext.agent,
              workflow: baseContext.workflow ? {
                ...baseContext.workflow,
                suspend: (args, suspendOptions) => {
                  suspendData = args;
                  return baseContext.workflow?.suspend?.(args, suspendOptions);
                }
              } : baseContext.workflow,
              requestContext: baseContext.requestContext || new RequestContext()
            };
          }
        }
        const resumeData = organizedContext.agent?.resumeData ?? organizedContext.workflow?.resumeData ?? organizedContext?.resumeData;
        if (resumeData) {
          const resumeValidation = validateToolInput(this.resumeSchema, resumeData, this.id);
          if (resumeValidation.error) {
            return resumeValidation.error;
          }
        }
        const output = await originalExecute(data, organizedContext);
        if (suspendData) {
          const suspendValidation = validateToolSuspendData(this.suspendSchema, suspendData, this.id);
          if (suspendValidation.error) {
            return suspendValidation.error;
          }
        }
        const skiptOutputValidation = !!(typeof output === "undefined" && suspendData);
        const outputValidation = validateToolOutput(this.outputSchema, output, this.id, skiptOutputValidation);
        if (outputValidation.error) {
          return outputValidation.error;
        }
        return outputValidation.data;
      };
    }
  }
};
function createTool(opts) {
  return new Tool(opts);
}

// src/tools/toolchecks.ts
function isMastraTool(tool) {
  return tool instanceof Tool || typeof tool === "object" && tool !== null && MASTRA_TOOL_MARKER in tool;
}
function isVercelTool(tool) {
  return !!(tool && !isMastraTool(tool) && ("parameters" in tool || "execute" in tool && typeof tool.execute === "function" && "inputSchema" in tool));
}
function isProviderDefinedTool(tool) {
  if (typeof tool !== "object" || tool === null) return false;
  const t = tool;
  const isProviderType = t.type === "provider-defined" || t.type === "provider";
  return isProviderType && typeof t.id === "string";
}
var isProviderTool = isProviderDefinedTool;
function getProviderToolName(providerId) {
  return providerId.split(".").slice(1).join(".");
}

export { MASTRA_TOOL_MARKER, Tool, createTool, getProviderToolName, isMastraTool, isProviderDefinedTool, isProviderTool, isValidationError, isVercelTool, validateToolInput, validateToolOutput, validateToolSuspendData };
//# sourceMappingURL=chunk-4IZGVZYF.js.map
//# sourceMappingURL=chunk-4IZGVZYF.js.map