import { agents, artifactComponents, dataComponents, functionTools, projects, subAgentArtifactComponents, subAgentDataComponents, subAgentFunctionToolRelations, subAgentToolRelations, subAgents, tools } from "../../db/manage/manage-schema.js";
import { getLogger } from "../../utils/logger.js";
import { createAgentsRunDatabaseClient } from "../../db/runtime/runtime-client.js";
import { generateId } from "../../utils/conversations.js";
import { getActiveBranch } from "../../dolt/schema-sync.js";
import { agentScopedWhere, projectScopedWhere, subAgentScopedWhere, tenantScopedWhere } from "./scope-helpers.js";
import { getProjectMainBranchName } from "./projectLifecycle.js";
import { cascadeDeleteByAgent } from "../runtime/cascade-delete.js";
import { getContextConfigById } from "./contextConfigs.js";
import { getExternalAgent } from "./externalAgents.js";
import { getFunction } from "./functions.js";
import { listFunctionTools } from "./functionTools.js";
import { getSkillsForSubAgents } from "./skills.js";
import { getSubAgentExternalAgentRelationsByAgent } from "./subAgentExternalAgentRelations.js";
import { getAgentRelations, getAgentRelationsByAgent } from "./subAgentRelations.js";
import { getSubAgentById } from "./subAgents.js";
import { getSubAgentTeamAgentRelationsByAgent } from "./subAgentTeamAgentRelations.js";
import { listTools } from "./tools.js";
import { getTriggerUsersBatch, listTriggers } from "./triggers.js";
import { and, count, desc, eq, inArray, sql } from "drizzle-orm";

