import { agentCardResponseSchema, a2aAgentIdPathParams, agentExecutionResponseSchema, agentExecutionBodySchema } from './chunk-KEE6UMGC.js';
import { getAgentFromSystem } from './chunk-5NBDNR2B.js';
import { getPublicOrigin } from './chunk-CCT2USYM.js';
import { convertInstructionsToString } from './chunk-QIQWHDPH.js';
import { createRoute } from './chunk-PIKPS6Q6.js';
import { __commonJS, __export, __toESM } from './chunk-PR4QN5HX.js';
import { isDeepStrictEqual } from 'util';
import { MastraA2AError } from '@mastra/core/a2a';
import { z } from 'zod/v4';
import * as crypto2 from 'crypto';
import { lookup } from 'dns/promises';
import { request as request$1 } from 'http';
import { request } from 'https';
import { isIP } from 'net';

// ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/canonicalize/1.0.8/8d710dcf19a48d178b2fc853e16c59951fde29eb27b6037da6c3f4dbb968b03d/node_modules/canonicalize/lib/canonicalize.js
var require_canonicalize = __commonJS({
  "../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/canonicalize/1.0.8/8d710dcf19a48d178b2fc853e16c59951fde29eb27b6037da6c3f4dbb968b03d/node_modules/canonicalize/lib/canonicalize.js"(exports, module) {
    module.exports = function serialize(object) {
      if (object === null || typeof object !== "object" || object.toJSON != null) {
        return JSON.stringify(object);
      }
      if (Array.isArray(object)) {
        return "[" + object.reduce((t, cv, ci) => {
          const comma = ci === 0 ? "" : ",";
          const value = cv === void 0 || typeof cv === "symbol" ? null : cv;
          return t + comma + serialize(value);
        }, "") + "]";
      }
      return "{" + Object.keys(object).sort().reduce((t, cv, ci) => {
        if (object[cv] === void 0 || typeof object[cv] === "symbol") {
          return t;
        }
        const comma = t.length === 0 ? "" : ",";
        return t + comma + serialize(cv) + ":" + serialize(object[cv]);
      }, "") + "}";
    };
  }
});

// src/server/handlers/a2a.ts
var a2a_exports = {};
__export(a2a_exports, {
  AGENT_EXECUTION_ROUTE: () => AGENT_EXECUTION_ROUTE,
  GET_AGENT_CARD_ROUTE: () => GET_AGENT_CARD_ROUTE,
  getAgentCardByIdHandler: () => getAgentCardByIdHandler,
  getAgentExecutionHandler: () => getAgentExecutionHandler,
  handleDeleteTaskPushNotificationConfig: () => handleDeleteTaskPushNotificationConfig,
  handleGetTaskPushNotificationConfig: () => handleGetTaskPushNotificationConfig,
  handleListTaskPushNotificationConfig: () => handleListTaskPushNotificationConfig,
  handleMessageSend: () => handleMessageSend,
  handleMessageStream: () => handleMessageStream,
  handleSetTaskPushNotificationConfig: () => handleSetTaskPushNotificationConfig,
  handleTaskCancel: () => handleTaskCancel,
  handleTaskGet: () => handleTaskGet,
  handleTaskResubscribe: () => handleTaskResubscribe
});

