import { projects, subAgentFunctionToolRelations, subAgentSkills, subAgentToolRelations, subAgents } from "../../db/manage/manage-schema.js";
import { validateAgentStructure, validateAndTypeAgentData } from "../../validation/agentFull.js";
import { getLogger } from "../../utils/logger.js";
import { deriveRelationId, generateId } from "../../utils/conversations.js";
import { agentScopedWhere, subAgentScopedWhere, tenantScopedWhere } from "./scope-helpers.js";
import { upsertContextConfig } from "./contextConfigs.js";
import { upsertFunction } from "./functions.js";
import { deleteFunctionTool, listFunctionTools, upsertFunctionTool, upsertSubAgentFunctionToolRelation } from "./functionTools.js";
import { upsertSubAgentSkill } from "./skills.js";
import { deleteSubAgentExternalAgentRelation, getSubAgentExternalAgentRelationsByAgent, upsertSubAgentExternalAgentRelation } from "./subAgentExternalAgentRelations.js";
import { createSubAgentRelation, deleteAgentRelationsByAgent, deleteAgentToolRelationByAgent, upsertSubAgentRelation } from "./subAgentRelations.js";
import { deleteSubAgent, listSubAgents, upsertSubAgent } from "./subAgents.js";
import { deleteSubAgentTeamAgentRelation, getSubAgentTeamAgentRelationsByAgent, upsertSubAgentTeamAgentRelation } from "./subAgentTeamAgentRelations.js";
import { upsertSubAgentToolRelation } from "./tools.js";
import { deleteTrigger, listTriggers, setTriggerUsers, upsertTrigger } from "./triggers.js";
import { deleteAgent, getAgentById, getFullAgentDefinition, getFullAgentDefinitionWithRelationIds, updateAgent, upsertAgent } from "./agents.js";
import { associateArtifactComponentWithAgent, deleteAgentArtifactComponentRelationByAgent, listArtifactComponents, upsertAgentArtifactComponentRelation } from "./artifactComponents.js";
import { associateDataComponentWithAgent, deleteAgentDataComponentRelationByAgent, listDataComponents, upsertAgentDataComponentRelation } from "./dataComponents.js";
import { and, eq, inArray, not } from "drizzle-orm";