//#region src/data-access/manage/agents.ts
const getAgentById = (db) => async (params) => {
	return await db.query.agents.findFirst({ where: and(projectScopedWhere(agents, params.scopes), eq(agents.id, params.scopes.agentId)) }) ?? null;
};
const getAgentWithDefaultSubAgent = (db) => async (params) => {
	return await db.query.agents.findFirst({
		where: and(projectScopedWhere(agents, params.scopes), eq(agents.id, params.scopes.agentId)),
		with: { defaultSubAgent: true }
	}) ?? null;
};
const listAgents = (db) => async (params) => {
	return await db.query.agents.findMany({ where: projectScopedWhere(agents, params.scopes) });
};
const listAgentsPaginated = (db) => async (params) => {
	const page = params.pagination?.page || 1;
	const limit = Math.min(params.pagination?.limit || 10, 100);
	const offset = (page - 1) * limit;
	const whereClause = projectScopedWhere(agents, params.scopes);
	const query = db.select().from(agents).where(whereClause).limit(limit).offset(offset).orderBy(desc(agents.createdAt));
	const [data, totalResult] = await Promise.all([query, db.select({ count: count() }).from(agents).where(whereClause)]);
	const total = totalResult[0]?.count || 0;
	return {
		data,
		pagination: {
			page,
			limit,
			total,
			pages: Math.ceil(total / limit)
		}
	};
};
const agentsLogger = getLogger("agents-data-access");
/**
* List agents across multiple project main branches for a tenant.
*
* Uses Dolt AS OF queries against each project's main branch without checkout.
*
* @param db - Database client
* @param params - Tenant and project IDs
*/
async function listAgentsAcrossProjectMainBranches(db, params) {
	const { tenantId, projectIds } = params;
	const results = await Promise.allSettled(projectIds.map(async (projectId) => {
		const branchName = getProjectMainBranchName(tenantId, projectId);
		return (await db.execute(sql`
          SELECT id as "agentId", name as "agentName", project_id as "projectId"
          FROM ${sql.raw(`agent AS OF '${branchName}'`)}
          WHERE tenant_id = ${tenantId} AND project_id = ${projectId}
          ORDER BY name
        `)).rows;
	}));
	const allAgents = [];
	for (let i = 0; i < results.length; i++) {
		const result = results[i];
		if (result.status === "fulfilled") allAgents.push(...result.value);
		else agentsLogger.warn({
			error: result.reason,
			projectId: projectIds[i]
		}, "Failed to fetch agents for project, skipping");
	}
	return allAgents;
}
const createAgent = (db) => async (data) => {
	const now = (/* @__PURE__ */ new Date()).toISOString();
	const insertData = {
		...data,
		createdAt: now,
		updatedAt: now,
		executionMode: data.executionMode ?? "classic",
		...data.description !== void 0 && { description: data.description },
		...data.contextConfigId !== void 0 && { contextConfigId: data.contextConfigId },
		...data.models !== void 0 && { models: data.models },
		...data.statusUpdates !== void 0 && { statusUpdates: data.statusUpdates },
		...data.prompt !== void 0 && { prompt: data.prompt },
		...data.stopWhen !== void 0 && { stopWhen: data.stopWhen }
	};
	return (await db.insert(agents).values(insertData).returning())[0];
};
const updateAgent = (db) => async (params) => {
	const data = params.data;
	const updateData = {
		...data,
		updatedAt: (/* @__PURE__ */ new Date()).toISOString()
	};
	if (data.models !== void 0) {
		if (!data.models || !data.models.base?.model && !data.models.structuredOutput?.model && !data.models.summarizer?.model && !data.models.base?.providerOptions && !data.models.structuredOutput?.providerOptions && !data.models.summarizer?.providerOptions) updateData.models = null;
	}
	if (data.statusUpdates !== void 0) {
		if (!data.statusUpdates) updateData.statusUpdates = null;
	}
	if (data.contextConfigId !== void 0 && !data.contextConfigId) updateData.contextConfigId = null;
	if (data.prompt !== void 0 && !data.prompt) updateData.prompt = null;
	if (data.stopWhen !== void 0 && !data.stopWhen) updateData.stopWhen = null;
	return (await db.update(agents).set(updateData).where(and(projectScopedWhere(agents, params.scopes), eq(agents.id, params.scopes.agentId))).returning())[0] ?? null;
};
const deleteAgent = (db) => async (params) => {
	const { agentId } = params.scopes;
	try {
		const currentBranch = await getActiveBranch(db)();
		const subAgentIds = (await db.query.subAgents.findMany({ where: agentScopedWhere(subAgents, params.scopes) })).map((sa) => sa.id);
		await cascadeDeleteByAgent(createAgentsRunDatabaseClient())({
			scopes: params.scopes,
			fullBranchName: currentBranch,
			subAgentIds
		});
	} catch (error) {
		agentsLogger.debug({
			error,
			agentId
		}, "Skipping runtime cascade delete - active_branch() not available");
	}
	return (await db.delete(agents).where(and(projectScopedWhere(agents, params.scopes), eq(agents.id, params.scopes.agentId))).returning()).length > 0;
};
/**
* Helper function to fetch component relationships using efficient joins
*/
const fetchComponentRelationships = (db) => async (scopes, subAgentIds, config) => {
	const componentsObject = {};
	if (subAgentIds.length > 0) {
		const results = await db.select(config.selectFields).from(config.relationTable).innerJoin(config.componentTable, eq(config.relationIdField, config.componentIdField)).where(and(agentScopedWhere(config.relationTable, scopes), inArray(config.subAgentIdField, subAgentIds)));
		for (const component of results) componentsObject[component.id] = component;
	}
	return componentsObject;
};
const getAgentSubAgentInfos = (db) => async ({ scopes: { tenantId, projectId }, agentId, subAgentId }) => {
	if (!await getAgentById(db)({ scopes: {
		tenantId,
		projectId,
		agentId
	} })) throw new Error(`Agent with ID ${agentId} not found for tenant ${tenantId}`);
	const targetSubAgentIds = (await getAgentRelations(db)({ scopes: {
		tenantId,
		projectId,
		agentId,
		subAgentId
	} })).map((relation) => relation.targetSubAgentId).filter((id) => id !== null);
	if (targetSubAgentIds.length === 0) return [];
	return (await Promise.all(targetSubAgentIds.map(async (subAgentId$1) => {
		const agent = await getSubAgentById(db)({
			scopes: {
				tenantId,
				projectId,
				agentId
			},
			subAgentId: subAgentId$1
		});
		return agent ? {
			id: agent.id,
			name: agent.name,
			description: agent.description
		} : null;
	}))).filter((agent) => agent !== null);
};
const getFullAgentDefinitionInternal = (db) => async ({ scopes: { tenantId, projectId, agentId }, includeRelationIds = false }) => {
	const agentScope = {
		tenantId,
		projectId,
		agentId
	};
	const agent = await getAgentById(db)({ scopes: agentScope });
	if (!agent) return null;
	const agentRelations = await getAgentRelationsByAgent(db)({ scopes: agentScope });
	const agentSubAgents = await db.query.subAgents.findMany({ where: agentScopedWhere(subAgents, agentScope) });
	const subAgentIds = agentSubAgents.map((subAgent) => subAgent.id);
	const externalAgentRelations = await getSubAgentExternalAgentRelationsByAgent(db)({ scopes: {
		tenantId,
		projectId,
		agentId
	} });
	const teamAgentRelations = await getSubAgentTeamAgentRelationsByAgent(db)({ scopes: {
		tenantId,
		projectId,
		agentId
	} });
	const teamAgentSubAgentIds = /* @__PURE__ */ new Set();
	for (const relation of teamAgentRelations) teamAgentSubAgentIds.add(relation.targetAgentId);
	const externalSubAgentIds = /* @__PURE__ */ new Set();
	for (const relation of externalAgentRelations) externalSubAgentIds.add(relation.externalAgentId);
	const subAgentSkillsList = await getSkillsForSubAgents(db)({
		scopes: {
			tenantId,
			projectId,
			agentId
		},
		subAgentIds
	});
	const skillsBySubAgent = {};
	for (const skill of subAgentSkillsList) {
		skillsBySubAgent[skill.subAgentId] ??= [];
		skillsBySubAgent[skill.subAgentId].push({
			id: skill.id,
			name: skill.name,
			description: skill.description,
			content: skill.content,
			metadata: skill.metadata,
			index: skill.index,
			alwaysLoaded: skill.alwaysLoaded,
			subAgentSkillId: skill.subAgentSkillId,
			subAgentId: skill.subAgentId,
			createdAt: skill.createdAt,
			updatedAt: skill.updatedAt
		});
	}
	const processedSubAgents = await Promise.all(agentSubAgents.map(async (agent$1) => {
		if (!agent$1) return null;
		const subAgentScope = {
			tenantId,
			projectId,
			agentId,
			subAgentId: agent$1.id
		};
		const subAgentRelationsList = agentRelations.filter((relation) => relation.sourceSubAgentId === agent$1.id);
		const canTransferTo = includeRelationIds ? subAgentRelationsList.filter((rel) => (rel.relationType === "transfer" || rel.relationType === "transfer_to") && rel.targetSubAgentId !== null).map((rel) => ({
			subAgentId: rel.targetSubAgentId,
			subAgentSubAgentRelationId: rel.id
		})) : subAgentRelationsList.filter((rel) => rel.relationType === "transfer" || rel.relationType === "transfer_to").map((rel) => rel.targetSubAgentId).filter((id) => id !== null);
		const canDelegateToInternal = includeRelationIds ? subAgentRelationsList.filter((rel) => (rel.relationType === "delegate" || rel.relationType === "delegate_to") && rel.targetSubAgentId !== null).map((rel) => ({
			subAgentId: rel.targetSubAgentId,
			subAgentSubAgentRelationId: rel.id
		})) : subAgentRelationsList.filter((rel) => rel.relationType === "delegate" || rel.relationType === "delegate_to").map((rel) => rel.targetSubAgentId).filter((id) => id !== null);
		const canDelegateToExternal = externalAgentRelations.filter((rel) => rel.subAgentId === agent$1.id).map((rel) => ({
			externalAgentId: rel.externalAgentId,
			subAgentExternalAgentRelationId: rel.id,
			headers: rel.headers
		}));
		const canDelegateToTeam = teamAgentRelations.filter((rel) => rel.subAgentId === agent$1.id).map((rel) => ({
			agentId: rel.targetAgentId,
			subAgentTeamAgentRelationId: rel.id,
			headers: rel.headers
		}));
		const canDelegateTo = [
			...canDelegateToInternal,
			...canDelegateToExternal,
			...canDelegateToTeam
		];
		const subAgentTools = await db.select({
			id: tools.id,
			name: tools.name,
			config: tools.config,
			createdAt: tools.createdAt,
			updatedAt: tools.updatedAt,
			capabilities: tools.capabilities,
			lastError: tools.lastError,
			credentialReferenceId: tools.credentialReferenceId,
			tenantId: tools.tenantId,
			projectId: tools.projectId,
			imageUrl: tools.imageUrl,
			selectedTools: subAgentToolRelations.selectedTools,
			headers: subAgentToolRelations.headers,
			toolPolicies: subAgentToolRelations.toolPolicies,
			agentToolRelationId: subAgentToolRelations.id
		}).from(subAgentToolRelations).innerJoin(tools, and(eq(subAgentToolRelations.toolId, tools.id), eq(subAgentToolRelations.tenantId, tools.tenantId), eq(subAgentToolRelations.projectId, tools.projectId))).where(subAgentScopedWhere(subAgentToolRelations, subAgentScope));
		const agentFunctionTools = await db.select({
			id: functionTools.id,
			name: functionTools.name,
			description: functionTools.description,
			functionId: functionTools.functionId,
			createdAt: functionTools.createdAt,
			updatedAt: functionTools.updatedAt,
			tenantId: functionTools.tenantId,
			projectId: functionTools.projectId,
			agentId: functionTools.agentId,
			agentToolRelationId: subAgentFunctionToolRelations.id,
			toolPolicies: subAgentFunctionToolRelations.toolPolicies
		}).from(subAgentFunctionToolRelations).innerJoin(functionTools, and(eq(subAgentFunctionToolRelations.functionToolId, functionTools.id), eq(subAgentFunctionToolRelations.tenantId, functionTools.tenantId), eq(subAgentFunctionToolRelations.projectId, functionTools.projectId), eq(subAgentFunctionToolRelations.agentId, functionTools.agentId))).where(subAgentScopedWhere(subAgentFunctionToolRelations, subAgentScope));
		const agentDataComponentIds = (await db.query.subAgentDataComponents.findMany({ where: subAgentScopedWhere(subAgentDataComponents, subAgentScope) })).map((rel) => rel.dataComponentId);
		const agentArtifactComponentIds = (await db.query.subAgentArtifactComponents.findMany({ where: subAgentScopedWhere(subAgentArtifactComponents, subAgentScope) })).map((rel) => rel.artifactComponentId);
		const mcpToolCanUse = subAgentTools.map((tool) => ({
			agentToolRelationId: tool.agentToolRelationId,
			toolId: tool.id,
			toolSelection: tool.selectedTools || null,
			headers: tool.headers || null,
			toolPolicies: tool.toolPolicies || null
		}));
		const functionToolCanUse = agentFunctionTools.map((tool) => ({
			agentToolRelationId: tool.agentToolRelationId,
			toolId: tool.id,
			toolSelection: null,
			headers: null,
			toolPolicies: tool.toolPolicies || null
		}));
		const canUse = [...mcpToolCanUse, ...functionToolCanUse];
		return {
			id: agent$1.id,
			name: agent$1.name,
			description: agent$1.description,
			prompt: agent$1.prompt,
			models: agent$1.models,
			stopWhen: agent$1.stopWhen,
			outputContract: agent$1.outputContract,
			canTransferTo,
			canDelegateTo,
			skills: skillsBySubAgent[agent$1.id] || [],
			dataComponents: agentDataComponentIds,
			artifactComponents: agentArtifactComponentIds,
			canUse
		};
	}));
	const externalAgents = await Promise.all(Array.from(externalSubAgentIds).map(async (externalAgentId) => {
		const subAgent = await getExternalAgent(db)({
			scopes: {
				tenantId,
				projectId
			},
			externalAgentId
		});
		if (!subAgent) return null;
		return {
			...subAgent,
			type: "external"
		};
	}));
	const teamAgents = await Promise.all(Array.from(teamAgentSubAgentIds).map(async (teamAgentId) => {
		const teamAgent = await getAgentById(db)({ scopes: {
			tenantId,
			projectId,
			agentId: teamAgentId
		} });
		if (!teamAgent) return null;
		return {
			id: teamAgent.id,
			name: teamAgent.name,
			description: teamAgent.description,
			type: "team"
		};
	}));
	const validSubAgents = processedSubAgents.filter((agent$1) => agent$1 !== null);
	const validExternalAgents = externalAgents.filter((agent$1) => agent$1 !== null);
	const validTeamAgents = teamAgents.filter((agent$1) => agent$1 !== null);
	const agentsObject = {};
	const externalAgentsObject = {};
	const teamAgentsObject = {};
	for (const subAgent of validSubAgents) agentsObject[subAgent.id] = subAgent;
	for (const externalAgent of validExternalAgents) externalAgentsObject[externalAgent.id] = {
		id: externalAgent.id,
		name: externalAgent.name,
		description: externalAgent.description,
		baseUrl: externalAgent.baseUrl,
		credentialReferenceId: externalAgent.credentialReferenceId,
		type: "external"
	};
	for (const teamAgent of validTeamAgents) teamAgentsObject[teamAgent.id] = teamAgent;
	let contextConfig = null;
	if (agent.contextConfigId) try {
		contextConfig = await getContextConfigById(db)({
			scopes: {
				tenantId,
				projectId,
				agentId
			},
			id: agent.contextConfigId
		});
	} catch (error) {
		agentsLogger.warn({
			error,
			contextConfigId: agent.contextConfigId
		}, "Failed to retrieve contextConfig");
	}
	try {
		await fetchComponentRelationships(db)(agentScope, subAgentIds, {
			relationTable: subAgentDataComponents,
			componentTable: dataComponents,
			relationIdField: subAgentDataComponents.dataComponentId,
			componentIdField: dataComponents.id,
			subAgentIdField: subAgentDataComponents.subAgentId,
			selectFields: {
				id: dataComponents.id,
				name: dataComponents.name,
				description: dataComponents.description,
				props: dataComponents.props
			}
		});
	} catch (error) {
		agentsLogger.warn({ error }, "Failed to retrieve dataComponents");
	}
	try {
		await fetchComponentRelationships(db)(agentScope, subAgentIds, {
			relationTable: subAgentArtifactComponents,
			componentTable: artifactComponents,
			relationIdField: subAgentArtifactComponents.artifactComponentId,
			componentIdField: artifactComponents.id,
			subAgentIdField: subAgentArtifactComponents.subAgentId,
			selectFields: {
				id: artifactComponents.id,
				name: artifactComponents.name,
				description: artifactComponents.description,
				props: artifactComponents.props
			}
		});
	} catch (error) {
		agentsLogger.warn({ error }, "Failed to retrieve artifactComponents");
	}
	const result = {
		id: agent.id,
		name: agent.name,
		description: agent.description,
		defaultSubAgentId: agent.defaultSubAgentId,
		subAgents: agentsObject,
		createdAt: agent.createdAt && !Number.isNaN(new Date(agent.createdAt).getTime()) ? new Date(agent.createdAt) : /* @__PURE__ */ new Date(),
		updatedAt: agent.updatedAt && !Number.isNaN(new Date(agent.updatedAt).getTime()) ? new Date(agent.updatedAt) : /* @__PURE__ */ new Date()
	};
	if (Object.keys(externalAgentsObject).length > 0) result.externalAgents = externalAgentsObject;
	if (Object.keys(teamAgentsObject).length > 0) result.teamAgents = teamAgentsObject;
	if (agent.models) result.models = agent.models;
	if (agent.statusUpdates) result.statusUpdates = agent.statusUpdates;
	if (agent.prompt) result.prompt = agent.prompt;
	if (agent.stopWhen) result.stopWhen = agent.stopWhen;
	if (agent.executionMode) result.executionMode = agent.executionMode;
	if (contextConfig) {
		const { id, headersSchema, contextVariables } = contextConfig;
		result.contextConfig = {
			id,
			headersSchema,
			contextVariables
		};
	}
	try {
		if (!db.query?.projects?.findFirst) return result;
		const project = await db.query.projects.findFirst({ where: and(tenantScopedWhere(projects, { tenantId }), eq(projects.id, projectId)) });
		if (project?.stopWhen) {
			const projectStopWhen = project.stopWhen;
			if (projectStopWhen.stepCountIs !== void 0) {
				const resultSubAgents = result.subAgents;
				if (resultSubAgents) {
					for (const [subAgentId, agentData] of Object.entries(resultSubAgents)) if (agentData && typeof agentData === "object" && !("baseUrl" in agentData)) {
						const agent$1 = agentData;
						if (!agent$1.stopWhen || agent$1.stopWhen.stepCountIs === void 0) {
							if (!agent$1.stopWhen) agent$1.stopWhen = {};
							agent$1.stopWhen.stepCountIs = projectStopWhen.stepCountIs;
							try {
								await db.update(subAgents).set({
									stopWhen: agent$1.stopWhen,
									updatedAt: (/* @__PURE__ */ new Date()).toISOString()
								}).where(and(agentScopedWhere(subAgents, {
									tenantId,
									projectId,
									agentId
								}), eq(subAgents.id, subAgentId)));
								result.subAgents[subAgentId] = {
									...result.subAgents[subAgentId],
									stopWhen: agent$1.stopWhen
								};
							} catch (dbError) {
								agentsLogger.warn({
									error: dbError,
									subAgentId
								}, "Failed to persist stopWhen for agent");
							}
						}
					}
				}
			}
		}
	} catch (error) {
		agentsLogger.warn({ error }, "Failed to apply agent stepCountIs inheritance");
	}
	try {
		const usedToolIds = new Set(Object.values(agentsObject).flatMap((a) => Array.isArray(a?.canUse) ? a.canUse : []).map((ref) => ref?.toolId).filter(Boolean));
		const toolsObject = {};
		if (usedToolIds.size > 0) {
			const { data } = await listTools(db)({
				scopes: {
					tenantId,
					projectId
				},
				pagination: {
					page: 1,
					limit: 1e3
				}
			});
			for (const tool of data) {
				if (!usedToolIds.has(tool.id)) continue;
				toolsObject[tool.id] = {
					id: tool.id,
					name: tool.name,
					description: tool.description,
					config: tool.config,
					credentialReferenceId: tool.credentialReferenceId,
					imageUrl: tool.imageUrl
				};
			}
		}
		result.tools = toolsObject;
		const functionToolsList = await listFunctionTools(db)({
			scopes: {
				tenantId,
				projectId,
				agentId
			},
			pagination: {
				page: 1,
				limit: 1e3
			}
		});
		const functionToolsObject = {};
		for (const functionTool of functionToolsList.data) functionToolsObject[functionTool.id] = {
			id: functionTool.id,
			name: functionTool.name,
			description: functionTool.description,
			functionId: functionTool.functionId
		};
		result.functionTools = functionToolsObject;
		const functionIds = /* @__PURE__ */ new Set();
		for (const functionTool of functionToolsList.data) if (functionTool.functionId) functionIds.add(functionTool.functionId);
		if (functionIds.size > 0) {
			const functions = (await Promise.all(Array.from(functionIds).map(async (functionId) => {
				const func = await getFunction(db)({
					functionId,
					scopes: {
						tenantId,
						projectId
					}
				});
				return func ? [functionId, {
					id: func.id,
					inputSchema: func.inputSchema,
					executeCode: func.executeCode,
					dependencies: func.dependencies
				}] : null;
			}))).filter((entry) => entry !== null);
			result.functions = Object.fromEntries(functions);
		}
	} catch (error) {
		agentsLogger.warn({ error }, "Failed to load tools/functions lookups");
	}
	try {
		const triggersList = await listTriggers(db)({ scopes: {
			tenantId,
			projectId,
			agentId
		} });
		agentsLogger.debug({
			agentId,
			count: triggersList.length
		}, "Fetched triggers for agent");
		if (triggersList.length > 0) {
			const triggerIds = triggersList.map((t) => t.id);
			const usersByTrigger = await getTriggerUsersBatch(db)({
				scopes: {
					tenantId,
					projectId,
					agentId
				},
				triggerIds
			});
			const triggersObject = {};
			for (const trigger of triggersList) triggersObject[trigger.id] = {
				id: trigger.id,
				name: trigger.name,
				description: trigger.description,
				enabled: trigger.enabled,
				inputSchema: trigger.inputSchema,
				outputTransform: trigger.outputTransform,
				messageTemplate: trigger.messageTemplate,
				authentication: trigger.authentication,
				signingSecretCredentialReferenceId: trigger.signingSecretCredentialReferenceId,
				signatureVerification: trigger.signatureVerification,
				dispatchDelayMs: trigger.dispatchDelayMs,
				runAsUserId: trigger.runAsUserId,
				runAsUserIds: usersByTrigger.get(trigger.id) ?? [],
				createdBy: trigger.createdBy
			};
			result.triggers = triggersObject;
			agentsLogger.debug({
				agentId,
				triggerIds: Object.keys(triggersObject)
			}, "Added triggers to result");
		}
	} catch (error) {
		agentsLogger.warn({ error }, "Failed to load triggers");
	}
	return result;
};
const getFullAgentDefinition = (db) => async ({ scopes }) => {
	return getFullAgentDefinitionInternal(db)({
		scopes,
		includeRelationIds: false
	});
};
const getFullAgentDefinitionWithRelationIds = (db) => async ({ scopes }) => {
	return getFullAgentDefinitionInternal(db)({
		scopes,
		includeRelationIds: true
	});
};
/**
* Upsert an agent (create if it doesn't exist, update if it does)
*/
const upsertAgent = (db) => async (params) => {
	const agentId = params.data.id || generateId();
	const scopes = {
		tenantId: params.data.tenantId,
		projectId: params.data.projectId,
		agentId
	};
	if (await getAgentById(db)({ scopes })) return await updateAgent(db)({
		scopes,
		data: {
			name: params.data.name,
			defaultSubAgentId: params.data.defaultSubAgentId,
			description: params.data.description,
			contextConfigId: params.data.contextConfigId,
			models: params.data.models,
			statusUpdates: params.data.statusUpdates
		}
	});
	return await createAgent(db)({
		...params.data,
		id: agentId
	});
};

//#endregion
export { createAgent, deleteAgent, fetchComponentRelationships, getAgentById, getAgentSubAgentInfos, getAgentWithDefaultSubAgent, getFullAgentDefinition, getFullAgentDefinitionWithRelationIds, listAgents, listAgentsAcrossProjectMainBranches, listAgentsPaginated, updateAgent, upsertAgent };