// src/server/a2a/agent-card-signing.ts
var import_canonicalize = __toESM(require_canonicalize(), 1);
var SUPPORTED_JWS_ALGORITHMS = /* @__PURE__ */ new Set([
  "ES256",
  "ES384",
  "ES512",
  "RS256",
  "RS384",
  "RS512",
  "PS256",
  "PS384",
  "PS512"
]);
function stripAgentCardSignatures(agentCard) {
  const unsignedCard = structuredClone(agentCard);
  delete unsignedCard.signatures;
  return unsignedCard;
}
function importSigningKey(signing) {
  const { privateKey } = signing;
  if (typeof privateKey === "string") {
    return crypto2.createPrivateKey(privateKey);
  }
  return crypto2.createPrivateKey({
    key: privateKey,
    format: "jwk"
  });
}
function getProtectedHeader(signing) {
  const { alg, ...rest } = signing.protectedHeader;
  if (!SUPPORTED_JWS_ALGORITHMS.has(alg)) {
    throw new Error(`Unsupported JWS algorithm for A2A Agent Card signing: ${alg}`);
  }
  return {
    ...rest,
    alg
  };
}
function getSignatureOptions(algorithm) {
  if (algorithm.startsWith("ES")) {
    return { dsaEncoding: "ieee-p1363" };
  }
  if (algorithm.startsWith("PS")) {
    return {
      padding: crypto2.constants.RSA_PKCS1_PSS_PADDING,
      saltLength: crypto2.constants.RSA_PSS_SALTLEN_DIGEST
    };
  }
  return {};
}
function getDigestAlgorithm(algorithm) {
  if (algorithm.endsWith("256")) return "sha256";
  if (algorithm.endsWith("384")) return "sha384";
  if (algorithm.endsWith("512")) return "sha512";
  throw new Error(`Unsupported JWS algorithm for A2A Agent Card signing: ${algorithm}`);
}
async function signAgentCard({
  agentCard,
  signing
}) {
  const canonicalPayload = (0, import_canonicalize.default)(stripAgentCardSignatures(agentCard));
  if (!canonicalPayload) {
    throw new Error("Failed to canonicalize A2A Agent Card for signing");
  }
  const key = importSigningKey(signing);
  const protectedHeader = getProtectedHeader(signing);
  const encodedHeader = Buffer.from(JSON.stringify(protectedHeader), "utf8").toString("base64url");
  const encodedPayload = Buffer.from(canonicalPayload, "utf8").toString("base64url");
  const signingInput = `${encodedHeader}.${encodedPayload}`;
  const signatureBuffer = crypto2.sign(
    getDigestAlgorithm(String(protectedHeader.alg)),
    Buffer.from(signingInput, "utf8"),
    {
      key,
      ...getSignatureOptions(String(protectedHeader.alg))
    }
  );
  const signatureValue = signatureBuffer.toString("base64url");
  if (!encodedHeader || !signatureValue) {
    throw new Error("Failed to create compact JWS for A2A Agent Card");
  }
  const signature = {
    protected: encodedHeader,
    signature: signatureValue,
    header: signing.header
  };
  return {
    ...agentCard,
    signatures: [...agentCard.signatures ?? [], signature]
  };
}
function normalizeError(error, reqId, taskId, logger) {
  let a2aError;
  if (error instanceof MastraA2AError) {
    a2aError = error;
  } else if (error instanceof Error) {
    a2aError = MastraA2AError.internalError(error.message, { stack: error.stack });
  } else {
    a2aError = MastraA2AError.internalError("An unknown error occurred.", error);
  }
  if (taskId && !a2aError.taskId) {
    a2aError.taskId = taskId;
  }
  logger?.error(`Error processing request (Task: ${a2aError.taskId ?? "N/A"}, ReqID: ${reqId ?? "N/A"}):`, a2aError);
  return createErrorResponse(reqId, a2aError.toJSONRPCError());
}
function createErrorResponse(id, error) {
  return {
    jsonrpc: "2.0",
    id,
    // Can be null if request ID was invalid/missing
    error
  };
}
function createSuccessResponse(id, result) {
  if (!id) {
    throw MastraA2AError.internalError("Cannot create success response for null ID.");
  }
  return {
    jsonrpc: "2.0",
    id,
    result
  };
}
function convertToCoreMessage(message) {
  return {
    role: message.role === "user" ? "user" : "assistant",
    content: message.parts.map((msg) => convertToCoreMessagePart(msg))
  };
}
function convertToCoreMessagePart(part) {
  switch (part.kind) {
    case "text":
      return {
        type: "text",
        text: part.text
      };
    case "file":
      return {
        type: "file",
        data: "uri" in part.file ? new URL(part.file.uri) : part.file.bytes,
        mimeType: part.file.mimeType
      };
    case "data":
      throw new Error("Data parts are not supported in core messages");
  }
}
var DEFAULT_PUSH_NOTIFICATION_TOKEN_HEADER = "X-A2A-Notification-Token";
function isDisallowedHostname(hostname) {
  const normalized = hostname.toLowerCase();
  return normalized === "localhost" || normalized.endsWith(".localhost") || normalized.endsWith(".local") || normalized.endsWith(".internal") || !normalized.includes(".");
}
function isDisallowedIpv4(address) {
  const [first = -1, second = -1] = address.split(".").map(Number);
  return first === 10 || first === 127 || first === 169 && second === 254 || first === 172 && second >= 16 && second <= 31 || first === 192 && second === 168;
}
function isDisallowedIpv6(address) {
  const normalized = address.toLowerCase();
  return normalized === "::1" || normalized.startsWith("fe8") || normalized.startsWith("fe9") || normalized.startsWith("fea") || normalized.startsWith("feb") || normalized.startsWith("fc") || normalized.startsWith("fd");
}
function isDisallowedIpAddress(address) {
  const version = isIP(address);
  if (version === 4) {
    return isDisallowedIpv4(address);
  }
  if (version === 6) {
    return isDisallowedIpv6(address);
  }
  return false;
}
var DefaultPushNotificationSender = class {
  constructor(pushNotificationStore, options = {}) {
    this.pushNotificationStore = pushNotificationStore;
    this.options = options;
  }
  pushNotificationStore;
  options;
  getStore() {
    return this.pushNotificationStore;
  }
  async resolveValidatedDestination(rawUrl) {
    const url = new URL(rawUrl);
    if (url.protocol !== "https:" && url.protocol !== "http:") {
      throw new Error(`Push notification URL must use http or https: ${url.protocol}`);
    }
    const hostname = url.hostname.toLowerCase();
    if (this.options.allowedHosts && !this.options.allowedHosts.includes(hostname)) {
      throw new Error(`Push notification host is not allowed: ${hostname}`);
    }
    if (isDisallowedHostname(hostname)) {
      throw new Error(`Push notification URL must not target local or internal hosts: ${hostname}`);
    }
    if (isDisallowedIpAddress(hostname)) {
      throw new Error(`Push notification URL must not target local or private IPs: ${hostname}`);
    }
    const resolvedAddresses = isIP(hostname) === 0 ? await (this.options.lookup ?? lookup)(hostname, { all: true, verbatim: true }) : [{ address: hostname, family: isIP(hostname) }];
    if (resolvedAddresses.some((result) => isDisallowedIpAddress(result.address))) {
      throw new Error(`Push notification URL resolved to a local or private IP: ${hostname}`);
    }
    const requestUrl = new URL(url.toString());
    requestUrl.hostname = resolvedAddresses[0].address;
    return {
      originalUrl: url,
      requestUrl,
      hostHeader: url.host,
      servername: isIP(hostname) === 0 ? hostname : void 0
    };
  }
  async postTaskSnapshot({
    requestUrl,
    hostHeader,
    servername,
    headers,
    body,
    timeout
  }) {
    headers.set("host", hostHeader);
    const signal = typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(timeout) : void 0;
    if (this.options.fetch) {
      return this.options.fetch(requestUrl.toString(), {
        method: "POST",
        headers,
        body,
        signal
      });
    }
    const transport = requestUrl.protocol === "https:" ? request : request$1;
    return await new Promise((resolve, reject) => {
      const request = transport(
        {
          protocol: requestUrl.protocol,
          hostname: requestUrl.hostname,
          port: requestUrl.port || void 0,
          path: `${requestUrl.pathname}${requestUrl.search}`,
          method: "POST",
          headers: Object.fromEntries(headers.entries()),
          servername
        },
        (response) => {
          response.resume();
          response.on("end", () => {
            resolve({
              ok: !!response.statusCode && response.statusCode >= 200 && response.statusCode < 300,
              status: response.statusCode ?? 0,
              statusText: response.statusMessage ?? ""
            });
          });
        }
      );
      request.on("error", reject);
      if (signal) {
        signal.addEventListener(
          "abort",
          () => {
            request.destroy(signal.reason instanceof Error ? signal.reason : new Error("Push notification timed out"));
          },
          { once: true }
        );
      }
      request.end(body);
    });
  }
  async sendNotifications({
    agentId,
    task,
    logger
  }) {
    const configs = this.pushNotificationStore.list({
      agentId,
      params: { id: task.id }
    });
    if (configs.length === 0) {
      return;
    }
    await Promise.allSettled(
      configs.map(async (config) => {
        const headers = new Headers({
          "content-type": "application/json"
        });
        if (config.pushNotificationConfig.token) {
          headers.set(
            this.options.tokenHeaderName ?? DEFAULT_PUSH_NOTIFICATION_TOKEN_HEADER,
            config.pushNotificationConfig.token
          );
        }
        const auth = config.pushNotificationConfig.authentication;
        if (auth?.credentials) {
          if (auth.schemes.includes("Bearer")) {
            headers.set("authorization", `Bearer ${auth.credentials}`);
          } else if (auth.schemes.includes("Basic")) {
            headers.set("authorization", `Basic ${auth.credentials}`);
          }
        }
        const { requestUrl, hostHeader, servername } = await this.resolveValidatedDestination(
          config.pushNotificationConfig.url
        );
        const response = await this.postTaskSnapshot({
          requestUrl,
          hostHeader,
          servername,
          headers,
          body: JSON.stringify(task),
          timeout: this.options.timeout ?? 5e3
        });
        if (!response.ok) {
          throw new Error(
            `Push notification failed with status ${response.status} ${response.statusText ?? ""}`.trim()
          );
        }
      })
    ).then((results) => {
      for (const result of results) {
        if (result.status === "rejected") {
          logger?.error("Failed to deliver A2A push notification", result.reason);
        }
      }
    });
  }
};

