import { getLogger as getLogger$1 } from "../../../logger.js";
import manageDbPool_default from "../../../data/db/manageDbPool.js";
import { toolSessionManager } from "./ToolSessionManager.js";
import { agentSessionManager } from "../services/AgentSession.js";
import { getUserIdFromContext } from "../types/executionContext.js";
import { resolveModelConfig } from "../utils/model-resolver.js";
import { enhanceInternalRelation, enhanceTeamRelation, getArtifactComponentsForSubAgent, getDataComponentsForSubAgent, getSubAgentRelations, getToolsForSubAgent } from "../utils/project.js";
import { buildTransferRelationConfig } from "./relationTools.js";
import { Agent } from "./Agent.js";
import { TaskState, generateId, getMcpToolById, withRef } from "@inkeep/agents-core";

//#region src/domains/run/agents/generateTaskHandler.ts
const logger = getLogger$1("generateTaskHandler");
const createTaskHandler = (config, credentialStoreRegistry) => {
	return async (task) => {
		let agent;
		try {
			const textParts = task.input.parts.filter((part) => part.kind === "text").map((part) => part.text).join(" ");
			const dataParts = task.input.parts.filter((part) => part.kind === "data" && part.data != null);
			let userMessage = textParts;
			if (dataParts.length > 0) userMessage = `${textParts}${dataParts.map((part) => {
				const metadata = part.metadata;
				return `\n\n<structured_data${metadata?.source ? ` (source: ${metadata.source})` : ""}>\n${JSON.stringify(part.data, null, 2)}\n</structured_data>`;
			}).join("")}`;
			if (!userMessage.trim()) return {
				status: {
					state: TaskState.Failed,
					message: "No text content found in task input"
				},
				artifacts: []
			};
			const forwardedHeaders = task.context?.metadata?.forwardedHeaders;
			const { project, agentId, tenantId, projectId, resolvedRef } = config.executionContext;
			const currentAgent = project.agents[agentId];
			const currentSubAgent = currentAgent?.subAgents?.[config.subAgentId];
			if (!currentSubAgent) return {
				status: {
					state: TaskState.Failed,
					message: `Sub-agent ${config.subAgentId} not found in project`
				},
				artifacts: []
			};
			const { externalRelations, teamRelations, transferRelations, internalDelegateRelations } = getSubAgentRelations({
				agent: currentAgent,
				project,
				subAgent: currentSubAgent
			});
			const allInternalRelations = [...transferRelations, ...internalDelegateRelations];
			const toolsForAgent = getToolsForSubAgent({
				agent: currentAgent,
				project,
				subAgent: currentSubAgent
			});
			const dataComponents = getDataComponentsForSubAgent({
				project,
				subAgent: currentSubAgent
			});
			const artifactComponents = getArtifactComponentsForSubAgent({
				project,
				subAgent: currentSubAgent
			});
			const enhancedInternalRelations = allInternalRelations.map((relation) => {
				try {
					return enhanceInternalRelation({
						relation,
						agent: currentAgent,
						project
					});
				} catch (error) {
					logger.warn({
						subAgentId: relation.id,
						error
					}, "Failed to enhance agent description");
					return relation;
				}
			});
			const enhancedTeamRelations = teamRelations.map((relation) => {
				try {
					return enhanceTeamRelation({
						relation,
						project
					});
				} catch (error) {
					logger.warn({
						targetAgentId: relation.targetAgentId,
						error
					}, "Failed to enhance team agent description");
					return relation;
				}
			});
			const prompt = "prompt" in config.agentSchema ? config.agentSchema.prompt || void 0 : "";
			const models = "models" in config.agentSchema ? config.agentSchema.models : void 0;
			const stopWhen = "stopWhen" in config.agentSchema ? config.agentSchema.stopWhen : void 0;
			const toolsForAgentResult = await withRef(manageDbPool_default, resolvedRef, async (db) => {
				return await Promise.all(toolsForAgent.map(async (item) => {
					const mcpTool = await getMcpToolById(db)({
						scopes: {
							tenantId,
							projectId
						},
						toolId: item.tool.id,
						credentialStoreRegistry,
						userId: config.userId
					});
					if (!mcpTool) throw new Error(`Tool not found: ${item.tool.id}`);
					if (item.relationshipId) mcpTool.relationshipId = item.relationshipId;
					if (item.selectedTools && item.selectedTools.length > 0) {
						const selectedToolsSet = new Set(item.selectedTools);
						mcpTool.availableTools = mcpTool.availableTools?.filter((tool) => selectedToolsSet.has(tool.name)) || [];
					}
					return mcpTool;
				}));
			}) ?? [];
			agent = new Agent({
				id: config.subAgentId,
				tenantId,
				projectId,
				agentId,
				baseUrl: config.baseUrl,
				apiKey: config.apiKey,
				userId: config.userId,
				name: config.name,
				description: config.description || "",
				prompt,
				models: models || void 0,
				stopWhen: stopWhen || void 0,
				subAgentRelations: enhancedInternalRelations.map((relation) => ({
					id: relation.id,
					tenantId,
					projectId,
					agentId,
					baseUrl: config.baseUrl,
					apiKey: config.apiKey,
					name: relation.name,
					description: relation.description || void 0,
					prompt: "",
					delegateRelations: [],
					subAgentRelations: [],
					transferRelations: [],
					relationId: relation.relationId
				})),
				transferRelations: await Promise.all(enhancedInternalRelations.filter((relation) => relation.relationType === "transfer").map((relation) => buildTransferRelationConfig({
					relation,
					executionContext: config.executionContext,
					baseUrl: config.baseUrl,
					apiKey: config.apiKey
				}, credentialStoreRegistry))),
				delegateRelations: [
					...enhancedInternalRelations.filter((relation) => relation.relationType === "delegate").map((relation) => ({
						type: "internal",
						config: {
							id: relation.id,
							relationId: relation.relationId,
							tenantId,
							projectId,
							agentId,
							baseUrl: config.baseUrl,
							apiKey: config.apiKey,
							name: relation.name,
							description: relation.description || void 0,
							prompt: "",
							delegateRelations: [],
							subAgentRelations: [],
							transferRelations: [],
							tools: [],
							project
						}
					})),
					...externalRelations.map((relation) => ({
						type: "external",
						config: {
							id: relation.externalAgent.id,
							name: relation.externalAgent.name,
							description: relation.externalAgent.description || "",
							ref: resolvedRef,
							baseUrl: relation.externalAgent.baseUrl,
							headers: relation.headers,
							credentialReferenceId: relation.externalAgent.credentialReferenceId,
							relationId: relation.relationId,
							relationType: "delegate"
						}
					})),
					...enhancedTeamRelations.map((relation) => ({
						type: "team",
						config: {
							id: relation.targetAgent.id,
							ref: resolvedRef,
							name: relation.targetAgent.name,
							description: relation.targetAgent.description || "",
							baseUrl: config.baseUrl,
							headers: relation.headers,
							relationId: relation.relationId
						}
					}))
				],
				tools: toolsForAgentResult,
				functionTools: [],
				dataComponents,
				artifactComponents,
				contextConfigId: config.contextConfigId || void 0,
				conversationHistoryConfig: config.conversationHistoryConfig,
				sandboxConfig: config.sandboxConfig,
				forwardedHeaders
			}, config.executionContext, credentialStoreRegistry);
			const artifactStreamRequestId = task.context?.metadata?.streamRequestId;
			if (artifactStreamRequestId && artifactComponents.length > 0) agentSessionManager.updateArtifactComponents(artifactStreamRequestId, artifactComponents);
			let contextId = task.context?.conversationId;
			if (!contextId || contextId === "default" || contextId === "") {
				const taskIdMatch = task.id.match(/^task_([^-]+-[^-]+-\d+)-/);
				if (taskIdMatch) {
					contextId = taskIdMatch[1];
					logger.info({
						taskId: task.id,
						extractedContextId: contextId,
						subAgentId: config.subAgentId
					}, "Extracted contextId from task ID for delegation");
				} else contextId = "default";
			}
			const streamRequestId = task.context?.metadata?.stream_request_id || task.context?.metadata?.streamRequestId;
			const isDelegation = task.context?.metadata?.isDelegation === true;
			const delegationId = task.context?.metadata?.delegationId;
			agent.setDelegationStatus(isDelegation);
			agent.setDelegationId(delegationId);
			if (isDelegation) {
				logger.info({
					subAgentId: config.subAgentId,
					taskId: task.id,
					delegationId
				}, "Delegated agent - streaming disabled");
				if (streamRequestId && tenantId && projectId) toolSessionManager.ensureAgentSession(streamRequestId, tenantId, projectId, contextId, task.id);
			}
			logger.info({ contextId }, "Context ID");
			logger.info({
				userMessage: userMessage.substring(0, 500),
				inputPartsCount: task.input.parts.length,
				textPartsCount: task.input.parts.filter((p) => p.kind === "text").length,
				dataPartsCount: task.input.parts.filter((p) => p.kind === "data").length,
				hasDataParts: task.input.parts.some((p) => p.kind === "data")
			}, "User Message with parts breakdown");
			const response = await agent.generate(userMessage, {
				contextId,
				metadata: {
					conversationId: contextId,
					taskId: task.id,
					threadId: contextId,
					streamRequestId,
					...config.apiKey ? { apiKey: config.apiKey } : {}
				}
			});
			agent.cleanupCompression();
			const stepContents = response.steps && Array.isArray(response.steps) ? response.steps.flatMap((step) => {
				return step.content && Array.isArray(step.content) ? step.content : [];
			}) : [];
			const allToolCalls = stepContents.filter((content) => content.type === "tool-call");
			const allToolResults = stepContents.filter((content) => content.type === "tool-result");
			const allThoughts = stepContents.filter((content) => content.type === "text");
			if (allToolCalls.length > 0) {
				for (const toolCall of allToolCalls) if (toolCall.toolName.includes("transfer") || toolCall.toolName.includes("transferToRefundAgent")) {
					const toolResult = allToolResults.find((result) => result.toolCallId === toolCall.toolCallId);
					logger.info({
						toolCallName: toolCall.toolName,
						toolCallId: toolCall.toolCallId,
						hasToolResult: !!toolResult,
						toolResultOutput: toolResult?.output,
						toolResultKeys: toolResult?.output ? Object.keys(toolResult.output) : []
					}, "[DEBUG] Transfer tool result found");
					const isValidTransferResult = (output) => {
						return typeof output === "object" && output !== null && "type" in output && "targetSubAgentId" in output && output.type === "transfer" && typeof output.targetSubAgentId === "string";
					};
					const transferReason = response.text || (response.object ? JSON.stringify(response.object) : "") || allThoughts[allThoughts.length - 1]?.text || "Agent requested transfer. No reason provided.";
					if (toolResult?.output && isValidTransferResult(toolResult.output)) {
						const transferResult = toolResult.output;
						logger.info({
							validationPassed: true,
							transferResult,
							targetSubAgentId: transferResult.targetSubAgentId,
							fromSubAgentId: transferResult.fromSubAgentId
						}, "[DEBUG] Transfer validation passed, extracted data");
						const artifactData = {
							type: "transfer",
							targetSubAgentId: transferResult.targetSubAgentId,
							fromSubAgentId: transferResult.fromSubAgentId,
							task_id: task.id,
							reason: transferReason,
							original_message: userMessage
						};
						logger.info({
							artifactData,
							artifactDataKeys: Object.keys(artifactData)
						}, "[DEBUG] Artifact data being returned");
						return {
							status: {
								state: TaskState.Completed,
								message: `Transfer requested to ${transferResult.targetSubAgentId}`
							},
							artifacts: [{
								artifactId: generateId(),
								parts: [{
									kind: "data",
									data: artifactData
								}],
								createdAt: (/* @__PURE__ */ new Date()).toISOString()
							}]
						};
					}
					logger.warn({
						hasToolResult: !!toolResult,
						hasOutput: !!toolResult?.output,
						validationPassed: false,
						output: toolResult?.output
					}, "[DEBUG] Transfer validation FAILED");
				}
			}
			const parts = (response.formattedContent?.parts || []).map((part) => {
				if (part.kind === "data") return {
					kind: "data",
					data: part.data
				};
				return {
					kind: "text",
					text: part.text
				};
			});
			return {
				status: { state: TaskState.Completed },
				artifacts: [{
					artifactId: generateId(),
					parts,
					createdAt: (/* @__PURE__ */ new Date()).toISOString()
				}]
			};
		} catch (error) {
			console.error("Task handler error:", error);
			try {
				if (agent) agent.cleanupCompression();
			} catch (cleanupError) {
				logger.warn({ cleanupError }, "Failed to cleanup agent compression on error");
			}
			const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
			const isConnectionRefused = errorMessage.includes("Connection refused. Please check if the MCP server is running.");
			return {
				status: {
					state: TaskState.Failed,
					message: errorMessage,
					type: isConnectionRefused ? "connection_refused" : "unknown"
				},
				artifacts: []
			};
		}
	};
};
/**
* Serializes a TaskHandlerConfig to JSON
*/
const serializeTaskHandlerConfig = (config) => {
	return JSON.stringify(config, null, 2);
};
/**
* Deserializes a TaskHandlerConfig from JSON
*/
const deserializeTaskHandlerConfig = (configJson) => {
	return JSON.parse(configJson);
};
/**
* Creates a task handler configuration from execution context and project data
*/
const createTaskHandlerConfig = async (params) => {
	const { executionContext, subAgentId, baseUrl, apiKey, sandboxConfig } = params;
	const { project, agentId } = executionContext;
	const agent = project.agents[agentId];
	const subAgent = agent?.subAgents?.[subAgentId];
	if (!subAgent) throw new Error(`Sub-agent not found: ${subAgentId}`);
	const effectiveModels = await resolveModelConfig(executionContext, subAgent);
	const effectiveConversationHistoryConfig = subAgent.conversationHistoryConfig;
	return {
		executionContext,
		subAgentId,
		agentSchema: {
			id: subAgent.id,
			name: subAgent.name,
			description: subAgent.description,
			prompt: subAgent.prompt,
			models: effectiveModels,
			conversationHistoryConfig: effectiveConversationHistoryConfig || null,
			stopWhen: subAgent.stopWhen || null,
			createdAt: subAgent.createdAt,
			updatedAt: subAgent.updatedAt
		},
		baseUrl,
		apiKey,
		name: subAgent.name,
		description: subAgent.description || void 0,
		conversationHistoryConfig: effectiveConversationHistoryConfig,
		contextConfigId: agent?.contextConfig?.id || void 0,
		sandboxConfig,
		userId: getUserIdFromContext(executionContext)
	};
};

//#endregion
export { createTaskHandler, createTaskHandlerConfig, deserializeTaskHandlerConfig, serializeTaskHandlerConfig };