//#region src/data-access/manage/agentFull.ts
const logger = getLogger("agentFull");
async function syncSubAgentSkills(db, scopes, subAgentsMap) {
	await db.delete(subAgentSkills).where(agentScopedWhere(subAgentSkills, scopes));
	const skillPromises = [];
	for (const [subAgentId, subAgentData] of Object.entries(subAgentsMap)) {
		if (!subAgentData.skills || subAgentData.skills.length === 0) continue;
		subAgentData.skills.forEach((skill) => {
			if (!skill.id) return;
			skillPromises.push(upsertSubAgentSkill(db)({
				scopes: {
					tenantId: scopes.tenantId,
					projectId: scopes.projectId,
					agentId: scopes.agentId,
					subAgentId
				},
				skillId: skill.id,
				index: skill.index,
				alwaysLoaded: skill.alwaysLoaded
			}));
		});
	}
	await Promise.all(skillPromises);
	logger.info({
		agentId: scopes.agentId,
		count: skillPromises.length
	}, "Synced sub-agent skills");
}
/**
* Apply execution limits inheritance from project to Agents and Sub Agents
*/
async function applyExecutionLimitsInheritance(db, scopes, agentData) {
	try {
		const project = await db.query.projects.findFirst({ where: and(tenantScopedWhere(projects, scopes), eq(projects.id, scopes.projectId)) });
		if (!project?.stopWhen) {
			logger.info({ projectId: scopes.projectId }, "No project stopWhen configuration found");
			return;
		}
		const projectStopWhen = project.stopWhen;
		logger.info({
			projectId: scopes.projectId,
			projectStopWhen
		}, "Found project stopWhen configuration");
		if (!agentData.stopWhen) agentData.stopWhen = {};
		if (agentData.stopWhen.transferCountIs === void 0 && projectStopWhen?.transferCountIs !== void 0) {
			agentData.stopWhen.transferCountIs = projectStopWhen.transferCountIs;
			logger.info({
				agentId: agentData.id,
				inheritedValue: projectStopWhen.transferCountIs
			}, "Agent inherited transferCountIs from project");
		}
		if (agentData.stopWhen.transferCountIs === void 0) {
			agentData.stopWhen.transferCountIs = 10;
			logger.info({
				agentId: agentData.id,
				defaultValue: 10
			}, "Agent set to default transferCountIs");
		}
		if (projectStopWhen?.stepCountIs !== void 0) {
			logger.info({
				projectId: scopes.projectId,
				stepCountIs: projectStopWhen.stepCountIs
			}, "Propagating stepCountIs to agents");
			for (const [subAgentId, subAgentData] of Object.entries(agentData.subAgents)) if (subAgentData.canTransferTo && Array.isArray(subAgentData.canTransferTo)) {
				const agent = agentData;
				if (!agent.stopWhen) agent.stopWhen = {};
				if (agent.stopWhen.stepCountIs === void 0) {
					agent.stopWhen.stepCountIs = projectStopWhen.stepCountIs;
					logger.info({
						subAgentId,
						inheritedValue: projectStopWhen.stepCountIs
					}, "Agent inherited stepCountIs from project");
				}
			}
		}
	} catch (error) {
		logger.error({
			projectId: scopes.projectId,
			error: error instanceof Error ? error.message : "Unknown error"
		}, "Failed to apply execution limits inheritance");
	}
}
async function loadComponentNameMaps(db, scopes, subAgentsMap) {
	if (!Object.values(subAgentsMap).some((s) => s?.outputContract != null)) return {
		componentNameById: /* @__PURE__ */ new Map(),
		artifactNameById: /* @__PURE__ */ new Map()
	};
	const [dataComps, artifactComps] = await Promise.all([listDataComponents(db)({ scopes }), listArtifactComponents(db)({ scopes })]);
	return {
		componentNameById: new Map(dataComps.map((c) => [c.id, c.name])),
		artifactNameById: new Map(artifactComps.map((c) => [c.id, c.name]))
	};
}
/**
* Drop require* entries that name a component/artifact the sub-agent no longer
* declares — a requirement must never outlive the component it points at, or it
* becomes an unsatisfiable contract. Returns null when no contract is set.
*/
function reconcileOutputContract(subAgent, componentNameById, artifactNameById) {
	const contract = subAgent.outputContract;
	if (!contract) return null;
	const declaredComponents = new Set((subAgent.dataComponents ?? []).map((id) => componentNameById.get(id)).filter((name) => Boolean(name)));
	const declaredArtifacts = new Set((subAgent.artifactComponents ?? []).map((id) => artifactNameById.get(id)).filter((name) => Boolean(name)));
	const reconciled = { ...contract };
	const requireComponent = contract.requireComponent?.filter((name) => declaredComponents.has(name));
	if (requireComponent && requireComponent.length > 0) reconciled.requireComponent = requireComponent;
	else delete reconciled.requireComponent;
	const requireArtifact = contract.requireArtifact?.filter((name) => declaredArtifacts.has(name));
	if (requireArtifact && requireArtifact.length > 0) reconciled.requireArtifact = requireArtifact;
	else delete reconciled.requireArtifact;
	return reconciled;
}
const createFullAgentServerSide = (db) => async (scopes, agentData) => {
	const { tenantId, projectId } = scopes;
	const typed = validateAndTypeAgentData(agentData);
	validateAgentStructure(typed);
	await applyExecutionLimitsInheritance(db, {
		tenantId,
		projectId
	}, typed);
	const { componentNameById, artifactNameById } = await loadComponentNameMaps(db, {
		tenantId,
		projectId
	}, typed.subAgents);
	try {
		logger.info("CredentialReferences are project-scoped - skipping credential reference creation in agent");
		logger.info("MCP Tools are project-scoped - skipping tool creation in agent");
		let finalAgentId;
		try {
			const agentId = typed.id || generateId();
			logger.info({ agentId }, "Creating agent metadata");
			const agent = await upsertAgent(db)({ data: {
				id: agentId,
				tenantId,
				projectId,
				name: typed.name,
				defaultSubAgentId: typed.defaultSubAgentId,
				description: typed.description,
				contextConfigId: void 0,
				models: typed.models,
				statusUpdates: typed.statusUpdates,
				prompt: typed.prompt,
				stopWhen: typed.stopWhen,
				executionMode: typed.executionMode
			} });
			if (!agent?.id) throw new Error("Failed to create agent: no ID returned");
			finalAgentId = agent.id;
			logger.info({ agentId: finalAgentId }, "Agent metadata created successfully");
		} catch (error) {
			logger.error({
				agentId: typed.id,
				error
			}, "Failed to create/update agent metadata");
			throw error;
		}
		let contextConfigId;
		if (typed.contextConfig) try {
			logger.info({ contextConfigId: typed.contextConfig.id }, "Processing context config");
			contextConfigId = (await upsertContextConfig(db)({ data: {
				...typed.contextConfig,
				agentId: finalAgentId,
				tenantId,
				projectId
			} })).id;
			logger.info({ contextConfigId }, "Context config processed successfully");
		} catch (error) {
			logger.error({
				contextConfigId: typed.contextConfig.id,
				error
			}, "Failed to create/update context config");
			throw error;
		}
		if (contextConfigId) try {
			logger.info({
				agentId: finalAgentId,
				contextConfigId
			}, "Updating agent with contextConfigId");
			await upsertAgent(db)({ data: {
				id: finalAgentId,
				tenantId,
				projectId,
				name: typed.name,
				defaultSubAgentId: typed.defaultSubAgentId,
				description: typed.description,
				contextConfigId,
				models: typed.models,
				statusUpdates: typed.statusUpdates,
				prompt: typed.prompt,
				stopWhen: typed.stopWhen,
				executionMode: typed.executionMode
			} });
			logger.info({
				agentId: finalAgentId,
				contextConfigId
			}, "Agent updated with contextConfigId successfully");
		} catch (error) {
			logger.error({
				agentId: finalAgentId,
				contextConfigId,
				error
			}, "Failed to update agent with contextConfigId");
			throw error;
		}
		logger.info("DataComponents are project-scoped - skipping dataComponent creation in agent");
		logger.info("ArtifactComponents are project-scoped - skipping artifactComponent creation in agent");
		if (typed.functions && Object.keys(typed.functions).length > 0) {
			logger.info({
				agentId: finalAgentId,
				functionCount: Object.keys(typed.functions).length
			}, "Creating functions for agent");
			const functionPromises = Object.entries(typed.functions).map(async ([functionId, functionData]) => {
				try {
					logger.info({
						agentId: finalAgentId,
						functionId
					}, "Creating function for agent");
					await upsertFunction(db)({
						data: {
							...functionData,
							id: functionId
						},
						scopes: {
							tenantId,
							projectId
						}
					});
					logger.info({
						agentId: finalAgentId,
						functionId
					}, "Function created successfully");
				} catch (error) {
					logger.error({
						agentId: finalAgentId,
						functionId,
						error
					}, "Failed to create function for agent");
					throw error;
				}
			});
			await Promise.all(functionPromises);
			logger.info({
				agentId: finalAgentId,
				functionCount: Object.keys(typed.functions).length
			}, "All functions created successfully");
		}
		if (typed.functionTools && Object.keys(typed.functionTools).length > 0) {
			logger.info({
				agentId: finalAgentId,
				functionToolCount: Object.keys(typed.functionTools).length
			}, "Creating function tools for agent");
			const functionToolPromises = Object.entries(typed.functionTools).map(async ([functionToolId, functionToolData]) => {
				try {
					logger.info({
						agentId: finalAgentId,
						functionToolId
					}, "Creating function tool in agent");
					await upsertFunctionTool(db)({
						data: {
							...functionToolData,
							id: functionToolId
						},
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						}
					});
					logger.info({
						agentId: finalAgentId,
						functionToolId
					}, "Function tool created successfully");
				} catch (error) {
					logger.error({
						agentId: finalAgentId,
						functionToolId,
						error
					}, "Failed to create function tool in agent");
					throw error;
				}
			});
			await Promise.all(functionToolPromises);
			logger.info({
				agentId: finalAgentId,
				functionToolCount: Object.keys(typed.functionTools).length
			}, "All function tools created successfully");
		}
		if (typed.triggers && Object.keys(typed.triggers).length > 0) {
			logger.info({
				agentId: finalAgentId,
				triggerCount: Object.keys(typed.triggers).length
			}, "Creating triggers for agent");
			const triggerPromises = Object.entries(typed.triggers).map(async ([triggerId, triggerData]) => {
				try {
					logger.info({
						agentId: finalAgentId,
						triggerId
					}, "Creating trigger in agent");
					const { runAsUserIds, ...triggerInsertData } = triggerData;
					await upsertTrigger(db)({
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						},
						data: {
							...triggerInsertData,
							id: triggerId,
							tenantId,
							projectId,
							agentId: finalAgentId
						}
					});
					if (runAsUserIds && runAsUserIds.length > 0) await setTriggerUsers(db)({
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						},
						triggerId,
						userIds: runAsUserIds
					});
					logger.info({
						agentId: finalAgentId,
						triggerId
					}, "Trigger created successfully");
				} catch (error) {
					logger.error({
						agentId: finalAgentId,
						triggerId,
						error
					}, "Failed to create trigger in agent");
					throw error;
				}
			});
			await Promise.all(triggerPromises);
			logger.info({
				agentId: finalAgentId,
				triggerCount: Object.keys(typed.triggers).length
			}, "All triggers created successfully");
		}
		const subAgentPromises = Object.entries(typed.subAgents).map(async ([subAgentId, agentData$1]) => {
			const subAgent = agentData$1;
			try {
				logger.info({ subAgentId }, "Processing sub-agent");
				await upsertSubAgent(db)({ data: {
					id: subAgentId,
					tenantId,
					projectId,
					agentId: finalAgentId,
					name: subAgent.name || "",
					description: subAgent.description || "",
					prompt: subAgent.prompt || "",
					conversationHistoryConfig: subAgent.conversationHistoryConfig,
					models: subAgent.models,
					stopWhen: subAgent.stopWhen,
					outputContract: reconcileOutputContract(subAgent, componentNameById, artifactNameById)
				} });
				logger.info({ subAgentId }, "Sub-agent processed successfully");
			} catch (error) {
				logger.error({
					subAgentId,
					error
				}, "Failed to create/update sub-agent");
				throw error;
			}
		});
		await Promise.all(subAgentPromises);
		const subAgentCount = Object.entries(typed.subAgents).length;
		logger.info({ subAgentCount }, "All sub-agents created/updated successfully");
		logger.info("External agents are project-scoped and managed at the project level.");
		const agentToolPromises = [];
		for (const [subAgentId, agentData$1] of Object.entries(typed.subAgents)) if (agentData$1.canUse && Array.isArray(agentData$1.canUse)) for (const canUseItem of agentData$1.canUse) agentToolPromises.push((async () => {
			try {
				const { toolId, toolSelection, headers, toolPolicies, agentToolRelationId } = canUseItem;
				const isFunctionTool = typed.functionTools && toolId in typed.functionTools;
				logger.info({
					subAgentId,
					toolId,
					hasFunctionTools: !!typed.functionTools,
					functionToolKeys: typed.functionTools ? Object.keys(typed.functionTools) : [],
					isFunctionTool
				}, "Processing canUse item");
				if (isFunctionTool) {
					logger.info({
						subAgentId,
						toolId
					}, "Processing agent-function tool relation");
					await upsertSubAgentFunctionToolRelation(db)({
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						},
						subAgentId,
						functionToolId: toolId,
						toolPolicies,
						relationId: agentToolRelationId
					});
					logger.info({
						subAgentId,
						toolId
					}, "Agent-function tool relation processed successfully");
				} else {
					logger.info({
						subAgentId,
						toolId
					}, "Processing agent-MCP tool relation");
					await upsertSubAgentToolRelation(db)({
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						},
						subAgentId,
						toolId,
						selectedTools: toolSelection,
						headers,
						toolPolicies,
						relationId: agentToolRelationId
					});
					logger.info({
						subAgentId,
						toolId
					}, "Agent-MCP tool relation processed successfully");
				}
			} catch (error) {
				logger.error({
					subAgentId,
					toolId: canUseItem.toolId,
					error
				}, "Failed to create agent-tool relation");
			}
		})());
		await Promise.all(agentToolPromises);
		logger.info({ agentToolCount: Object.keys(typed.subAgents).length }, "All agent-tool relations created");
		const agentDataComponentPromises = [];
		for (const [subAgentId, agentData$1] of Object.entries(typed.subAgents)) if (agentData$1.dataComponents) for (const dataComponentId of agentData$1.dataComponents) agentDataComponentPromises.push((async () => {
			try {
				logger.info({
					subAgentId,
					dataComponentId
				}, "Processing agent-data component relation");
				await upsertAgentDataComponentRelation(db)({
					scopes: {
						tenantId,
						projectId,
						agentId: finalAgentId,
						subAgentId
					},
					dataComponentId
				});
				logger.info({
					subAgentId,
					dataComponentId
				}, "Agent-data component relation processed successfully");
			} catch (error) {
				logger.error({
					subAgentId,
					dataComponentId,
					error
				}, "Failed to create agent-data component relation");
			}
		})());
		await Promise.all(agentDataComponentPromises);
		logger.info("All agent-data component relations created");
		const agentArtifactComponentPromises = [];
		for (const [subAgentId, agentData$1] of Object.entries(typed.subAgents)) if (agentData$1.artifactComponents) for (const artifactComponentId of agentData$1.artifactComponents) agentArtifactComponentPromises.push((async () => {
			try {
				logger.info({
					subAgentId,
					artifactComponentId
				}, "Processing agent-artifact component relation");
				await upsertAgentArtifactComponentRelation(db)({
					scopes: {
						tenantId,
						projectId,
						agentId: finalAgentId,
						subAgentId
					},
					artifactComponentId
				});
				logger.info({
					subAgentId,
					artifactComponentId
				}, "Agent-artifact component relation processed successfully");
			} catch (error) {
				logger.error({
					subAgentId,
					artifactComponentId,
					error
				}, "Failed to create agent-artifact component relation");
			}
		})());
		await Promise.all(agentArtifactComponentPromises);
		logger.info("All agent-artifact component relations created");
		const subAgentRelationPromises = [];
		const subAgentExternalAgentRelationPromises = [];
		const subAgentTeamAgentRelationPromises = [];
		for (const [subAgentId, agentData$1] of Object.entries(typed.subAgents)) if (agentData$1.canTransferTo) {
			for (const targetSubAgentId of agentData$1.canTransferTo) subAgentRelationPromises.push((async () => {
				try {
					logger.info({
						subAgentId,
						targetSubAgentId,
						type: "transfer"
					}, "Processing agent transfer relation");
					await upsertSubAgentRelation(db)({
						id: deriveRelationId(tenantId, projectId, finalAgentId, subAgentId, targetSubAgentId, "transfer"),
						tenantId,
						projectId,
						agentId: finalAgentId,
						sourceSubAgentId: subAgentId,
						targetSubAgentId,
						relationType: "transfer"
					});
					logger.info({
						subAgentId,
						targetSubAgentId,
						type: "transfer"
					}, "Agent transfer relation processed successfully");
				} catch (error) {
					logger.error({
						subAgentId,
						targetSubAgentId,
						type: "transfer",
						error
					}, "Failed to create transfer relation");
				}
			})());
			if (agentData$1.canDelegateTo) {
				for (const targetItem of agentData$1.canDelegateTo) if (typeof targetItem === "string") subAgentRelationPromises.push((async () => {
					try {
						logger.info({
							subAgentId,
							targetSubAgentId: targetItem,
							type: "delegate"
						}, "Processing sub-agent delegation relation");
						await upsertSubAgentRelation(db)({
							id: deriveRelationId(tenantId, projectId, finalAgentId, subAgentId, targetItem, "delegate"),
							tenantId,
							projectId,
							agentId: finalAgentId,
							sourceSubAgentId: subAgentId,
							targetSubAgentId: targetItem,
							relationType: "delegate"
						});
						logger.info({
							subAgentId,
							targetSubAgentId: targetItem,
							type: "delegate"
						}, "Sub-agent delegation relation processed successfully");
					} catch (error) {
						logger.error({
							subAgentId,
							targetSubAgentId: targetItem,
							type: "delegate",
							error
						}, "Failed to create sub-agent delegation relation");
					}
				})());
				else if (typeof targetItem === "object" && "externalAgentId" in targetItem) subAgentExternalAgentRelationPromises.push((async () => {
					try {
						await upsertSubAgentExternalAgentRelation(db)({
							scopes: {
								tenantId,
								projectId,
								agentId: finalAgentId,
								subAgentId
							},
							relationId: targetItem.subAgentExternalAgentRelationId,
							data: {
								externalAgentId: targetItem.externalAgentId,
								headers: targetItem.headers || null
							}
						});
						logger.info({
							subAgentId,
							externalAgentId: targetItem.externalAgentId
						}, "External agent delegation relation processed successfully");
					} catch (error) {
						logger.error({
							subAgentId,
							externalAgentId: targetItem.externalAgentId,
							error
						}, "Failed to create external delegation relation");
					}
				})());
				else if (typeof targetItem === "object" && "agentId" in targetItem) subAgentTeamAgentRelationPromises.push((async () => {
					try {
						await upsertSubAgentTeamAgentRelation(db)({
							scopes: {
								tenantId,
								projectId,
								agentId: finalAgentId,
								subAgentId
							},
							relationId: targetItem.subAgentTeamAgentRelationId,
							data: {
								targetAgentId: targetItem.agentId,
								headers: targetItem.headers || null
							}
						});
						logger.info({
							subAgentId,
							agentId: targetItem.agentId
						}, "Team agent delegation relation processed successfully");
					} catch (error) {
						logger.error({
							subAgentId,
							agentId: targetItem.agentId,
							error
						}, "Failed to create team agent delegation relation");
					}
				})());
			}
		}
		await Promise.all(subAgentRelationPromises);
		await Promise.all(subAgentExternalAgentRelationPromises);
		await Promise.all(subAgentTeamAgentRelationPromises);
		await syncSubAgentSkills(db, {
			tenantId,
			projectId,
			agentId: finalAgentId
		}, typed.subAgents);
		logger.info({ subAgentRelationCount: subAgentRelationPromises.length }, "All sub-agent relations created");
		logger.info({ subAgentExternalAgentRelationCount: subAgentExternalAgentRelationPromises.length }, "All sub-agent external agent relations created");
		logger.info({ subAgentTeamAgentRelationCount: subAgentTeamAgentRelationPromises.length }, "All sub-agent team agent relations created");
		const createdAgent = await getFullAgentDefinition(db)({ scopes: {
			tenantId,
			projectId,
			agentId: finalAgentId
		} });
		if (!createdAgent) throw new Error("Failed to retrieve created agent");
		logger.info({
			tenantId,
			agentId: finalAgentId
		}, "Full agent created successfully");
		return createdAgent;
	} catch (error) {
		const errorAgentId = typed.id || "unknown";
		logger.error({
			tenantId,
			agentId: errorAgentId,
			error
		}, "Failed to create full agent");
		throw error;
	}
};
/**
* Server-side implementation of updateFullAgent that performs actual database operations.
* This function updates a complete agent with all agents, tools, and relationships.
*/
const updateFullAgentServerSide = (db) => async (scopes, agentData) => {
	const { tenantId, projectId } = scopes;
	const typedAgentDefinition = validateAndTypeAgentData(agentData);
	if (!typedAgentDefinition.id) throw new Error("Agent ID is required");
	const { componentNameById, artifactNameById } = await loadComponentNameMaps(db, {
		tenantId,
		projectId
	}, typedAgentDefinition.subAgents);
	logger.info({
		tenantId,
		agentId: typedAgentDefinition.id,
		agentCount: Object.keys(typedAgentDefinition.subAgents).length
	}, "Updating full agent in database");
	validateAgentStructure(typedAgentDefinition);
	await applyExecutionLimitsInheritance(db, {
		tenantId,
		projectId
	}, typedAgentDefinition);
	try {
		const existingAgent = await getAgentById(db)({ scopes: {
			tenantId,
			projectId,
			agentId: typedAgentDefinition.id
		} });
		if (!existingAgent) {
			logger.info({ agentId: typedAgentDefinition.id }, "Agent does not exist, creating new agent");
			return createFullAgentServerSide(db)(scopes, agentData);
		}
		const existingAgentModels = existingAgent.models;
		logger.info("CredentialReferences are project-scoped - skipping credential reference update in agent");
		logger.info("MCP Tools are project-scoped - skipping tool creation in agent update");
		let finalAgentId;
		try {
			const agentId = typedAgentDefinition.id || generateId();
			logger.info({ agentId }, "Getting/creating agent metadata");
			const agent = await upsertAgent(db)({ data: {
				id: agentId,
				tenantId,
				projectId,
				name: typedAgentDefinition.name,
				defaultSubAgentId: typedAgentDefinition.defaultSubAgentId,
				description: typedAgentDefinition.description,
				contextConfigId: void 0,
				models: typedAgentDefinition.models,
				statusUpdates: typedAgentDefinition.statusUpdates,
				prompt: typedAgentDefinition.prompt,
				stopWhen: typedAgentDefinition.stopWhen,
				executionMode: typedAgentDefinition.executionMode
			} });
			if (!agent?.id) throw new Error("Failed to upsert agent: no ID returned");
			finalAgentId = agent.id;
			logger.info({ agentId: finalAgentId }, "Agent metadata ready");
		} catch (error) {
			logger.error({
				agentId: typedAgentDefinition.id,
				error
			}, "Failed to get/update agent metadata");
			throw error;
		}
		let contextConfigId;
		if (typedAgentDefinition.contextConfig) logger.info({ contextConfigId: typedAgentDefinition.contextConfig?.id }, " context config exists");
		if (typedAgentDefinition.contextConfig) try {
			contextConfigId = (await upsertContextConfig(db)({ data: {
				...typedAgentDefinition.contextConfig,
				agentId: finalAgentId,
				tenantId,
				projectId
			} })).id;
			logger.info({ contextConfigId }, "Context config processed successfully");
		} catch (error) {
			logger.error({
				contextConfigId: typedAgentDefinition.contextConfig.id,
				error
			}, "Failed to create/update context config");
			throw error;
		}
		if (contextConfigId) try {
			logger.info({
				agentId: finalAgentId,
				contextConfigId
			}, "Updating agent with contextConfigId");
			await upsertAgent(db)({ data: {
				id: finalAgentId,
				tenantId,
				projectId,
				name: typedAgentDefinition.name,
				defaultSubAgentId: typedAgentDefinition.defaultSubAgentId,
				description: typedAgentDefinition.description,
				contextConfigId,
				models: typedAgentDefinition.models,
				statusUpdates: typedAgentDefinition.statusUpdates,
				prompt: typedAgentDefinition.prompt,
				stopWhen: typedAgentDefinition.stopWhen,
				executionMode: typedAgentDefinition.executionMode
			} });
			logger.info({
				agentId: finalAgentId,
				contextConfigId
			}, "Agent updated with contextConfigId successfully");
		} catch (error) {
			logger.error({
				agentId: finalAgentId,
				contextConfigId,
				error
			}, "Failed to update agent with contextConfigId");
			throw error;
		}
		logger.info("DataComponents are project-scoped - skipping dataComponent update in agent");
		logger.info("ArtifactComponents are project-scoped - skipping artifactComponent update in agent");
		if (typedAgentDefinition.functions && Object.keys(typedAgentDefinition.functions).length > 0) {
			logger.info({
				agentId: finalAgentId,
				functionCount: Object.keys(typedAgentDefinition.functions).length
			}, "Updating functions for agent");
			const functionPromises = Object.entries(typedAgentDefinition.functions).map(async ([functionId, functionData]) => {
				try {
					logger.info({
						agentId: finalAgentId,
						functionId
					}, "Updating function for agent");
					await upsertFunction(db)({
						data: {
							...functionData,
							id: functionId
						},
						scopes: {
							tenantId,
							projectId
						}
					});
					logger.info({
						agentId: finalAgentId,
						functionId
					}, "Function updated successfully");
				} catch (error) {
					logger.error({
						agentId: finalAgentId,
						functionId,
						error
					}, "Failed to update function for agent");
					throw error;
				}
			});
			await Promise.all(functionPromises);
			logger.info({
				agentId: finalAgentId,
				functionCount: Object.keys(typedAgentDefinition.functions).length
			}, "All functions updated successfully");
		}
		if (typedAgentDefinition.functionTools && Object.keys(typedAgentDefinition.functionTools).length > 0) {
			logger.info({
				agentId: finalAgentId,
				functionToolCount: Object.keys(typedAgentDefinition.functionTools).length
			}, "Updating function tools for agent");
			const functionToolPromises = Object.entries(typedAgentDefinition.functionTools).map(async ([functionToolId, functionToolData]) => {
				try {
					logger.info({
						agentId: finalAgentId,
						functionToolId
					}, "Updating function tool in agent");
					await upsertFunctionTool(db)({
						data: {
							...functionToolData,
							id: functionToolId
						},
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						}
					});
					logger.info({
						agentId: finalAgentId,
						functionToolId
					}, "Function tool updated successfully");
				} catch (error) {
					logger.error({
						agentId: finalAgentId,
						functionToolId,
						error
					}, "Failed to update function tool in agent");
					throw error;
				}
			});
			await Promise.all(functionToolPromises);
			logger.info({
				agentId: finalAgentId,
				functionToolCount: Object.keys(typedAgentDefinition.functionTools).length
			}, "All function tools updated successfully");
		}
		const incomingFunctionToolIds = new Set(typedAgentDefinition.functionTools ? Object.keys(typedAgentDefinition.functionTools) : []);
		const existingFunctionTools = await listFunctionTools(db)({
			scopes: {
				tenantId,
				projectId,
				agentId: finalAgentId
			},
			pagination: {
				page: 1,
				limit: 1e3
			}
		});
		let deletedFunctionToolCount = 0;
		for (const functionTool of existingFunctionTools.data) if (!incomingFunctionToolIds.has(functionTool.id)) try {
			await deleteFunctionTool(db)({
				scopes: {
					tenantId,
					projectId,
					agentId: finalAgentId
				},
				functionToolId: functionTool.id
			});
			deletedFunctionToolCount++;
			logger.info({ functionToolId: functionTool.id }, "Deleted orphaned function tool");
		} catch (error) {
			logger.error({
				functionToolId: functionTool.id,
				error
			}, "Failed to delete orphaned function tool");
		}
		if (deletedFunctionToolCount > 0) logger.info({ deletedFunctionToolCount }, "Deleted orphaned function tools from agent");
		if (typedAgentDefinition.triggers && Object.keys(typedAgentDefinition.triggers).length > 0) {
			logger.info({
				agentId: finalAgentId,
				triggerCount: Object.keys(typedAgentDefinition.triggers).length
			}, "Updating triggers for agent");
			const triggerPromises = Object.entries(typedAgentDefinition.triggers).map(async ([triggerId, triggerData]) => {
				try {
					logger.info({
						agentId: finalAgentId,
						triggerId
					}, "Updating trigger in agent");
					const { runAsUserIds, ...triggerInsertData } = triggerData;
					await upsertTrigger(db)({
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						},
						data: {
							...triggerInsertData,
							id: triggerId,
							tenantId,
							projectId,
							agentId: finalAgentId
						}
					});
					if (runAsUserIds !== void 0) await setTriggerUsers(db)({
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						},
						triggerId,
						userIds: runAsUserIds
					});
					logger.info({
						agentId: finalAgentId,
						triggerId
					}, "Trigger updated successfully");
				} catch (error) {
					logger.error({
						agentId: finalAgentId,
						triggerId,
						error
					}, "Failed to update trigger in agent");
					throw error;
				}
			});
			await Promise.all(triggerPromises);
			logger.info({
				agentId: finalAgentId,
				triggerCount: Object.keys(typedAgentDefinition.triggers).length
			}, "All triggers updated successfully");
		}
		if (typedAgentDefinition.triggers !== void 0) {
			const incomingTriggerIds = new Set(Object.keys(typedAgentDefinition.triggers));
			const existingTriggers = await listTriggers(db)({ scopes: {
				tenantId,
				projectId,
				agentId: finalAgentId
			} });
			let deletedTriggerCount = 0;
			for (const trigger of existingTriggers) if (!incomingTriggerIds.has(trigger.id)) try {
				await deleteTrigger(db)({
					scopes: {
						tenantId,
						projectId,
						agentId: finalAgentId
					},
					triggerId: trigger.id
				});
				deletedTriggerCount++;
				logger.info({ triggerId: trigger.id }, "Deleted orphaned trigger");
			} catch (error) {
				logger.error({
					triggerId: trigger.id,
					error
				}, "Failed to delete orphaned trigger");
			}
			if (deletedTriggerCount > 0) logger.info({ deletedTriggerCount }, "Deleted orphaned triggers from agent");
		}
		const subAgentPromises = Object.entries(typedAgentDefinition.subAgents).map(async ([subAgentId, agentData$1]) => {
			const subAgent = agentData$1;
			let existingSubAgent = null;
			try {
				existingSubAgent = await db.query.subAgents.findFirst({
					where: and(agentScopedWhere(subAgents, {
						tenantId,
						projectId,
						agentId: finalAgentId
					}), eq(subAgents.id, subAgentId)),
					columns: { models: true }
				});
			} catch (_error) {}
			let finalModelSettings = subAgent.models === void 0 ? void 0 : subAgent.models;
			if (existingSubAgent?.models && typedAgentDefinition.models) {
				const subAgentModels = existingSubAgent.models;
				const agentModels = typedAgentDefinition.models;
				const modelTypes = [
					"base",
					"structuredOutput",
					"summarizer"
				];
				const cascadedModels = { ...finalModelSettings };
				for (const modelType of modelTypes) if (subAgentModels[modelType]?.model && existingAgentModels?.[modelType]?.model && subAgentModels[modelType].model === existingAgentModels[modelType].model && agentModels[modelType] && (agentModels[modelType].model !== existingAgentModels[modelType]?.model || JSON.stringify(agentModels[modelType].providerOptions) !== JSON.stringify(existingAgentModels[modelType]?.providerOptions))) {
					cascadedModels[modelType] = agentModels[modelType];
					logger.info({
						subAgentId,
						modelType,
						oldModel: existingAgentModels[modelType]?.model,
						newModel: agentModels[modelType].model,
						hasProviderOptions: !!agentModels[modelType].providerOptions
					}, "Cascading model change from parent agent to subAgent");
				}
				finalModelSettings = cascadedModels;
			}
			try {
				logger.info({ subAgentId }, "Processing sub-agent");
				await upsertSubAgent(db)({ data: {
					id: subAgentId,
					tenantId,
					projectId,
					agentId: finalAgentId,
					name: subAgent.name || "",
					description: subAgent.description || "",
					prompt: subAgent.prompt || "",
					conversationHistoryConfig: subAgent.conversationHistoryConfig,
					models: finalModelSettings,
					stopWhen: subAgent.stopWhen,
					outputContract: reconcileOutputContract(subAgent, componentNameById, artifactNameById)
				} });
				logger.info({ subAgentId }, "Sub-agent processed successfully");
			} catch (error) {
				logger.error({
					subAgentId,
					error
				}, "Failed to create/update sub-agent");
				throw error;
			}
		});
		await Promise.all(subAgentPromises);
		const subAgentCount = Object.entries(typedAgentDefinition.subAgents).length;
		logger.info({ subAgentCount }, "All sub-agents created/updated successfully");
		const relinkToolRelationPromises = [];
		for (const [subAgentId, agentData$1] of Object.entries(typedAgentDefinition.subAgents)) if (agentData$1.canUse && Array.isArray(agentData$1.canUse)) for (const canUseItem of agentData$1.canUse) {
			if (!canUseItem.agentToolRelationId) continue;
			relinkToolRelationPromises.push((async () => {
				try {
					const { toolId, toolSelection, headers, toolPolicies, agentToolRelationId } = canUseItem;
					if (typedAgentDefinition.functionTools && toolId in typedAgentDefinition.functionTools) await upsertSubAgentFunctionToolRelation(db)({
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						},
						subAgentId,
						functionToolId: toolId,
						toolPolicies,
						relationId: agentToolRelationId
					});
					else await upsertSubAgentToolRelation(db)({
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						},
						subAgentId,
						toolId,
						selectedTools: toolSelection,
						headers,
						toolPolicies,
						relationId: agentToolRelationId
					});
				} catch (error) {
					logger.error({
						subAgentId,
						relationId: canUseItem.agentToolRelationId,
						toolId: canUseItem.toolId,
						error
					}, "Failed to relink tool relation during sub-agent update");
				}
			})());
		}
		if (relinkToolRelationPromises.length > 0) await Promise.all(relinkToolRelationPromises);
		logger.info("External agents are project-scoped and managed at the project level.");
		const incomingSubAgentIds = new Set(Object.keys(typedAgentDefinition.subAgents));
		const existingSubAgents = await listSubAgents(db)({ scopes: {
			tenantId,
			projectId,
			agentId: finalAgentId
		} });
		let deletedSubAgentCount = 0;
		for (const subAgent of existingSubAgents) if (!incomingSubAgentIds.has(subAgent.id)) try {
			await deleteSubAgent(db)({
				scopes: {
					tenantId,
					projectId,
					agentId: finalAgentId
				},
				subAgentId: subAgent.id
			});
			deletedSubAgentCount++;
			logger.info({ subAgentId: subAgent.id }, "Deleted orphaned sub-agent");
		} catch (error) {
			logger.error({
				subAgentId: subAgent.id,
				error
			}, "Failed to delete orphaned sub-agent");
		}
		if (deletedSubAgentCount > 0) logger.info({ deletedSubAgentCount }, "Deleted orphaned sub-agents from agent");
		const incomingExternalAgentRelationIds = /* @__PURE__ */ new Map();
		const incomingTeamAgentRelationIds = /* @__PURE__ */ new Map();
		for (const [subAgentId, agentData$1] of Object.entries(typedAgentDefinition.subAgents)) if (agentData$1.canDelegateTo && Array.isArray(agentData$1.canDelegateTo)) {
			for (const delegateItem of agentData$1.canDelegateTo) if (typeof delegateItem === "object") {
				if ("externalAgentId" in delegateItem) incomingExternalAgentRelationIds.set(subAgentId, delegateItem.subAgentExternalAgentRelationId ?? "");
				else if ("agentId" in delegateItem) incomingTeamAgentRelationIds.set(subAgentId, delegateItem.subAgentTeamAgentRelationId ?? "");
			}
		}
		const existingExternalAgentRelations = await getSubAgentExternalAgentRelationsByAgent(db)({ scopes: {
			tenantId,
			projectId,
			agentId: finalAgentId
		} });
		let deletedExternalAgentRelationCount = 0;
		for (const relation of existingExternalAgentRelations) if (!incomingExternalAgentRelationIds.get(relation.subAgentId)?.includes(relation.id)) try {
			await deleteSubAgentExternalAgentRelation(db)({
				scopes: {
					tenantId,
					projectId,
					agentId: finalAgentId,
					subAgentId: relation.subAgentId
				},
				relationId: relation.id
			});
			deletedExternalAgentRelationCount++;
		} catch (error) {
			logger.error({
				relationId: relation.id,
				error
			}, "Failed to delete orphaned external agent relation");
		}
		if (deletedExternalAgentRelationCount > 0) logger.info({ deletedExternalAgentRelationCount }, "Deleted orphaned external agent relations from agent");
		let deletedTeamAgentRelationCount = 0;
		const existingTeamAgentRelations = await getSubAgentTeamAgentRelationsByAgent(db)({ scopes: {
			tenantId,
			projectId,
			agentId: finalAgentId
		} });
		for (const relation of existingTeamAgentRelations) if (!incomingTeamAgentRelationIds.get(relation.subAgentId)?.includes(relation.id)) try {
			await deleteSubAgentTeamAgentRelation(db)({
				scopes: {
					tenantId,
					projectId,
					agentId: finalAgentId,
					subAgentId: relation.subAgentId
				},
				relationId: relation.id
			});
			deletedTeamAgentRelationCount++;
		} catch (error) {
			logger.error({
				relationId: relation.id,
				error
			}, "Failed to delete orphaned team agent relation");
		}
		if (deletedTeamAgentRelationCount > 0) logger.info({ deletedTeamAgentRelationCount }, "Deleted orphaned team agent relations from agent");
		await updateAgent(db)({
			scopes: {
				tenantId,
				projectId,
				agentId: typedAgentDefinition.id
			},
			data: {
				name: typedAgentDefinition.name,
				defaultSubAgentId: typedAgentDefinition.defaultSubAgentId,
				description: typedAgentDefinition.description,
				contextConfigId,
				models: typedAgentDefinition.models,
				statusUpdates: typedAgentDefinition.statusUpdates,
				prompt: typedAgentDefinition.prompt,
				stopWhen: typedAgentDefinition.stopWhen,
				executionMode: typedAgentDefinition.executionMode
			}
		});
		logger.info({ agentId: typedAgentDefinition.id }, "Agent metadata updated");
		const incomingRelationshipIds = /* @__PURE__ */ new Set();
		for (const [_subAgentId, agentData$1] of Object.entries(typedAgentDefinition.subAgents)) if (agentData$1.canUse && Array.isArray(agentData$1.canUse)) {
			for (const canUseItem of agentData$1.canUse) if (canUseItem.agentToolRelationId) incomingRelationshipIds.add(canUseItem.agentToolRelationId);
		}
		for (const subAgentId of Object.keys(typedAgentDefinition.subAgents)) try {
			let deletedCount = 0;
			const toolRelScopes = {
				tenantId,
				projectId,
				agentId: finalAgentId,
				subAgentId
			};
			if (incomingRelationshipIds.size === 0) deletedCount = (await db.delete(subAgentToolRelations).where(subAgentScopedWhere(subAgentToolRelations, toolRelScopes)).returning()).length;
			else deletedCount = (await db.delete(subAgentToolRelations).where(and(subAgentScopedWhere(subAgentToolRelations, toolRelScopes), not(inArray(subAgentToolRelations.id, Array.from(incomingRelationshipIds))))).returning()).length;
			if (deletedCount > 0) logger.info({
				subAgentId,
				deletedCount
			}, "Deleted orphaned agent-tool relations");
		} catch (error) {
			logger.error({
				subAgentId,
				error
			}, "Failed to delete orphaned agent-tool relations");
		}
		const incomingFunctionToolRelationIds = /* @__PURE__ */ new Set();
		for (const [_subAgentId, agentData$1] of Object.entries(typedAgentDefinition.subAgents)) if (agentData$1.canUse && Array.isArray(agentData$1.canUse)) {
			for (const canUseItem of agentData$1.canUse) if (typedAgentDefinition.functionTools && canUseItem.toolId in typedAgentDefinition.functionTools && canUseItem.agentToolRelationId) incomingFunctionToolRelationIds.add(canUseItem.agentToolRelationId);
		}
		for (const subAgentId of Object.keys(typedAgentDefinition.subAgents)) try {
			let deletedFunctionToolRelationCount = 0;
			const fnToolRelScopes = {
				tenantId,
				projectId,
				agentId: finalAgentId,
				subAgentId
			};
			if (incomingFunctionToolRelationIds.size === 0) deletedFunctionToolRelationCount = (await db.delete(subAgentFunctionToolRelations).where(subAgentScopedWhere(subAgentFunctionToolRelations, fnToolRelScopes)).returning()).length;
			else deletedFunctionToolRelationCount = (await db.delete(subAgentFunctionToolRelations).where(and(subAgentScopedWhere(subAgentFunctionToolRelations, fnToolRelScopes), not(inArray(subAgentFunctionToolRelations.id, Array.from(incomingFunctionToolRelationIds))))).returning()).length;
			if (deletedFunctionToolRelationCount > 0) logger.info({
				subAgentId,
				deletedCount: deletedFunctionToolRelationCount
			}, "Deleted orphaned sub-agent-function tool relations");
		} catch (error) {
			logger.error({
				subAgentId,
				error
			}, "Failed to delete orphaned sub-agent-function tool relations");
		}
		const subAgentToolPromises = [];
		for (const [subAgentId, agentData$1] of Object.entries(typedAgentDefinition.subAgents)) if (agentData$1.canUse && Array.isArray(agentData$1.canUse)) for (const canUseItem of agentData$1.canUse) subAgentToolPromises.push((async () => {
			try {
				const { toolId, toolSelection, headers, toolPolicies, agentToolRelationId } = canUseItem;
				if (typedAgentDefinition.functionTools && toolId in typedAgentDefinition.functionTools) {
					logger.info({
						subAgentId,
						toolId
					}, "Processing sub-agent-function tool relation");
					await upsertSubAgentFunctionToolRelation(db)({
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						},
						subAgentId,
						functionToolId: toolId,
						toolPolicies,
						relationId: agentToolRelationId
					});
					logger.info({
						subAgentId,
						toolId,
						relationId: agentToolRelationId
					}, "Sub-agent-function tool relation upserted");
				} else {
					logger.info({
						subAgentId,
						toolId
					}, "Processing sub-agent-MCP tool relation");
					await upsertSubAgentToolRelation(db)({
						scopes: {
							tenantId,
							projectId,
							agentId: finalAgentId
						},
						subAgentId,
						toolId,
						selectedTools: toolSelection,
						headers,
						toolPolicies,
						relationId: agentToolRelationId
					});
					logger.info({
						subAgentId,
						toolId,
						relationId: agentToolRelationId
					}, "Sub-agent-MCP tool relation upserted");
				}
			} catch (error) {
				logger.error({
					subAgentId,
					toolId: canUseItem.toolId,
					relationId: canUseItem.agentToolRelationId,
					error
				}, "Failed to upsert agent-tool relation");
			}
		})());
		await Promise.all(subAgentToolPromises);
		logger.info({ subAgentToolPromisesCount: subAgentToolPromises.length }, "All sub-agent-tool relations updated");
		for (const subAgentId of Object.keys(typedAgentDefinition.subAgents)) await deleteAgentDataComponentRelationByAgent(db)({ scopes: {
			tenantId,
			projectId,
			agentId: finalAgentId,
			subAgentId
		} });
		const agentDataComponentPromises = [];
		for (const [subAgentId, agentData$1] of Object.entries(typedAgentDefinition.subAgents)) if (agentData$1.dataComponents) for (const dataComponentId of agentData$1.dataComponents) agentDataComponentPromises.push((async () => {
			try {
				await associateDataComponentWithAgent(db)({
					scopes: {
						tenantId,
						projectId,
						agentId: finalAgentId,
						subAgentId
					},
					dataComponentId
				});
				logger.info({
					subAgentId,
					dataComponentId
				}, "Sub-agent-dataComponent relation created");
			} catch (error) {
				logger.error({
					subAgentId,
					dataComponentId,
					error
				}, "Failed to create sub-agent-dataComponent relation");
			}
		})());
		await Promise.all(agentDataComponentPromises);
		logger.info({ agentDataComponentPromisesCount: agentDataComponentPromises.length }, "All sub-agent-dataComponent relations updated");
		for (const subAgentId of Object.keys(typedAgentDefinition.subAgents)) await deleteAgentArtifactComponentRelationByAgent(db)({ scopes: {
			tenantId,
			projectId,
			agentId: finalAgentId,
			subAgentId
		} });
		const agentArtifactComponentPromises = [];
		for (const [subAgentId, agentData$1] of Object.entries(typedAgentDefinition.subAgents)) if (agentData$1.artifactComponents) for (const artifactComponentId of agentData$1.artifactComponents) agentArtifactComponentPromises.push((async () => {
			try {
				await associateArtifactComponentWithAgent(db)({
					scopes: {
						tenantId,
						projectId,
						agentId: finalAgentId,
						subAgentId
					},
					artifactComponentId
				});
				logger.info({
					subAgentId,
					artifactComponentId
				}, "Sub-agent-artifactComponent relation created");
			} catch (error) {
				logger.error({
					subAgentId,
					artifactComponentId,
					error
				}, "Failed to create sub-agent-artifactComponent relation");
			}
		})());
		await Promise.all(agentArtifactComponentPromises);
		logger.info({ agentArtifactComponentPromisesCount: agentArtifactComponentPromises.length }, "All sub-agent-artifactComponent relations updated");
		await deleteAgentRelationsByAgent(db)({ scopes: {
			tenantId,
			projectId,
			agentId: typedAgentDefinition.id
		} });
		const subAgentRelationPromises = [];
		const subAgentExternalAgentRelationPromises = [];
		const subAgentTeamAgentRelationPromises = [];
		for (const [subAgentId, agentData$1] of Object.entries(typedAgentDefinition.subAgents)) {
			if (agentData$1.canTransferTo) for (const targetSubAgentId of agentData$1.canTransferTo) subAgentRelationPromises.push((async () => {
				try {
					await createSubAgentRelation(db)({
						tenantId,
						projectId,
						id: deriveRelationId(tenantId, projectId, typedAgentDefinition.id || "", subAgentId, targetSubAgentId, "transfer"),
						agentId: typedAgentDefinition.id || "",
						sourceSubAgentId: subAgentId,
						targetSubAgentId,
						relationType: "transfer"
					});
					logger.info({
						subAgentId,
						targetSubAgentId
					}, "Transfer relation created");
				} catch (error) {
					logger.error({
						subAgentId,
						targetSubAgentId,
						error
					}, "Failed to create transfer relation");
				}
			})());
			if (agentData$1.canDelegateTo) {
				for (const targetItem of agentData$1.canDelegateTo) if (typeof targetItem === "string") subAgentRelationPromises.push((async () => {
					try {
						await createSubAgentRelation(db)({
							tenantId,
							projectId,
							id: deriveRelationId(tenantId, projectId, typedAgentDefinition.id || "", subAgentId, targetItem, "delegate"),
							agentId: typedAgentDefinition.id || "",
							sourceSubAgentId: subAgentId,
							targetSubAgentId: targetItem,
							relationType: "delegate"
						});
						logger.info({
							subAgentId,
							targetSubAgentId: targetItem
						}, "Sub-agent delegation relation created");
					} catch (error) {
						logger.error({
							subAgentId,
							targetSubAgentId: targetItem,
							error
						}, "Failed to create sub-agent delegation relation");
					}
				})());
				else if ("externalAgentId" in targetItem) subAgentExternalAgentRelationPromises.push((async () => {
					try {
						await upsertSubAgentExternalAgentRelation(db)({
							scopes: {
								tenantId,
								projectId,
								agentId: typedAgentDefinition.id || "",
								subAgentId
							},
							relationId: targetItem.subAgentExternalAgentRelationId,
							data: {
								externalAgentId: targetItem.externalAgentId,
								headers: targetItem.headers || null
							}
						});
						logger.info({
							subAgentId,
							externalAgentId: targetItem.externalAgentId
						}, "External delegation relation created");
					} catch (error) {
						logger.error({
							subAgentId,
							externalAgentId: targetItem.externalAgentId,
							error
						}, "Failed to create external delegation relation");
					}
				})());
				else if ("agentId" in targetItem) {
					logger.info({
						subAgentId,
						targetItem
					}, "Processing team agent delegation");
					subAgentTeamAgentRelationPromises.push((async () => {
						try {
							await upsertSubAgentTeamAgentRelation(db)({
								scopes: {
									tenantId,
									projectId,
									agentId: finalAgentId,
									subAgentId
								},
								relationId: targetItem.subAgentTeamAgentRelationId,
								data: {
									targetAgentId: targetItem.agentId,
									headers: targetItem.headers || null
								}
							});
							logger.info({
								subAgentId,
								agentId: targetItem.agentId
							}, "Team agent delegation relation created");
						} catch (error) {
							logger.error({
								subAgentId,
								agentId: targetItem.agentId,
								error
							}, "Failed to create team agent delegation relation");
						}
					})());
				}
			}
		}
		await Promise.all(subAgentRelationPromises);
		logger.info({ subAgentRelationPromisesCount: subAgentRelationPromises.length }, "All sub-agent relations updated");
		await Promise.all(subAgentExternalAgentRelationPromises);
		logger.info({ subAgentExternalAgentRelationPromisesCount: subAgentExternalAgentRelationPromises.length }, "All sub-agent external agent relations updated");
		await Promise.all(subAgentTeamAgentRelationPromises);
		logger.info({ subAgentTeamAgentRelationPromisesCount: subAgentTeamAgentRelationPromises.length }, "All sub-agent team agent relations updated");
		await syncSubAgentSkills(db, {
			tenantId,
			projectId,
			agentId: typedAgentDefinition.id
		}, typedAgentDefinition.subAgents);
		const updatedAgent = await getFullAgentDefinition(db)({ scopes: {
			tenantId,
			projectId,
			agentId: typedAgentDefinition.id
		} });
		if (!updatedAgent) throw new Error("Failed to retrieve updated agent");
		logger.info({ agentId: typedAgentDefinition.id }, "Full agent updated successfully");
		return updatedAgent;
	} catch (error) {
		logger.error({
			agentId: typedAgentDefinition.id,
			error
		}, "Failed to update full agent");
		throw error;
	}
};
/**
* Get a complete agent definition by ID
*/
const getFullAgent = (db) => async (params) => {
	const { scopes } = params;
	const { tenantId, projectId } = scopes;
	logger.info({
		tenantId,
		agentId: scopes.agentId
	}, "Retrieving full agent definition");
	try {
		const agent = await getFullAgentDefinition(db)({ scopes: {
			tenantId,
			projectId,
			agentId: scopes.agentId
		} });
		if (!agent) {
			logger.info({
				tenantId,
				agentId: scopes.agentId
			}, "Agent not found");
			return null;
		}
		logger.info({
			tenantId,
			agentId: scopes.agentId,
			agentCount: Object.keys(agent.subAgents).length
		}, "Full agent retrieved successfully");
		return agent;
	} catch (error) {
		logger.error({
			tenantId,
			agentId: scopes.agentId,
			error: error instanceof Error ? error.message : "Unknown error"
		}, "Failed to retrieve full agent");
		throw error;
	}
};
const getFullAgentWithRelationIds = (db) => async (params) => {
	const { scopes } = params;
	const { tenantId, projectId } = scopes;
	logger.info({
		tenantId,
		agentId: scopes.agentId
	}, "Retrieving full agent definition with relation ids");
	try {
		const agent = await getFullAgentDefinitionWithRelationIds(db)({ scopes: {
			tenantId,
			projectId,
			agentId: scopes.agentId
		} });
		if (!agent) {
			logger.info({
				tenantId,
				agentId: scopes.agentId
			}, "Agent not found");
			return null;
		}
		logger.info({
			tenantId,
			agentId: scopes.agentId,
			agentCount: Object.keys(agent.subAgents).length
		}, "Full agent with relation ids retrieved successfully");
		return agent;
	} catch (error) {
		logger.error({
			tenantId,
			agentId: scopes.agentId,
			error: error instanceof Error ? error.message : "Unknown error"
		}, "Failed to retrieve full agent with relation ids");
		throw error;
	}
};
/**
* Delete a complete agent and cascade to all related entities
*/
const deleteFullAgent = (db) => async (params) => {
	const { tenantId, projectId, agentId } = params.scopes;
	logger.info({
		tenantId,
		agentId
	}, "Deleting full agent and related entities");
	try {
		const agent = await getFullAgentDefinition(db)({ scopes: {
			tenantId,
			projectId,
			agentId
		} });
		if (!agent) {
			logger.info({
				tenantId,
				agentId
			}, "Agent not found for deletion");
			return false;
		}
		await deleteAgentRelationsByAgent(db)({ scopes: {
			tenantId,
			projectId,
			agentId
		} });
		logger.info({
			tenantId,
			agentId
		}, "Agent relations deleted");
		const subAgentIds = Object.keys(agent.subAgents);
		if (subAgentIds.length > 0) {
			for (const subAgentId of subAgentIds) await deleteAgentToolRelationByAgent(db)({ scopes: {
				tenantId,
				projectId,
				agentId,
				subAgentId
			} });
			logger.info({
				tenantId,
				agentId,
				agentCount: subAgentIds.length
			}, "Agent-tool relations deleted");
		}
		await deleteAgent(db)({ scopes: {
			tenantId,
			projectId,
			agentId
		} });
		logger.info({
			tenantId,
			agentId
		}, "Agent metadata deleted");
		logger.info({
			tenantId,
			agentId
		}, "Full agent deleted successfully");
		return true;
	} catch (error) {
		logger.error({
			tenantId,
			agentId,
			error: error instanceof Error ? error.message : "Unknown error"
		}, "Failed to delete full agent");
		throw error;
	}
};

//#endregion
export { createFullAgentServerSide, deleteFullAgent, getFullAgent, getFullAgentWithRelationIds, reconcileOutputContract, updateFullAgentServerSide };