// src/server/a2a/push-notification-store.ts
function normalizeConfigId(taskId, configId) {
  return configId || taskId;
}
var InMemoryPushNotificationStore = class {
  store = /* @__PURE__ */ new Map();
  getKey(agentId, taskId) {
    return JSON.stringify([agentId, taskId]);
  }
  set({ agentId, config }) {
    const key = this.getKey(agentId, config.taskId);
    const configs = this.store.get(key) ?? /* @__PURE__ */ new Map();
    const normalizedConfig = {
      taskId: config.taskId,
      pushNotificationConfig: {
        ...config.pushNotificationConfig,
        id: normalizeConfigId(config.taskId, config.pushNotificationConfig.id)
      }
    };
    configs.set(normalizedConfig.pushNotificationConfig.id, structuredClone(normalizedConfig));
    this.store.set(key, configs);
    return structuredClone(normalizedConfig);
  }
  get({
    agentId,
    params
  }) {
    const key = this.getKey(agentId, params.id);
    const configId = normalizeConfigId(params.id, params.pushNotificationConfigId);
    const config = this.store.get(key)?.get(configId);
    return config ? structuredClone(config) : null;
  }
  list({
    agentId,
    params
  }) {
    const key = this.getKey(agentId, params.id);
    return Array.from(this.store.get(key)?.values() ?? []).map((config) => structuredClone(config));
  }
  delete({ agentId, params }) {
    const key = this.getKey(agentId, params.id);
    const configs = this.store.get(key);
    if (!configs) {
      return false;
    }
    const deleted = configs.delete(params.pushNotificationConfigId);
    if (configs.size === 0) {
      this.store.delete(key);
    }
    return deleted;
  }
};

// src/server/a2a/tasks.ts
function isTaskStatusUpdate(update) {
  return "state" in update && !("parts" in update);
}
function isArtifactUpdate(update) {
  return "kind" in update && update.kind === "artifact-update";
}
function applyUpdateToTask(current, update) {
  let newTask = structuredClone(current);
  if (isTaskStatusUpdate(update)) {
    newTask.status = {
      ...newTask.status,
      // Keep existing properties if not overwritten
      ...update,
      // Apply updates
      timestamp: (/* @__PURE__ */ new Date()).toISOString()
    };
  } else if (isArtifactUpdate(update)) {
    if (!newTask.artifacts) {
      newTask.artifacts = [];
    } else {
      newTask.artifacts = [...newTask.artifacts];
    }
    const artifact = update.artifact;
    const existingIndex = newTask.artifacts.findIndex((a) => a.name === artifact.name);
    const existingArtifact = newTask.artifacts[existingIndex];
    if (existingArtifact) {
      if (update.append) {
        const appendedArtifact = JSON.parse(JSON.stringify(existingArtifact));
        appendedArtifact.parts.push(...artifact.parts);
        if (artifact.metadata) {
          appendedArtifact.metadata = {
            ...appendedArtifact.metadata || {},
            ...artifact.metadata
          };
        }
        if (artifact.description) appendedArtifact.description = artifact.description;
        newTask.artifacts[existingIndex] = appendedArtifact;
      } else {
        newTask.artifacts[existingIndex] = { ...artifact };
      }
    } else {
      newTask.artifacts.push({ ...artifact });
    }
  }
  return newTask;
}
async function loadOrCreateTask({
  agentId,
  taskId,
  taskStore,
  message,
  contextId,
  metadata,
  logger
}) {
  const data = await taskStore.load({ agentId, taskId });
  if (!data) {
    const initialTask = {
      id: taskId,
      contextId: contextId || crypto.randomUUID(),
      status: {
        state: "submitted",
        timestamp: (/* @__PURE__ */ new Date()).toISOString(),
        message: void 0
      },
      artifacts: [],
      history: [message],
      metadata,
      kind: "task"
    };
    logger?.info(`[Task ${taskId}] Created new task.`);
    await taskStore.save({ agentId, data: initialTask });
    return initialTask;
  }
  logger?.info(`[Task ${taskId}] Loaded existing task.`);
  let updatedData = data;
  updatedData.history = [...data.history || [], message];
  const { status } = data;
  const finalStates = ["completed", "failed", "canceled"];
  if (finalStates.includes(status.state)) {
    logger?.warn(`[Task ${taskId}] Received message for task in final state ${status.state}. Restarting.`);
    updatedData = applyUpdateToTask(updatedData, {
      state: "submitted",
      message: void 0
    });
  } else if (status.state === "input-required") {
    logger?.info(`[Task ${taskId}] Changing state from 'input-required' to 'working'.`);
    updatedData = applyUpdateToTask(updatedData, { state: "working" });
  } else if (status.state === "working") {
    logger?.warn(`[Task ${taskId}] Received message while already 'working'. Proceeding.`);
  }
  await taskStore.save({ agentId, data: updatedData });
  return updatedData;
}
function createTaskContext({
  task,
  userMessage,
  history,
  activeCancellations
}) {
  return {
    task: structuredClone(task),
    userMessage,
    history: structuredClone(history),
    isCancelled: () => activeCancellations.has(task.id)
  };
}

