import manageDbPool_default from "../../../../data/db/manageDbPool.js";
import { getLogger as getLogger$1 } from "../../../../logger.js";
import { FUNCTION_TOOL_EXECUTION_TIMEOUT_MS_DEFAULT, FUNCTION_TOOL_SANDBOX_VCPUS_DEFAULT } from "../../constants/execution-limits/index.js";
import { toolSessionManager } from "../services/ToolSessionManager.js";
import { wrapToolWithStreaming } from "./tool-wrapper.js";
import { enhanceToolResultWithStructureHints } from "../generation/tool-result.js";
import { parseAndCheckApproval } from "./tool-approval.js";
import { z } from "@hono/zod-openapi";
import { getFunctionToolsForSubAgent, withRef } from "@inkeep/agents-core";
import { tool } from "ai";

//#region src/domains/run/agents/tools/function-tools.ts
const logger = getLogger$1("Agent");
async function getFunctionTools(ctx, sessionId, streamRequestId) {
	const functionTools = {};
	const project = ctx.executionContext.project;
	try {
		const withRefStart = Date.now();
		const functionToolsForAgent = await withRef(manageDbPool_default, ctx.executionContext.resolvedRef, async (db) => {
			return await getFunctionToolsForSubAgent(db)({
				scopes: {
					tenantId: ctx.config.tenantId,
					projectId: ctx.config.projectId,
					agentId: ctx.config.agentId
				},
				subAgentId: ctx.config.id
			});
		});
		const withRefMs = Date.now() - withRefStart;
		if (withRefMs > 5e3) logger.info({
			ref: ctx.executionContext.resolvedRef.name,
			withRefMs,
			subAgentId: ctx.config.id
		}, "Slow withRef in getFunctionTools");
		const functionToolsData = functionToolsForAgent.data ?? [];
		if (functionToolsData.length === 0) return functionTools;
		ctx.functionToolRelationshipIdByName = new Map(functionToolsData.flatMap((t) => {
			return t.relationshipId ? [[t.name, t.relationshipId]] : [];
		}));
		const { SandboxExecutorFactory } = await import("../../tools/SandboxExecutorFactory.js");
		const sandboxExecutor = sessionId ? SandboxExecutorFactory.getForSession(sessionId) : new SandboxExecutorFactory();
		for (const functionToolDef of functionToolsData) {
			const functionId = functionToolDef.functionId;
			if (!functionId) {
				logger.warn({ functionToolId: functionToolDef.id }, "Function tool missing functionId reference");
				continue;
			}
			const functionData = project.functions?.[functionId];
			if (!functionData) {
				logger.warn({
					functionId,
					functionToolId: functionToolDef.id
				}, "Function not found in functions table");
				continue;
			}
			const zodSchema = functionData.inputSchema ? z.fromJSONSchema(functionData.inputSchema) : z.string();
			const toolPolicies = functionToolDef.toolPolicies;
			const needsApproval = !!toolPolicies?.["*"]?.needsApproval || !!toolPolicies?.[functionToolDef.name]?.needsApproval;
			const aiTool = tool({
				description: functionToolDef.description || functionToolDef.name,
				inputSchema: zodSchema,
				execute: async (args, { toolCallId, providerMetadata }) => {
					const parsed = await parseAndCheckApproval(ctx, functionToolDef.name, toolCallId, args, providerMetadata, needsApproval);
					if (parsed.denied) return parsed.result;
					if (parsed.pendingApproval) return null;
					const finalArgs = parsed.args;
					logger.debug({
						toolName: functionToolDef.name,
						toolCallId,
						args: finalArgs
					}, "Function Tool Called");
					try {
						const defaultSandboxConfig = {
							provider: "native",
							runtime: "node22",
							timeout: FUNCTION_TOOL_EXECUTION_TIMEOUT_MS_DEFAULT,
							vcpus: FUNCTION_TOOL_SANDBOX_VCPUS_DEFAULT
						};
						const result = await sandboxExecutor.executeFunctionTool(functionToolDef.id, finalArgs, {
							description: functionToolDef.description || functionToolDef.name,
							inputSchema: functionData.inputSchema || {},
							executeCode: functionData.executeCode,
							dependencies: functionData.dependencies || {},
							sandboxConfig: ctx.config.sandboxConfig || defaultSandboxConfig
						});
						toolSessionManager.recordToolResult(sessionId || "", {
							toolCallId,
							toolName: functionToolDef.name,
							args: finalArgs,
							result,
							timestamp: Date.now()
						});
						const r = result;
						return enhanceToolResultWithStructureHints(ctx, r?.type === "text" && typeof r?.value === "string" ? { text: r.value } : result, toolCallId);
					} catch (error) {
						logger.error({
							toolName: functionToolDef.name,
							toolCallId,
							error: error instanceof Error ? error.message : String(error)
						}, "Function tool execution failed");
						throw error;
					}
				}
			});
			functionTools[functionToolDef.name] = wrapToolWithStreaming(ctx, functionToolDef.name, aiTool, streamRequestId || "", "tool", { needsApproval });
		}
	} catch (error) {
		logger.error({ error }, "Failed to load function tools from database");
	}
	return functionTools;
}

//#endregion
export { getFunctionTools };