import { agentCardResponseSchema, a2aAgentIdPathParams, agentExecutionResponseSchema, agentExecutionBodySchema } from './chunk-TJNZEYLA.js';
import { getPublicOrigin } from './chunk-JJT4GBDZ.js';
import { getAgentFromSystem } from './chunk-YGQNINW7.js';
import { convertInstructionsToString } from './chunk-ERKUFMCT.js';
import { createRoute } from './chunk-PA2BYLKF.js';
import { __export } from './chunk-PR4QN5HX.js';
import { MastraA2AError } from '@mastra/core/a2a';
import { z } from 'zod/v4';

// 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,
  handleMessageSend: () => handleMessageSend,
  handleMessageStream: () => handleMessageStream,
  handleTaskCancel: () => handleTaskCancel,
  handleTaskGet: () => handleTaskGet,
  handleTaskResubscribe: () => handleTaskResubscribe
});
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");
  }
}

// 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 messageSendParamsSchema = z.object({
  message: z.object({
    role: z.enum(["user", "agent"]),
    parts: z.array(
      z.object({
        kind: z.enum(["text"]),
        text: z.string()
      })
    ),
    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()
  })
});
function createAgentCardDefaults() {
  return {
    protocolVersion: "0.3.0",
    additionalInterfaces: [],
    supportsAuthenticatedExtendedCard: false,
    security: [],
    securitySchemes: {},
    capabilities: {
      streaming: true,
      pushNotifications: false,
      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",
  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(),
    // 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"]
    }))
  };
  return agentCard;
}
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 createTextArtifactUpdate({ taskId, contextId, text }) {
  return {
    kind: "artifact-update",
    taskId,
    contextId,
    lastChunk: true,
    artifact: {
      artifactId: `${taskId}:response`,
      name: "response.txt",
      parts: [{ kind: "text", text }]
    }
  };
}
async function handleMessageSend({
  requestId,
  params,
  taskStore,
  agent,
  agentId,
  logger,
  requestContext
}) {
  validateMessageSendParams(params);
  const { message, metadata } = params;
  const { contextId } = message;
  const taskId = message.taskId || crypto.randomUUID();
  let currentData = await loadOrCreateTask({
    taskId,
    taskStore,
    agentId,
    message,
    contextId,
    metadata
  });
  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 } : {}
    });
    if (result.text) {
      currentData = applyUpdateToTask(
        currentData,
        createTextArtifactUpdate({
          taskId: currentData.id,
          contextId: currentData.contextId,
          text: result.text
        })
      );
    }
    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 taskStore.save({ agentId, data: 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 taskStore.save({ agentId, data: currentData });
    } 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* handleMessageStream({
  requestId,
  params,
  taskStore,
  agent,
  agentId,
  logger,
  requestContext
}) {
  validateMessageSendParams(params);
  const { message, metadata } = params;
  const { contextId } = message;
  const taskId = message.taskId || crypto.randomUUID();
  let currentData = await loadOrCreateTask({
    taskId,
    taskStore,
    agentId,
    message,
    contextId,
    metadata
  });
  currentData = applyUpdateToTask(currentData, {
    state: "working",
    message: {
      messageId: crypto.randomUUID(),
      kind: "message",
      role: "agent",
      parts: [{ kind: "text", text: "Generating response..." }]
    }
  });
  await taskStore.save({ agentId, data: currentData });
  yield createSuccessResponse(requestId, currentData);
  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 = result.text && createTextArtifactUpdate({
      taskId: currentData.id,
      contextId: currentData.contextId,
      text: result.text
    });
    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 taskStore.save({ agentId, data: currentData });
    if (artifactUpdate) {
      yield createSuccessResponse(requestId, artifactUpdate);
    }
  } catch (handlerError) {
    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 taskStore.save({ agentId, data: currentData });
    } 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);
  }
  const finalStates = ["completed", "failed", "canceled"];
  while (true) {
    const { task, version } = snapshot;
    const isFinal = finalStates.includes(task.status.state);
    yield createSuccessResponse(requestId, {
      kind: "status-update",
      taskId: task.id,
      contextId: task.contextId,
      status: task.status,
      final: isFinal
    });
    if (isFinal) {
      return;
    }
    const nextUpdate = await taskStore.waitForNextUpdate({
      agentId,
      taskId,
      afterVersion: version,
      signal: abortSignal
    });
    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,
  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()
    }
  };
  data = applyUpdateToTask(data, cancelUpdate);
  await taskStore.save({ agentId, data });
  taskStore.activeCancellations.delete(taskId);
  return createSuccessResponse(requestId, data);
}
async function getAgentExecutionHandler({
  requestId,
  mastra,
  agentId,
  requestContext,
  method,
  params,
  taskStore,
  logger,
  abortSignal
}) {
  const agent = await getAgentFromSystem({ mastra, agentId });
  let taskId;
  try {
    taskId = getTaskIdFromParams(params);
    switch (method) {
      case "message/send": {
        const result = await handleMessageSend({
          requestId,
          params,
          taskStore,
          agent,
          agentId,
          requestContext
        });
        return result;
      }
      case "message/stream": {
        const result = await handleMessageStream({
          requestId,
          taskStore,
          params,
          agent,
          agentId,
          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,
          agentId,
          taskId: taskId || "No task ID provided"
        });
        return result;
      }
      case "tasks/resubscribe":
        return await handleTaskResubscribe({
          requestId,
          taskStore,
          agentId,
          taskId: taskId || "No task ID provided",
          abortSignal
        });
      case "tasks/pushNotificationConfig/set":
      case "tasks/pushNotificationConfig/get":
      case "tasks/pushNotificationConfig/list":
      case "tasks/pushNotificationConfig/delete":
        throw MastraA2AError.pushNotificationNotSupported();
      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
    });
  }
});
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, handleMessageSend, handleMessageStream, handleTaskCancel, handleTaskGet, handleTaskResubscribe };
//# sourceMappingURL=chunk-3DKWFTZU.js.map
//# sourceMappingURL=chunk-3DKWFTZU.js.map