import { callLlmStep, executeToolStep, initializeTaskStep, markWorkflowCompleteStep, markWorkflowFailedStep, markWorkflowResumingStep, markWorkflowRunningStep, markWorkflowSuspendedStep } from "../steps/agentExecutionSteps.js";
import { defineHook, getWorkflowMetadata } from "workflow";

//#region src/domains/run/workflow/functions/agentExecution.ts
/**
* Hook for tool approval: external systems resume this to approve/deny a tool call.
* Token format: `tool-approval:${conversationId}:${workflowRunId}:${toolCallId}`
*/
const toolApprovalHook = defineHook();
async function _agentExecutionWorkflow(payload) {
	"use workflow";
	const { workflowRunId } = getWorkflowMetadata();
	await markWorkflowRunningStep({
		payload,
		workflowRunId
	});
	const { taskId, defaultSubAgentId, maxTransfers } = await initializeTaskStep({ payload });
	let currentSubAgentId = defaultSubAgentId;
	let iterations = 0;
	let approvalRound = 0;
	let isPostApproval = false;
	const denialRedirects = [];
	try {
		while (iterations < maxTransfers) {
			iterations++;
			const streamNamespace = approvalRound === 0 ? void 0 : `r${approvalRound}`;
			const llmResult = await callLlmStep({
				payload,
				currentSubAgentId,
				isFirstMessage: iterations === 1,
				workflowRunId,
				streamNamespace,
				taskId,
				isPostApproval,
				denialRedirects: denialRedirects.length > 0 ? denialRedirects : void 0
			});
			if (llmResult.type === "transfer") {
				currentSubAgentId = llmResult.targetSubAgentId;
				isPostApproval = false;
				continue;
			}
			if (llmResult.type === "tool_calls") {
				for (const toolCall of llmResult.toolCalls) {
					const continuationNs = `r${approvalRound + 1}`;
					await markWorkflowSuspendedStep({
						tenantId: payload.tenantId,
						projectId: payload.projectId,
						workflowRunId,
						continuationStreamNamespace: continuationNs
					});
					const hookToolCallId = llmResult.delegatedApproval?.toolCallId ?? toolCall.toolCallId;
					const token = `tool-approval:${payload.conversationId}:${workflowRunId}:${hookToolCallId}`;
					console.info("[agentExecution] Creating tool approval hook", {
						hookToolCallId,
						parentToolCallId: toolCall.toolCallId,
						isDelegated: !!llmResult.delegatedApproval,
						workflowRunId
					});
					const approvalResult = await toolApprovalHook.create({ token });
					approvalRound++;
					await markWorkflowResumingStep({
						tenantId: payload.tenantId,
						projectId: payload.projectId,
						workflowRunId
					});
					const toolResult = await executeToolStep({
						payload,
						currentSubAgentId,
						toolCallId: toolCall.toolCallId,
						toolName: toolCall.toolName,
						args: toolCall.args,
						workflowRunId,
						streamNamespace: `r${approvalRound}`,
						taskId,
						preApproved: approvalResult.approved,
						approvalReason: approvalResult.reason,
						...llmResult.delegatedApproval ? {
							delegatedApproval: llmResult.delegatedApproval,
							delegatedApprovalDecision: {
								approved: approvalResult.approved,
								reason: approvalResult.reason
							}
						} : {}
					});
					if (toolResult.type === "completed" && toolResult.denial) denialRedirects.push(toolResult.denial);
				}
				isPostApproval = true;
				continue;
			}
			break;
		}
		await markWorkflowCompleteStep({
			tenantId: payload.tenantId,
			projectId: payload.projectId,
			workflowRunId
		});
		return { success: true };
	} catch (error) {
		const message = error instanceof Error ? error.message : String(error);
		await markWorkflowFailedStep({
			tenantId: payload.tenantId,
			projectId: payload.projectId,
			workflowRunId,
			error: message
		});
		throw error;
	}
}
const agentExecutionWorkflow = Object.assign(_agentExecutionWorkflow, { workflowId: "workflow//./src/domains/run/workflow/functions/agentExecution//_agentExecutionWorkflow" });

//#endregion
export { agentExecutionWorkflow, toolApprovalHook };