// src/server/handlers/a2a.ts
var messagePartSchema = z.discriminatedUnion("kind", [
  z.object({
    kind: z.literal("text"),
    text: z.string(),
    metadata: z.record(z.string(), z.any()).optional()
  }),
  z.object({
    kind: z.literal("file"),
    file: z.union([
      z.object({
        bytes: z.string(),
        mimeType: z.string().optional(),
        name: z.string().optional()
      }),
      z.object({
        uri: z.string(),
        mimeType: z.string().optional(),
        name: z.string().optional()
      })
    ]),
    metadata: z.record(z.string(), z.any()).optional()
  }),
  z.object({
    kind: z.literal("data"),
    data: z.record(z.string(), z.any()),
    metadata: z.record(z.string(), z.any()).optional()
  })
]);
var messageSendParamsSchema = z.object({
  message: z.object({
    role: z.enum(["user", "agent"]),
    parts: z.array(messagePartSchema),
    kind: z.literal("message"),
    messageId: z.string(),
    contextId: z.string().optional(),
    taskId: z.string().optional(),
    referenceTaskIds: z.array(z.string()).optional(),
    extensions: z.array(z.string()).optional(),
    metadata: z.record(z.string(), z.any()).optional()
  }),
  configuration: z.object({
    acceptedOutputModes: z.array(z.string()).optional(),
    blocking: z.boolean().optional(),
    historyLength: z.number().optional(),
    pushNotificationConfig: z.object({
      url: z.string(),
      id: z.string().optional(),
      token: z.string().optional(),
      authentication: z.object({
        schemes: z.array(z.string()),
        credentials: z.string().optional()
      }).optional()
    }).optional()
  }).optional()
});
var defaultPushNotificationStore = new InMemoryPushNotificationStore();
var defaultPushNotificationSender = new DefaultPushNotificationSender(defaultPushNotificationStore);
function createAgentCardDefaults({
  pushNotifications = false
} = {}) {
  return {
    protocolVersion: "0.3.0",
    additionalInterfaces: [],
    supportsAuthenticatedExtendedCard: false,
    security: [],
    securitySchemes: {},
    capabilities: {
      streaming: true,
      pushNotifications,
      stateTransitionHistory: false,
      extensions: []
    },
    defaultInputModes: ["text/plain"],
    defaultOutputModes: ["text/plain"]
  };
}
async function getAgentCardByIdHandler({
  mastra,
  agentId,
  executionUrl = `/a2a/${agentId}`,
  provider = {
    organization: "Mastra",
    url: "https://mastra.ai"
  },
  version = "1.0",
  pushNotifications = false,
  requestContext
}) {
  const agent = await getAgentFromSystem({ mastra, agentId });
  const [instructions, tools] = await Promise.all([agent.getInstructions({ requestContext }), agent.listTools({ requestContext })]);
  const agentCard = {
    name: agent.id || agentId,
    description: convertInstructionsToString(instructions),
    url: executionUrl,
    provider,
    version,
    ...createAgentCardDefaults({ pushNotifications }),
    // Convert agent tools to skills format for A2A protocol
    skills: Object.entries(tools).map(([toolId, tool]) => ({
      id: toolId,
      name: toolId,
      description: tool.description || `Tool: ${toolId}`,
      // Optional fields
      tags: ["tool"]
    }))
  };
  const signing = mastra.getServer?.()?.a2a?.agentCardSigning;
  if (!signing) {
    return agentCard;
  }
  return signAgentCard({
    agentCard,
    signing
  });
}
function getA2AExecutionUrl({
  agentId,
  request,
  routePrefix
}) {
  const executionPath = `${routePrefix ?? ""}/a2a/${agentId}`;
  if (!request) {
    return executionPath;
  }
  return `${getPublicOrigin(request)}${executionPath}`;
}
function validateMessageSendParams(params) {
  try {
    messageSendParamsSchema.parse(params);
  } catch (error) {
    if (error instanceof z.ZodError) {
      throw MastraA2AError.invalidParams(error.issues[0].message);
    }
    throw error;
  }
}
function createArtifactUpdate({
  taskId,
  contextId,
  text,
  data
}) {
  const parts = [
    ...text ? [{ kind: "text", text }] : [],
    ...data ? [{ kind: "data", data }] : []
  ];
  if (parts.length === 0) {
    return void 0;
  }
  return {
    kind: "artifact-update",
    taskId,
    contextId,
    lastChunk: true,
    artifact: {
      artifactId: `${taskId}:response`,
      name: data ? "response.json" : "response.txt",
      parts
    }
  };
}
function createTextChunkArtifactUpdate({
  taskId,
  contextId,
  text,
  append,
  lastChunk
}) {
  return {
    kind: "artifact-update",
    taskId,
    contextId,
    ...append ? { append: true } : {},
    ...lastChunk !== void 0 ? { lastChunk } : {},
    artifact: {
      artifactId: `${taskId}:response:text`,
      name: "response.txt",
      parts: [{ kind: "text", text }]
    }
  };
}
function createDataArtifactUpdate({
  taskId,
  contextId,
  data,
  lastChunk
}) {
  return {
    kind: "artifact-update",
    taskId,
    contextId,
    ...{ lastChunk } ,
    artifact: {
      artifactId: `${taskId}:response:data`,
      name: "response.json",
      parts: [{ kind: "data", data }]
    }
  };
}
function resolvePushNotificationPair({
  pushNotificationStore,
  pushNotificationSender
}) {
  if (pushNotificationSender) {
    return {
      pushNotificationStore: pushNotificationSender.getStore(),
      pushNotificationSender
    };
  }
  if (pushNotificationStore) {
    return {
      pushNotificationStore,
      pushNotificationSender: new DefaultPushNotificationSender(pushNotificationStore)
    };
  }
  return {
    pushNotificationStore: defaultPushNotificationStore,
    pushNotificationSender: defaultPushNotificationSender
  };
}
function createTaskPushNotificationConfig(taskId, pushNotificationConfig) {
  return {
    taskId,
    pushNotificationConfig: {
      ...pushNotificationConfig,
      id: pushNotificationConfig.id ?? taskId
    }
  };
}
function shouldSendPushNotification(previousTask, nextTask) {
  const pushTriggerStates = ["completed", "failed", "canceled", "input-required"];
  if (!pushTriggerStates.includes(nextTask.status.state)) {
    return false;
  }
  return previousTask?.status.state !== nextTask.status.state;
}
async function saveTaskAndMaybeSendPushNotification({
  taskStore,
  pushNotificationSender,
  previousTask,
  nextTask,
  agentId,
  logger
}) {
  await taskStore.save({ agentId, data: nextTask });
  if (!shouldSendPushNotification(previousTask, nextTask)) {
    return;
  }
  void pushNotificationSender.sendNotifications({
    agentId,
    task: nextTask,
    logger
  }).catch((error) => {
    logger?.error("Failed to schedule A2A push notification", error);
  });
}
function extractFullStreamTextDelta(value) {
  if (typeof value !== "object" || value === null || !("type" in value)) {
    return null;
  }
  const chunk = value;
  switch (chunk.type) {
    case "text-delta":
      if (typeof chunk.payload?.text === "string") {
        return chunk.payload.text;
      }
      if (typeof chunk.payload?.delta === "string") {
        return chunk.payload.delta;
      }
      if (typeof chunk.textDelta === "string") {
        return chunk.textDelta;
      }
      if (typeof chunk.delta === "string") {
        return chunk.delta;
      }
      if (typeof chunk.text === "string") {
        return chunk.text;
      }
      return null;
    default:
      return null;
  }
}
function extractFinalStructuredObject(value) {
  if (typeof value !== "object" || value === null || !("type" in value)) {
    return void 0;
  }
  const chunk = value;
  if (chunk.type !== "object-result") {
    return void 0;
  }
  const objectValue = chunk.payload?.object ?? chunk.object;
  return objectValue && typeof objectValue === "object" ? objectValue : void 0;
}
function isTerminalTaskState(state) {
  return ["completed", "failed", "canceled"].includes(state);
}
function artifactIdentity(artifact) {
  return artifact.artifactId || artifact.name;
}
function areArtifactPartsEqual(left, right) {
  if (left === right) {
    return true;
  }
  if (left.length !== right.length) {
    return false;
  }
  return left.every((part, index) => {
    const other = right[index];
    if (!other || part.kind !== other.kind) {
      return false;
    }
    if (part.kind === "text" && other.kind === "text") {
      return part.text === other.text;
    }
    return part === other;
  });
}
function areArtifactsEqual(left, right) {
  if (left === right) {
    return true;
  }
  if (!left || !right) {
    return left === right;
  }
  return left.artifactId === right.artifactId && left.name === right.name && left.description === right.description && left.metadata === right.metadata && areArtifactPartsEqual(left.parts, right.parts);
}
function areStatusMessagePartsEqual(left, right) {
  return left === right || isDeepStrictEqual(left, right);
}
function areStatusMessagesEqual(left, right) {
  if (left === right) {
    return true;
  }
  if (!left || !right) {
    return left === right;
  }
  return left.messageId === right.messageId && left.kind === right.kind && left.role === right.role && left.contextId === right.contextId && left.taskId === right.taskId && isDeepStrictEqual(left.referenceTaskIds, right.referenceTaskIds) && isDeepStrictEqual(left.extensions, right.extensions) && isDeepStrictEqual(left.metadata, right.metadata) && areStatusMessagePartsEqual(left.parts, right.parts);
}
function didTaskStatusChange(previous, next) {
  return previous.status.state !== next.status.state || previous.status.timestamp !== next.status.timestamp || !areStatusMessagesEqual(previous.status.message, next.status.message);
}
function getTaskArtifactUpdates({ previous, next }) {
  const previousArtifacts = new Map((previous.artifacts ?? []).map((artifact) => [artifactIdentity(artifact), artifact]));
  const changedArtifacts = (next.artifacts ?? []).filter((artifact) => {
    const priorArtifact = previousArtifacts.get(artifactIdentity(artifact));
    return !priorArtifact || !areArtifactsEqual(priorArtifact, artifact);
  });
  return changedArtifacts.map((artifact, index) => ({
    kind: "artifact-update",
    taskId: next.id,
    contextId: next.contextId,
    lastChunk: isTerminalTaskState(next.status.state) && index === changedArtifacts.length - 1,
    artifact: structuredClone(artifact)
  }));
}
async function handleMessageSend({
  requestId,
  params,
  taskStore,
  pushNotificationStore,
  pushNotificationSender,
  agent,
  agentId,
  logger,
  requestContext
}) {
  validateMessageSendParams(params);
  const { message, metadata } = params;
  const { contextId } = message;
  const taskId = message.taskId || crypto.randomUUID();
  const {
    pushNotificationStore: resolvedPushNotificationStore,
    pushNotificationSender: resolvedPushNotificationSender
  } = resolvePushNotificationPair({
    pushNotificationStore,
    pushNotificationSender
  });
  let currentData = await loadOrCreateTask({
    taskId,
    taskStore,
    agentId,
    message,
    contextId,
    metadata
  });
  if (params.configuration?.pushNotificationConfig) {
    resolvedPushNotificationStore.set({
      agentId,
      config: createTaskPushNotificationConfig(taskId, params.configuration.pushNotificationConfig)
    });
  }
  const context = createTaskContext({
    task: currentData,
    userMessage: message,
    history: currentData.history || [],
    activeCancellations: taskStore.activeCancellations
  });
  try {
    const resourceId = metadata?.resourceId ?? message.metadata?.resourceId ?? agentId;
    const result = await agent.generate([convertToCoreMessage(message)], {
      runId: taskId,
      requestContext,
      ...contextId ? { threadId: contextId, resourceId } : {}
    });
    const artifactUpdate = createArtifactUpdate({
      taskId: currentData.id,
      contextId: currentData.contextId,
      text: result.text,
      data: result.object
    });
    if (artifactUpdate) {
      currentData = applyUpdateToTask(currentData, artifactUpdate);
    }
    currentData = applyUpdateToTask(currentData, {
      state: "completed",
      message: void 0
    });
    currentData.metadata = {
      ...currentData.metadata,
      execution: {
        toolCalls: result.toolCalls,
        toolResults: result.toolResults,
        usage: result.usage,
        finishReason: result.finishReason
      }
    };
    await saveTaskAndMaybeSendPushNotification({
      taskStore,
      pushNotificationSender: resolvedPushNotificationSender,
      previousTask: context.task,
      nextTask: currentData,
      agentId,
      logger
    });
    context.task = currentData;
  } catch (handlerError) {
    const failureStatusUpdate = {
      state: "failed",
      message: {
        messageId: crypto.randomUUID(),
        role: "agent",
        parts: [
          {
            kind: "text",
            text: `Handler failed: ${handlerError instanceof Error ? handlerError.message : String(handlerError)}`
          }
        ],
        kind: "message"
      }
    };
    currentData = applyUpdateToTask(currentData, failureStatusUpdate);
    try {
      await saveTaskAndMaybeSendPushNotification({
        taskStore,
        pushNotificationSender: resolvedPushNotificationSender,
        previousTask: context.task,
        nextTask: currentData,
        agentId,
        logger
      });
    } catch (saveError) {
      logger?.error(`Failed to save task ${currentData.id} after handler error:`, saveError?.message);
    }
    return normalizeError(handlerError, requestId, currentData.id, logger);
  }
  return createSuccessResponse(requestId, currentData);
}
async function handleTaskGet({
  requestId,
  taskStore,
  agentId,
  taskId
}) {
  const task = await taskStore.load({ agentId, taskId });
  if (!task) {
    throw MastraA2AError.taskNotFound(taskId);
  }
  return createSuccessResponse(requestId, task);
}
async function loadTaskOrThrow({
  taskStore,
  agentId,
  taskId
}) {
  const task = await taskStore.load({ agentId, taskId });
  if (!task) {
    throw MastraA2AError.taskNotFound(taskId);
  }
  return task;
}
async function handleSetTaskPushNotificationConfig({
  requestId,
  taskStore,
  pushNotificationStore,
  agentId,
  params
}) {
  await loadTaskOrThrow({
    taskStore,
    agentId,
    taskId: params.taskId
  });
  const { pushNotificationStore: resolvedPushNotificationStore } = resolvePushNotificationPair({
    pushNotificationStore
  });
  const config = resolvedPushNotificationStore.set({
    agentId,
    config: createTaskPushNotificationConfig(params.taskId, params.pushNotificationConfig)
  });
  return createSuccessResponse(requestId, config);
}
async function handleGetTaskPushNotificationConfig({
  requestId,
  taskStore,
  pushNotificationStore,
  agentId,
  params
}) {
  await loadTaskOrThrow({
    taskStore,
    agentId,
    taskId: params.id
  });
  const { pushNotificationStore: resolvedPushNotificationStore } = resolvePushNotificationPair({
    pushNotificationStore
  });
  const config = resolvedPushNotificationStore.get({
    agentId,
    params
  });
  if (!config) {
    throw MastraA2AError.invalidParams(
      `Push notification config not found: ${params.pushNotificationConfigId ?? params.id}`
    );
  }
  return createSuccessResponse(requestId, config);
}
async function handleListTaskPushNotificationConfig({
  requestId,
  taskStore,
  pushNotificationStore,
  agentId,
  params
}) {
  await loadTaskOrThrow({
    taskStore,
    agentId,
    taskId: params.id
  });
  const { pushNotificationStore: resolvedPushNotificationStore } = resolvePushNotificationPair({
    pushNotificationStore
  });
  const configs = resolvedPushNotificationStore.list({
    agentId,
    params
  });
  return createSuccessResponse(requestId, configs);
}
async function handleDeleteTaskPushNotificationConfig({
  requestId,
  taskStore,
  pushNotificationStore,
  agentId,
  params
}) {
  await loadTaskOrThrow({
    taskStore,
    agentId,
    taskId: params.id
  });
  const { pushNotificationStore: resolvedPushNotificationStore } = resolvePushNotificationPair({
    pushNotificationStore
  });
  const deleted = resolvedPushNotificationStore.delete({
    agentId,
    params
  });
  if (!deleted) {
    throw MastraA2AError.invalidParams(`Push notification config not found: ${params.pushNotificationConfigId}`);
  }
  return createSuccessResponse(requestId, null);
}
async function* handleMessageStream({
  requestId,
  params,
  taskStore,
  pushNotificationStore,
  pushNotificationSender,
  agent,
  agentId,
  logger,
  requestContext
}) {
  validateMessageSendParams(params);
  const { message, metadata } = params;
  const { contextId } = message;
  const taskId = message.taskId || crypto.randomUUID();
  const {
    pushNotificationStore: resolvedPushNotificationStore,
    pushNotificationSender: resolvedPushNotificationSender
  } = resolvePushNotificationPair({
    pushNotificationStore,
    pushNotificationSender
  });
  let currentData = await loadOrCreateTask({
    taskId,
    taskStore,
    agentId,
    message,
    contextId,
    metadata
  });
  if (params.configuration?.pushNotificationConfig) {
    resolvedPushNotificationStore.set({
      agentId,
      config: createTaskPushNotificationConfig(taskId, params.configuration.pushNotificationConfig)
    });
  }
  currentData = applyUpdateToTask(currentData, {
    state: "working",
    message: {
      messageId: crypto.randomUUID(),
      kind: "message",
      role: "agent",
      parts: [{ kind: "text", text: "Generating response..." }]
    }
  });
  await saveTaskAndMaybeSendPushNotification({
    taskStore,
    pushNotificationSender: resolvedPushNotificationSender,
    nextTask: currentData,
    agentId,
    logger
  });
  yield createSuccessResponse(requestId, currentData);
  try {
    const resourceId = metadata?.resourceId ?? message.metadata?.resourceId ?? agentId;
    const result = await agent.stream([convertToCoreMessage(message)], {
      runId: taskId,
      requestContext,
      ...contextId ? { threadId: contextId, resourceId } : {}
    });
    let sawTextArtifact = false;
    let pendingTextChunk;
    let structuredData;
    for await (const chunk of result.fullStream) {
      const textDelta = extractFullStreamTextDelta(chunk);
      if (textDelta !== null) {
        if (!pendingTextChunk) {
          pendingTextChunk = textDelta;
          continue;
        }
        const textUpdate = createTextChunkArtifactUpdate({
          taskId: currentData.id,
          contextId: currentData.contextId,
          text: pendingTextChunk,
          append: sawTextArtifact,
          lastChunk: false
        });
        currentData = applyUpdateToTask(currentData, textUpdate);
        await saveTaskAndMaybeSendPushNotification({
          taskStore,
          pushNotificationSender: resolvedPushNotificationSender,
          nextTask: currentData,
          agentId,
          logger
        });
        yield createSuccessResponse(requestId, textUpdate);
        sawTextArtifact = true;
        pendingTextChunk = textDelta;
        continue;
      }
      const finalStructuredObject = extractFinalStructuredObject(chunk);
      if (finalStructuredObject) {
        structuredData = finalStructuredObject;
      }
    }
    structuredData ??= await result.object;
    if (!pendingTextChunk && !sawTextArtifact) {
      const finalText = await result.text;
      if (finalText) {
        pendingTextChunk = finalText;
      }
    }
    if (pendingTextChunk) {
      const textUpdate = createTextChunkArtifactUpdate({
        taskId: currentData.id,
        contextId: currentData.contextId,
        text: pendingTextChunk,
        append: sawTextArtifact,
        lastChunk: !structuredData
      });
      currentData = applyUpdateToTask(currentData, textUpdate);
      await saveTaskAndMaybeSendPushNotification({
        taskStore,
        pushNotificationSender: resolvedPushNotificationSender,
        nextTask: currentData,
        agentId,
        logger
      });
      yield createSuccessResponse(requestId, textUpdate);
      sawTextArtifact = true;
      pendingTextChunk = void 0;
    }
    if (structuredData) {
      const dataUpdate = createDataArtifactUpdate({
        taskId: currentData.id,
        contextId: currentData.contextId,
        data: structuredData,
        lastChunk: true
      });
      currentData = applyUpdateToTask(currentData, dataUpdate);
      await saveTaskAndMaybeSendPushNotification({
        taskStore,
        pushNotificationSender: resolvedPushNotificationSender,
        nextTask: currentData,
        agentId,
        logger
      });
      yield createSuccessResponse(requestId, dataUpdate);
    }
    const previousTask = currentData;
    const completedTask = applyUpdateToTask(currentData, {
      state: "completed",
      message: void 0
    });
    completedTask.metadata = {
      ...completedTask.metadata,
      execution: {
        toolCalls: await result.toolCalls,
        toolResults: await result.toolResults,
        usage: await result.usage,
        finishReason: await result.finishReason
      }
    };
    currentData = completedTask;
    await saveTaskAndMaybeSendPushNotification({
      taskStore,
      pushNotificationSender: resolvedPushNotificationSender,
      previousTask,
      nextTask: currentData,
      agentId,
      logger
    });
  } catch (handlerError) {
    const previousTask = currentData;
    currentData = applyUpdateToTask(currentData, {
      state: "failed",
      message: {
        messageId: crypto.randomUUID(),
        role: "agent",
        parts: [
          {
            kind: "text",
            text: `Handler failed: ${handlerError instanceof Error ? handlerError.message : String(handlerError)}`
          }
        ],
        kind: "message"
      }
    });
    try {
      await saveTaskAndMaybeSendPushNotification({
        taskStore,
        pushNotificationSender: resolvedPushNotificationSender,
        previousTask,
        nextTask: currentData,
        agentId,
        logger
      });
    } catch (saveError) {
      logger?.error(`Failed to save task ${currentData.id} after handler error:`, saveError?.message);
    }
  }
  yield createSuccessResponse(requestId, {
    kind: "status-update",
    taskId: currentData.id,
    contextId: currentData.contextId,
    status: currentData.status,
    final: true
  });
}
async function* handleTaskResubscribe({
  requestId,
  taskStore,
  agentId,
  taskId,
  abortSignal
}) {
  let snapshot = taskStore.loadWithVersion({ agentId, taskId });
  if (!snapshot) {
    throw MastraA2AError.taskNotFound(taskId);
  }
  yield createSuccessResponse(requestId, snapshot.task);
  if (isTerminalTaskState(snapshot.task.status.state)) {
    return;
  }
  while (true) {
    const { task, version } = snapshot;
    const nextUpdate = await taskStore.waitForNextUpdate({
      agentId,
      taskId,
      afterVersion: version,
      signal: abortSignal
    });
    for (const artifactUpdate of getTaskArtifactUpdates({ previous: task, next: nextUpdate.task })) {
      yield createSuccessResponse(requestId, artifactUpdate);
    }
    if (didTaskStatusChange(task, nextUpdate.task)) {
      yield createSuccessResponse(requestId, {
        kind: "status-update",
        taskId: nextUpdate.task.id,
        contextId: nextUpdate.task.contextId,
        status: nextUpdate.task.status,
        final: isTerminalTaskState(nextUpdate.task.status.state)
      });
    }
    if (isTerminalTaskState(nextUpdate.task.status.state)) {
      return;
    }
    snapshot = nextUpdate;
  }
}
function getTaskIdFromParams(params) {
  if (!params || typeof params !== "object") {
    return void 0;
  }
  if ("id" in params && typeof params.id === "string") {
    return params.id;
  }
  if ("taskId" in params && typeof params.taskId === "string") {
    return params.taskId;
  }
  if ("message" in params && params.message && typeof params.message === "object" && "taskId" in params.message) {
    return typeof params.message.taskId === "string" ? params.message.taskId : void 0;
  }
  return void 0;
}
function isAsyncIterable(value) {
  return !!value && typeof value === "object" && Symbol.asyncIterator in value;
}
function createA2AJsonResponse(payload) {
  return Response.json(payload);
}
function createA2ASSEResponse(payload) {
  const encoder = new TextEncoder();
  const iterable = isAsyncIterable(payload) ? payload : (async function* () {
    yield payload;
  })();
  const stream = new ReadableStream({
    async start(controller) {
      try {
        for await (const chunk of iterable) {
          controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}

`));
        }
      } catch (error) {
        controller.error(error);
        return;
      }
      controller.close();
    }
  });
  return new Response(stream, {
    headers: {
      "Content-Type": "text/event-stream; charset=utf-8",
      "Cache-Control": "no-cache",
      Connection: "keep-alive",
      "X-Accel-Buffering": "no"
    }
  });
}
async function handleTaskCancel({
  requestId,
  taskStore,
  pushNotificationSender,
  agentId,
  taskId,
  logger
}) {
  let data = await taskStore.load({
    agentId,
    taskId
  });
  if (!data) {
    throw MastraA2AError.taskNotFound(taskId);
  }
  const finalStates = ["completed", "failed", "canceled"];
  if (finalStates.includes(data.status.state)) {
    logger?.info(`Task ${taskId} already in final state ${data.status.state}, cannot cancel.`);
    return createSuccessResponse(requestId, data);
  }
  taskStore.activeCancellations.add(taskId);
  const cancelUpdate = {
    state: "canceled",
    message: {
      role: "agent",
      parts: [{ kind: "text", text: "Task cancelled by request." }],
      kind: "message",
      messageId: crypto.randomUUID()
    }
  };
  const previousTask = data;
  data = applyUpdateToTask(data, cancelUpdate);
  await saveTaskAndMaybeSendPushNotification({
    taskStore,
    pushNotificationSender: resolvePushNotificationPair({ pushNotificationSender }).pushNotificationSender,
    previousTask,
    nextTask: data,
    agentId,
    logger
  });
  taskStore.activeCancellations.delete(taskId);
  return createSuccessResponse(requestId, data);
}
async function getAgentExecutionHandler({
  requestId,
  mastra,
  agentId,
  requestContext,
  method,
  params,
  taskStore,
  pushNotificationStore,
  pushNotificationSender,
  logger,
  abortSignal
}) {
  const agent = await getAgentFromSystem({ mastra, agentId });
  const {
    pushNotificationStore: resolvedPushNotificationStore,
    pushNotificationSender: resolvedPushNotificationSender
  } = resolvePushNotificationPair({
    pushNotificationStore,
    pushNotificationSender
  });
  let taskId;
  try {
    taskId = getTaskIdFromParams(params);
    switch (method) {
      case "message/send": {
        const result = await handleMessageSend({
          requestId,
          params,
          taskStore,
          pushNotificationStore: resolvedPushNotificationStore,
          pushNotificationSender: resolvedPushNotificationSender,
          agent,
          agentId,
          logger,
          requestContext
        });
        return result;
      }
      case "message/stream": {
        const result = await handleMessageStream({
          requestId,
          taskStore,
          params,
          pushNotificationStore: resolvedPushNotificationStore,
          pushNotificationSender: resolvedPushNotificationSender,
          agent,
          agentId,
          logger,
          requestContext
        });
        return result;
      }
      case "tasks/get": {
        const result = await handleTaskGet({
          requestId,
          taskStore,
          agentId,
          taskId: taskId || "No task ID provided"
        });
        return result;
      }
      case "tasks/cancel": {
        const result = await handleTaskCancel({
          requestId,
          taskStore,
          pushNotificationSender: resolvedPushNotificationSender,
          agentId,
          taskId: taskId || "No task ID provided",
          logger
        });
        return result;
      }
      case "tasks/resubscribe":
        return await handleTaskResubscribe({
          requestId,
          taskStore,
          agentId,
          taskId: taskId || "No task ID provided",
          abortSignal
        });
      case "tasks/pushNotificationConfig/set":
        return await handleSetTaskPushNotificationConfig({
          requestId,
          taskStore,
          pushNotificationStore: resolvedPushNotificationStore,
          agentId,
          params
        });
      case "tasks/pushNotificationConfig/get":
        return await handleGetTaskPushNotificationConfig({
          requestId,
          taskStore,
          pushNotificationStore: resolvedPushNotificationStore,
          agentId,
          params
        });
      case "tasks/pushNotificationConfig/list":
        return await handleListTaskPushNotificationConfig({
          requestId,
          taskStore,
          pushNotificationStore: resolvedPushNotificationStore,
          agentId,
          params
        });
      case "tasks/pushNotificationConfig/delete":
        return await handleDeleteTaskPushNotificationConfig({
          requestId,
          taskStore,
          pushNotificationStore: resolvedPushNotificationStore,
          agentId,
          params
        });
      case "agent/getAuthenticatedExtendedCard":
        throw MastraA2AError.extendedAgentCardNotConfigured();
      default:
        throw MastraA2AError.methodNotFound(method);
    }
  } catch (error) {
    if (error instanceof MastraA2AError && taskId && !error.taskId) {
      error.taskId = taskId;
    }
    return normalizeError(error, requestId, taskId, logger);
  }
}
var GET_AGENT_CARD_ROUTE = createRoute({
  method: "GET",
  path: "/.well-known/:agentId/agent-card.json",
  responseType: "json",
  pathParamSchema: a2aAgentIdPathParams,
  responseSchema: agentCardResponseSchema,
  summary: "Get agent card",
  description: "Returns the agent card information for A2A protocol discovery",
  tags: ["Agent-to-Agent"],
  requiresAuth: true,
  handler: async (ctx) => {
    const executionUrl = getA2AExecutionUrl({
      agentId: ctx.agentId,
      request: ctx.request,
      routePrefix: ctx.routePrefix
    });
    return getAgentCardByIdHandler({
      mastra: ctx.mastra,
      requestContext: ctx.requestContext,
      agentId: ctx.agentId,
      executionUrl,
      pushNotifications: true
    });
  }
});
var AGENT_EXECUTION_ROUTE = createRoute({
  method: "POST",
  path: "/a2a/:agentId",
  responseType: "datastream-response",
  pathParamSchema: a2aAgentIdPathParams,
  bodySchema: agentExecutionBodySchema,
  responseSchema: agentExecutionResponseSchema,
  summary: "Execute agent",
  description: "Executes an agent action via JSON-RPC 2.0 over A2A protocol",
  tags: ["Agent-to-Agent"],
  requiresAuth: true,
  handler: async ({ mastra, agentId, requestContext, taskStore, abortSignal, ...bodyParams }) => {
    const { id: requestId, method } = bodyParams;
    const params = "params" in bodyParams ? bodyParams.params : void 0;
    const result = await getAgentExecutionHandler({
      requestId,
      mastra,
      agentId,
      requestContext,
      method,
      params,
      taskStore,
      abortSignal
    });
    if (method === "message/stream" || method === "tasks/resubscribe") {
      return createA2ASSEResponse(result);
    }
    return createA2AJsonResponse(result);
  }
});

export { AGENT_EXECUTION_ROUTE, GET_AGENT_CARD_ROUTE, a2a_exports, getAgentCardByIdHandler, getAgentExecutionHandler, handleDeleteTaskPushNotificationConfig, handleGetTaskPushNotificationConfig, handleListTaskPushNotificationConfig, handleMessageSend, handleMessageStream, handleSetTaskPushNotificationConfig, handleTaskCancel, handleTaskGet, handleTaskResubscribe };
//# sourceMappingURL=chunk-UY3PA3YA.js.map
//# sourceMappingURL=chunk-UY3PA3YA.js.map