import { getLogger as getLogger$1 } from "../../../../logger.js";
import { tracer } from "../../utils/tracer.js";
import { createDeniedToolResult } from "../../utils/tool-result.js";
import { pendingToolApprovalManager } from "../../session/PendingToolApprovalManager.js";
import { toolApprovalUiBus } from "../../session/ToolApprovalUiBus.js";
import { parseEmbeddedJson } from "@inkeep/agents-core";
import { SpanStatusCode, trace } from "@opentelemetry/api";

//#region src/domains/run/agents/tools/tool-approval.ts
const logger = getLogger$1("Agent");
async function waitForToolApproval(ctx, toolCallId, toolName, args, providerMetadata) {
	logger.info({
		toolName,
		toolCallId,
		args
	}, "Tool requires approval - waiting for user response");
	const currentSpan = trace.getActiveSpan();
	if (currentSpan) currentSpan.addEvent("tool.approval.requested", {
		"tool.name": toolName,
		"tool.callId": toolCallId,
		"subAgent.id": ctx.config.id
	});
	const baseSpanAttributes = {
		"tool.name": toolName,
		"tool.callId": toolCallId,
		"subAgent.id": ctx.config.id,
		"subAgent.name": ctx.config.name,
		...ctx.conversationId ? { "conversation.id": ctx.conversationId } : {}
	};
	if (ctx.durableWorkflowRunId) {
		const approvedToolCalls = ctx.approvedToolCalls;
		if (approvedToolCalls) {
			const queue = approvedToolCalls[toolName];
			const preApproved = queue?.shift();
			if (queue?.length === 0) delete approvedToolCalls[toolName];
			if (preApproved !== void 0) {
				if (!preApproved.approved) return {
					approved: false,
					deniedResult: tracer.startActiveSpan("tool.approval_denied", { attributes: {
						...baseSpanAttributes,
						"tool.approval.reason": preApproved.reason
					} }, (denialSpan) => {
						logger.info({
							toolName,
							toolCallId,
							reason: preApproved.reason
						}, "Tool execution denied (durable pre-approved decision)");
						denialSpan.setStatus({ code: SpanStatusCode.OK });
						denialSpan.end();
						return createDeniedToolResult(toolCallId, preApproved.reason);
					})
				};
				tracer.startActiveSpan("tool.approval_approved", { attributes: baseSpanAttributes }, (approvedSpan) => {
					logger.info({
						toolName,
						toolCallId
					}, "Tool approved (durable pre-approved decision)");
					approvedSpan.setStatus({ code: SpanStatusCode.OK });
					approvedSpan.end();
				});
				return { approved: true };
			}
		}
		tracer.startActiveSpan("tool.approval_requested", { attributes: baseSpanAttributes }, (requestSpan) => {
			requestSpan.setStatus({ code: SpanStatusCode.OK });
			requestSpan.end();
		});
		const streamHelper$1 = ctx.isDelegatedAgent ? void 0 : ctx.streamHelper;
		if (streamHelper$1) await streamHelper$1.writeToolApprovalRequest({
			approvalId: `aitxt-${toolCallId}`,
			toolCallId,
			toolName,
			input: args
		});
		else if (ctx.isDelegatedAgent) {
			const currentStreamRequestId = ctx.streamRequestId ?? "";
			if (currentStreamRequestId) await toolApprovalUiBus.publish(currentStreamRequestId, {
				type: "approval-needed",
				toolCallId,
				toolName,
				input: args,
				providerMetadata,
				approvalId: `aitxt-${toolCallId}`
			});
		}
		ctx.pendingDurableApproval = {
			toolCallId,
			toolName,
			args
		};
		return { approved: "pending" };
	}
	tracer.startActiveSpan("tool.approval_requested", { attributes: baseSpanAttributes }, (requestSpan) => {
		requestSpan.setStatus({ code: SpanStatusCode.OK });
		requestSpan.end();
	});
	const streamHelper = ctx.isDelegatedAgent ? void 0 : ctx.streamHelper;
	if (streamHelper) await streamHelper.writeToolApprovalRequest({
		approvalId: `aitxt-${toolCallId}`,
		toolCallId,
		toolName,
		input: args
	});
	else if (ctx.isDelegatedAgent) {
		const currentStreamRequestId = ctx.streamRequestId ?? "";
		if (currentStreamRequestId) await toolApprovalUiBus.publish(currentStreamRequestId, {
			type: "approval-needed",
			toolCallId,
			toolName,
			input: args,
			providerMetadata,
			approvalId: `aitxt-${toolCallId}`
		});
	}
	const approvalResult = await pendingToolApprovalManager.waitForApproval(toolCallId, toolName, args, ctx.conversationId || "unknown", ctx.config.id);
	if (!approvalResult.approved) {
		if (!streamHelper && ctx.isDelegatedAgent) {
			const currentStreamRequestId = ctx.streamRequestId ?? "";
			if (currentStreamRequestId) await toolApprovalUiBus.publish(currentStreamRequestId, {
				type: "approval-resolved",
				toolCallId,
				approved: false,
				reason: approvalResult.reason
			});
		}
		return {
			approved: false,
			deniedResult: tracer.startActiveSpan("tool.approval_denied", { attributes: {
				...baseSpanAttributes,
				"tool.approval.reason": approvalResult.reason
			} }, (denialSpan) => {
				logger.info({
					toolName,
					toolCallId,
					reason: approvalResult.reason
				}, "Tool execution denied by user");
				denialSpan.setStatus({ code: SpanStatusCode.OK });
				denialSpan.end();
				return createDeniedToolResult(toolCallId, approvalResult.reason);
			})
		};
	}
	tracer.startActiveSpan("tool.approval_approved", { attributes: baseSpanAttributes }, (approvedSpan) => {
		logger.info({
			toolName,
			toolCallId
		}, "Tool approved, continuing with execution");
		approvedSpan.setStatus({ code: SpanStatusCode.OK });
		approvedSpan.end();
	});
	if (!streamHelper && ctx.isDelegatedAgent) {
		const currentStreamRequestId = ctx.streamRequestId ?? "";
		if (currentStreamRequestId) await toolApprovalUiBus.publish(currentStreamRequestId, {
			type: "approval-resolved",
			toolCallId,
			approved: true
		});
	}
	return { approved: true };
}
function recordDenial(ctx, toolName, toolCallId, reason) {
	ctx.taskDenialRedirects.push({
		toolName,
		toolCallId,
		reason: reason ?? "Tool call was denied by the user."
	});
}
async function parseAndCheckApproval(ctx, toolName, toolCallId, args, providerMetadata, needsApproval) {
	let processedArgs;
	try {
		processedArgs = parseEmbeddedJson(args);
		if (JSON.stringify(args) !== JSON.stringify(processedArgs)) logger.warn({
			toolName,
			toolCallId
		}, "Fixed stringified JSON parameters (indicates schema ambiguity)");
	} catch (error) {
		logger.warn({
			toolName,
			toolCallId,
			error: error.message
		}, "Failed to parse embedded JSON, using original args");
		processedArgs = args;
	}
	if (needsApproval) {
		const approval = await waitForToolApproval(ctx, toolCallId, toolName, args, providerMetadata);
		if (approval.approved === "pending") return {
			args: processedArgs,
			denied: false,
			pendingApproval: true
		};
		if (!approval.approved) {
			const deniedResult = approval.deniedResult;
			recordDenial(ctx, toolName, toolCallId, deniedResult?.reason);
			return {
				args: processedArgs,
				denied: true,
				result: approval.deniedResult
			};
		}
	}
	return {
		args: processedArgs,
		denied: false
	};
}

//#endregion
export { parseAndCheckApproval, recordDenial, waitForToolApproval };