import { getLogger as getLogger$1 } from "../../../../logger.js";
import { toolSessionManager } from "../services/ToolSessionManager.js";
import { agentSessionManager } from "../../session/AgentSession.js";
import { isValidTool } from "../agent-types.js";
import { getRelationshipIdForTool } from "./tool-utils.js";
import { wrapToolWithStreaming } from "./tool-wrapper.js";
import { enhanceToolResultWithStructureHints } from "../generation/tool-result.js";
import { parseAndCheckApproval } from "./tool-approval.js";
import { parseEmbeddedJson, unwrapError } from "@inkeep/agents-core";
import { SpanStatusCode, trace } from "@opentelemetry/api";
import { tool } from "ai";

//#region src/domains/run/agents/tools/mcp-tools.ts
const logger = getLogger$1("Agent");
async function getMcpTools(ctx, sessionId, streamRequestId) {
	const mcpTools = ctx.config.tools?.filter((tool$1) => {
		return tool$1.config?.type === "mcp";
	}) || [];
	const { mcpManager } = ctx;
	const toolSets = mcpManager ? await Promise.all(mcpTools.map((tool$1) => mcpManager.getToolSet(tool$1))) || [] : [];
	if (!sessionId) {
		const wrappedTools$1 = {};
		for (const toolSet of toolSets) for (const [toolName, toolDef] of Object.entries(toolSet.tools)) {
			const needsApproval = toolSet.toolPolicies?.[toolName]?.needsApproval || false;
			wrappedTools$1[toolName] = wrapToolWithStreaming(ctx, toolName, {
				...toolDef || {},
				needsApproval
			}, streamRequestId, "mcp", {
				needsApproval,
				mcpServerId: toolSet.mcpServerId,
				mcpServerName: toolSet.mcpServerName
			});
		}
		return {
			tools: wrappedTools$1,
			toolSets
		};
	}
	const wrappedTools = {};
	for (const toolResult of toolSets) for (const [toolName, originalTool] of Object.entries(toolResult.tools)) {
		if (!isValidTool(originalTool)) {
			logger.error({ toolName }, "Invalid MCP tool structure - missing required properties");
			continue;
		}
		const needsApproval = toolResult.toolPolicies?.[toolName]?.needsApproval || false;
		logger.debug({
			toolName,
			toolPolicies: toolResult.toolPolicies,
			needsApproval,
			policyForThisTool: toolResult.toolPolicies?.[toolName]
		}, "Tool approval check");
		wrappedTools[toolName] = wrapToolWithStreaming(ctx, toolName, tool({
			description: originalTool.description,
			inputSchema: originalTool.inputSchema,
			execute: async (args, { toolCallId, providerMetadata }) => {
				const parsed = await parseAndCheckApproval(ctx, toolName, toolCallId, args, providerMetadata, needsApproval);
				if (parsed.denied) return parsed.result;
				if (parsed.pendingApproval) return null;
				const finalArgs = parsed.args;
				logger.debug({
					toolName,
					toolCallId
				}, "MCP Tool Called");
				try {
					const rawResult = await originalTool.execute(finalArgs, { toolCallId });
					const result = rawResult;
					if (result.isError) {
						const errorMessage = result.content?.[0]?.text || "MCP tool returned an error";
						logger.error({
							toolName,
							toolCallId,
							errorMessage,
							rawResult
						}, "MCP tool returned error status");
						toolSessionManager.recordToolResult(sessionId, {
							toolCallId,
							toolName,
							args: finalArgs,
							result: {
								error: errorMessage,
								failed: true
							},
							timestamp: Date.now()
						});
						if (streamRequestId) {
							const relationshipId = getRelationshipIdForTool(ctx, toolName, "mcp");
							agentSessionManager.recordEvent(streamRequestId, "error", ctx.config.id, {
								message: `MCP tool "${toolName}" failed: ${errorMessage}`,
								code: "mcp_tool_error",
								severity: "error",
								context: {
									toolName,
									toolCallId,
									errorMessage,
									relationshipId
								},
								relationshipId
							});
						}
						const activeSpan = trace.getActiveSpan();
						if (activeSpan) {
							const error = /* @__PURE__ */ new Error(`Tool "${toolName}" failed: ${errorMessage}. This tool is currently unavailable. Please try a different approach or inform the user of the issue.`);
							activeSpan.recordException(error);
							activeSpan.setStatus({
								code: SpanStatusCode.ERROR,
								message: `MCP tool returned error: ${errorMessage}`
							});
						}
						throw new Error(`Tool "${toolName}" failed: ${errorMessage}. This tool is currently unavailable. Please try a different approach or inform the user of the issue.`);
					}
					const parsedResult = parseEmbeddedJson(rawResult);
					const enhancedResult = enhanceToolResultWithStructureHints(ctx, parsedResult, toolCallId);
					toolSessionManager.recordToolResult(sessionId, {
						toolCallId,
						toolName,
						args: finalArgs,
						result: parsedResult,
						timestamp: Date.now()
					});
					return enhancedResult;
				} catch (error) {
					const rootCause = unwrapError(error);
					logger.error({
						toolName,
						toolCallId,
						error: rootCause.message
					}, "MCP tool execution failed");
					throw rootCause;
				}
			}
		}), streamRequestId, "mcp", {
			needsApproval,
			mcpServerId: toolResult.mcpServerId,
			mcpServerName: toolResult.mcpServerName
		});
	}
	return {
		tools: wrappedTools,
		toolSets
	};
}

//#endregion
export { getMcpTools };