import manageDbPool_default from "../../../../data/db/manageDbPool.js";
import runDbClient_default from "../../../../data/db/runDbClient.js";
import { getLogger as getLogger$1 } from "../../../../logger.js";
import manageDbClient_default from "../../../../data/db/manageDbClient.js";
import "../../../../data/db/index.js";
import { EvaluationService } from "../../services/EvaluationService.js";
import { executeAgentAsync } from "../../../run/services/TriggerService.js";
import { addConversationIdToInvocation, createDatasetRunConversationRelation, createEvaluationResult, generateId, getAgentIdsForEvaluators, getConversation, getEvaluatorById, getProjectScopedRef, isForeignKeyViolation, markScheduledTriggerInvocationCompleted, markScheduledTriggerInvocationFailed, markScheduledTriggerInvocationRunning, resolveRef, updateEvaluationResult, updateTriggerInvocationStatus, withRef } from "@inkeep/agents-core";

//#region src/domains/evals/workflow/functions/runDatasetItem.ts
const logger = getLogger$1("workflow-run-dataset-item");
/**
* Step: Execute the dataset item by calling executeAgentAsync directly
*/
async function executeDatasetItemStep(payload) {
	"use step";
	const { tenantId, projectId, agentId, datasetItemInput, datasetRunId, scheduledTriggerInvocationId } = payload;
	const conversationId = generateId();
	const effectiveTimeout = 780;
	try {
		const ref = getProjectScopedRef(tenantId, projectId, payload.ref || "main");
		const resolvedRef = await resolveRef(manageDbClient_default)(ref);
		if (!resolvedRef) return {
			success: false,
			conversationId,
			error: `Failed to resolve ref for project ${projectId}`
		};
		const timeoutMs = effectiveTimeout * 1e3;
		const timeoutPromise = new Promise((_, reject) => {
			setTimeout(() => reject(/* @__PURE__ */ new Error(`Execution timed out after ${effectiveTimeout}s`)), timeoutMs);
		});
		await Promise.race([executeAgentAsync({
			tenantId,
			projectId,
			agentId,
			triggerId: datasetRunId,
			invocationId: scheduledTriggerInvocationId,
			conversationId,
			resolvedRef,
			messages: datasetItemInput.messages,
			invocationType: "scheduled_trigger",
			datasetRunId
		}), timeoutPromise]);
		return {
			success: true,
			conversationId
		};
	} catch (error) {
		const errorMessage = error instanceof Error ? error.message : String(error);
		logger.error({
			datasetRunId,
			invocationId: scheduledTriggerInvocationId,
			conversationId,
			error: errorMessage
		}, "Dataset item execution failed");
		return {
			success: false,
			conversationId,
			error: errorMessage
		};
	}
}
/**
* Step: Record conversation relation and track on invocation
*/
async function recordConversationStep(params) {
	"use step";
	const { tenantId, projectId, agentId, datasetRunId, datasetItemId, conversationId, scheduledTriggerInvocationId } = params;
	try {
		await Promise.all([createDatasetRunConversationRelation(runDbClient_default)({
			tenantId,
			projectId,
			id: generateId(),
			datasetRunId,
			conversationId,
			datasetItemId
		}), addConversationIdToInvocation(runDbClient_default)({
			scopes: {
				tenantId,
				projectId,
				agentId
			},
			scheduledTriggerId: datasetRunId,
			invocationId: scheduledTriggerInvocationId,
			conversationId
		})]);
	} catch (error) {
		if (isForeignKeyViolation(error)) logger.warn({
			tenantId,
			projectId,
			datasetItemId,
			datasetRunId,
			conversationId
		}, "Conversation does not exist, skipping relation creation");
		else throw error;
	}
}
/**
* Step: Mark invocation as completed
*/
async function markCompletedStep(params) {
	"use step";
	await Promise.all([markScheduledTriggerInvocationCompleted(runDbClient_default)({
		scopes: {
			tenantId: params.tenantId,
			projectId: params.projectId,
			agentId: params.agentId
		},
		scheduledTriggerId: params.datasetRunId,
		invocationId: params.scheduledTriggerInvocationId
	}), updateTriggerInvocationStatus(runDbClient_default)({
		scopes: {
			tenantId: params.tenantId,
			projectId: params.projectId,
			agentId: params.agentId
		},
		triggerId: params.datasetRunId,
		invocationId: params.scheduledTriggerInvocationId,
		data: { status: "success" }
	}).catch((err) => logger.warn({
		err,
		invocationId: params.scheduledTriggerInvocationId
	}, "Failed to update trigger invocation status to success"))]);
}
/**
* Step: Mark invocation as failed
*/
async function markFailedStep(params) {
	"use step";
	await Promise.all([markScheduledTriggerInvocationFailed(runDbClient_default)({
		scopes: {
			tenantId: params.tenantId,
			projectId: params.projectId,
			agentId: params.agentId
		},
		scheduledTriggerId: params.datasetRunId,
		invocationId: params.scheduledTriggerInvocationId
	}), updateTriggerInvocationStatus(runDbClient_default)({
		scopes: {
			tenantId: params.tenantId,
			projectId: params.projectId,
			agentId: params.agentId
		},
		triggerId: params.datasetRunId,
		invocationId: params.scheduledTriggerInvocationId,
		data: { status: "failed" }
	}).catch((err) => logger.warn({
		err,
		invocationId: params.scheduledTriggerInvocationId
	}, "Failed to update trigger invocation status to failed"))]);
}
/**
* Step: Mark invocation as running
*/
async function markRunningStep(params) {
	"use step";
	await markScheduledTriggerInvocationRunning(runDbClient_default)({
		scopes: {
			tenantId: params.tenantId,
			projectId: params.projectId,
			agentId: params.agentId
		},
		scheduledTriggerId: params.datasetRunId,
		invocationId: params.scheduledTriggerInvocationId
	});
}
/**
* Step: Execute a single evaluator on a conversation
*/
async function executeEvaluatorStep(tenantId, projectId, conversationId, evaluatorId, evaluationRunId, expectedOutput, branchRef) {
	"use step";
	const ref = getProjectScopedRef(tenantId, projectId, branchRef || "main");
	const resolvedRef = await resolveRef(manageDbClient_default)(ref);
	if (!resolvedRef) throw new Error("Failed to resolve ref");
	const evaluator = await withRef(manageDbPool_default, resolvedRef, (db) => getEvaluatorById(db)({ scopes: {
		tenantId,
		projectId,
		evaluatorId
	} }));
	if (!evaluator) {
		logger.warn({ evaluatorId }, "Evaluator not found");
		return null;
	}
	const conversation = await getConversation(runDbClient_default)({
		scopes: {
			tenantId,
			projectId
		},
		conversationId
	});
	if (!conversation) throw new Error(`Conversation not found: ${conversationId}`);
	const evalResult = await createEvaluationResult(runDbClient_default)({
		id: generateId(),
		tenantId,
		projectId,
		conversationId,
		evaluatorId: evaluator.id,
		evaluationRunId
	});
	try {
		const output = await new EvaluationService().executeEvaluation({
			conversation,
			evaluator,
			tenantId,
			projectId,
			expectedOutput
		});
		await updateEvaluationResult(runDbClient_default)({
			scopes: {
				tenantId,
				projectId,
				evaluationResultId: evalResult.id
			},
			data: { output }
		});
		logger.info({
			conversationId,
			evaluatorId: evaluator.id,
			resultId: evalResult.id
		}, "Evaluation completed");
		return evalResult.id;
	} catch (error) {
		const errorMessage = error instanceof Error ? error.message : "Unknown error";
		logger.error({
			error,
			conversationId,
			evaluatorId: evaluator.id
		}, "Evaluation failed");
		await updateEvaluationResult(runDbClient_default)({
			scopes: {
				tenantId,
				projectId,
				evaluationResultId: evalResult.id
			},
			data: { output: { text: `Evaluation failed: ${errorMessage}` } }
		});
		return evalResult.id;
	}
}
/**
* Step: Log workflow progress
*/
async function logStep(message, data) {
	"use step";
	logger.info(data, message);
}
/**
* Step: Filter evaluators by agent scoping.
* Evaluators with no agent relations pass through (project-wide).
* Evaluators scoped to specific agents are kept only if agentId matches.
*/
async function filterEvaluatorsByAgentStep(params) {
	"use step";
	const { tenantId, projectId, agentId, evaluatorIds } = params;
	const ref = getProjectScopedRef(tenantId, projectId, params.ref || "main");
	const resolvedRef = await resolveRef(manageDbClient_default)(ref);
	if (!resolvedRef) {
		logger.warn({
			tenantId,
			projectId,
			agentId,
			ref: params.ref
		}, "Failed to resolve ref for evaluator agent scoping — skipping all evaluators");
		return [];
	}
	const agentIdsMap = await withRef(manageDbPool_default, resolvedRef, (db) => getAgentIdsForEvaluators(db)({
		scopes: {
			tenantId,
			projectId
		},
		evaluatorIds
	}));
	const filtered = evaluatorIds.filter((evalId) => {
		const scopedAgents = agentIdsMap.get(evalId);
		if (!scopedAgents || scopedAgents.length === 0) return true;
		return scopedAgents.includes(agentId);
	});
	if (filtered.length < evaluatorIds.length) logger.info({
		agentId,
		originalCount: evaluatorIds.length,
		filteredCount: filtered.length,
		excluded: evaluatorIds.filter((id) => !filtered.includes(id))
	}, "Filtered evaluators by agent scoping in dataset run");
	return filtered;
}
/**
* Main workflow function - processes a single dataset item.
* Calls executeAgentAsync directly for agent execution.
* Optionally runs evaluators on the resulting conversation.
*/
async function _runDatasetItemWorkflow(payload) {
	"use workflow";
	const { tenantId, projectId, agentId, datasetItemId, datasetRunId, scheduledTriggerInvocationId, evaluatorIds, evaluationRunId } = payload;
	await logStep("Starting dataset item processing", {
		datasetItemId,
		datasetRunId,
		agentId,
		hasEvaluators: !!(evaluatorIds && evaluatorIds.length > 0)
	});
	await markRunningStep({
		tenantId,
		projectId,
		agentId,
		datasetRunId,
		scheduledTriggerInvocationId
	});
	const result = await executeDatasetItemStep(payload);
	if (result.success && result.conversationId) {
		await recordConversationStep({
			tenantId,
			projectId,
			agentId,
			datasetRunId,
			datasetItemId,
			conversationId: result.conversationId,
			scheduledTriggerInvocationId
		});
		await markCompletedStep({
			tenantId,
			projectId,
			agentId,
			datasetRunId,
			scheduledTriggerInvocationId
		});
		if (evaluatorIds && evaluatorIds.length > 0 && evaluationRunId) {
			const filteredEvaluatorIds = await filterEvaluatorsByAgentStep({
				tenantId,
				projectId,
				agentId,
				evaluatorIds,
				ref: payload.ref
			});
			for (const evaluatorId of filteredEvaluatorIds) await executeEvaluatorStep(tenantId, projectId, result.conversationId, evaluatorId, evaluationRunId, payload.datasetItemExpectedOutput, payload.ref);
		}
	} else {
		await logStep("Dataset item execution failed or no conversation created", {
			datasetItemId,
			datasetRunId,
			error: result.error
		});
		await markFailedStep({
			tenantId,
			projectId,
			agentId,
			datasetRunId,
			scheduledTriggerInvocationId
		});
	}
	return {
		success: result.success,
		datasetItemId,
		datasetRunId,
		conversationId: result.conversationId || null,
		error: result.error || null
	};
}
const runDatasetItemWorkflow = Object.assign(_runDatasetItemWorkflow, { workflowId: "workflow//./src/domains/evals/workflow/functions/runDatasetItem//_runDatasetItemWorkflow" });

//#endregion
export { runDatasetItemWorkflow };