n8n
Version:
n8n Workflow Automation Tool
255 lines • 12.7 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AgentsService = void 0;
const agent_config_1 = require("@n8n/ai-utilities/agent-config");
const api_types_1 = require("@n8n/api-types");
const backend_common_1 = require("@n8n/backend-common");
const db_1 = require("@n8n/db");
const di_1 = require("@n8n/di");
const permissions_1 = require("@n8n/permissions");
const uuid_1 = require("uuid");
const conflict_error_1 = require("../../errors/response-errors/conflict.error");
const not_found_error_1 = require("../../errors/response-errors/not-found.error");
const agent_chat_attachment_service_1 = require("./agent-chat-attachment.service");
const agent_knowledge_service_1 = require("./agent-knowledge.service");
const agent_execution_service_1 = require("./agent-execution.service");
const agent_runtime_cache_service_1 = require("./agent-runtime-cache.service");
const agent_test_chat_service_1 = require("./agent-test-chat.service");
const chat_integration_service_1 = require("./integrations/chat-integration.service");
const agent_task_repository_1 = require("./repositories/agent-task.repository");
const agent_config_composition_1 = require("./json-config/agent-config-composition");
const agent_repository_1 = require("./repositories/agent.repository");
const sub_agent_cleanup_service_1 = require("./sub-agents/sub-agent-cleanup.service");
const agent_capabilities_1 = require("./utils/agent-capabilities");
const event_service_1 = require("../../events/event.service");
let AgentsService = class AgentsService {
constructor(logger, agentRepository, projectRelationRepository, agentChatAttachmentService, agentKnowledgeService, runtimeCacheService, testChatService, agentTaskRepository, subAgentCleanupService, eventService, agentExecutionService) {
this.logger = logger;
this.agentRepository = agentRepository;
this.projectRelationRepository = projectRelationRepository;
this.agentChatAttachmentService = agentChatAttachmentService;
this.agentKnowledgeService = agentKnowledgeService;
this.runtimeCacheService = runtimeCacheService;
this.testChatService = testChatService;
this.agentTaskRepository = agentTaskRepository;
this.subAgentCleanupService = subAgentCleanupService;
this.eventService = eventService;
this.agentExecutionService = agentExecutionService;
}
async create(projectId, name, { availableInMCP = false, id, adoptUnconfiguredOnCollision = false, schema, skills, } = {}) {
const defaultConfig = {
name,
model: '',
instructions: '',
tools: [],
skills: [],
personalisation: {
icon: api_types_1.DEFAULT_AGENT_PERSONALISATION.icon,
gradient: (0, api_types_1.getRandomAgentPersonalisationGradient)(),
},
};
const { schemaConfig, integrations } = (0, agent_config_composition_1.decomposeJsonConfig)(schema ?? defaultConfig);
const agent = this.agentRepository.create({
...(id ? { id } : {}),
name,
projectId,
schema: schemaConfig,
...(integrations.length > 0 ? { integrations } : {}),
...(skills ? { skills } : {}),
versionId: (0, uuid_1.v4)(),
availableInMCP,
});
let saved;
try {
saved = await this.agentRepository.save(agent);
}
catch (error) {
if (!id || !(0, db_1.isUniqueConstraintError)(error))
throw error;
const conflict = new conflict_error_1.ConflictError('An agent with this id already exists');
if (!adoptUnconfiguredOnCollision)
throw conflict;
const existing = await this.agentRepository.findByIdAndProjectId(id, projectId);
if (!existing || !(0, agent_capabilities_1.isUnconfiguredAgent)(existing.schema, existing.integrations ?? [])) {
throw conflict;
}
this.logger.debug('Adopted concurrently created SDK agent', { agentId: id, projectId });
return existing;
}
this.logger.debug('Created SDK agent', { agentId: saved.id, projectId });
return saved;
}
async findByProjectId(projectId) {
return await this.agentRepository.findByProjectId(projectId);
}
async findByProjectIdPaginated(projectId, options) {
return await this.agentRepository.findByProjectIdsPaginated([projectId], options);
}
async findById(agentId, projectId) {
return await this.agentRepository.findByIdAndProjectId(agentId, projectId);
}
async getCapabilitySummary(agentId, projectId) {
const entity = await this.agentRepository.findByIdAndProjectId(agentId, projectId);
if (!entity)
throw new not_found_error_1.NotFoundError('Agent not found');
const schema = entity.schema;
const modelId = schema?.model ?? '';
const model = modelId ? (0, agent_config_1.splitModelId)(modelId) : null;
const channels = (entity.integrations ?? []).map((integration) => ({
type: integration.type,
}));
const tools = (schema?.tools ?? []).flatMap((tool) => {
switch (tool.type) {
case 'custom':
return [{ type: 'custom', name: entity.tools[tool.id]?.descriptor?.name ?? tool.id }];
case 'workflow':
return [{ type: 'workflow', name: tool.name ?? tool.workflow }];
case 'node':
return [
{
type: 'node',
name: tool.name,
nodeType: tool.node?.nodeType,
nodeTypeVersion: tool.node?.nodeTypeVersion,
},
];
default:
return [];
}
});
const mcpServers = (schema?.mcpServers ?? []).map((server) => ({ name: server.name }));
const skills = (schema?.skills ?? []).map((skill) => ({
id: skill.id,
name: entity.skills[skill.id]?.name ?? skill.id,
}));
const taskRefs = schema?.tasks ?? [];
let taskNamesById = {};
if (taskRefs.length > 0) {
const taskBodies = await this.agentTaskRepository.findByAgentId(agentId);
taskNamesById = Object.fromEntries(taskBodies.map((task) => [task.id, task.name]));
}
const tasks = taskRefs.map((task) => ({
id: task.id,
name: taskNamesById[task.id] ?? task.id,
enabled: task.enabled,
}));
return {
id: entity.id,
name: entity.name,
model,
channels,
tools,
mcpServers,
skills,
tasks,
};
}
async findByUser(userId) {
const projectRelations = await this.projectRelationRepository.findAllByUser(userId);
const projectIds = projectRelations.map((pr) => pr.projectId);
if (projectIds.length === 0)
return [];
return await this.agentRepository.find({
where: { projectId: (0, db_1.In)(projectIds) },
order: { updatedAt: 'DESC' },
});
}
async findSummariesInProjects(projectIds, options = {}) {
return await this.agentRepository.findSummariesByProjectIds(projectIds, options);
}
async findByIdForUser(agentId, user) {
if ((0, permissions_1.hasGlobalScope)(user, 'agent:read')) {
return await this.agentRepository.findById(agentId);
}
const projectRelations = await this.projectRelationRepository.findAllByUser(user.id);
const projectIds = projectRelations.map((pr) => pr.projectId);
return await this.agentRepository.findByIdInProjects(agentId, projectIds);
}
async findByUserPaginated(userId, options) {
const projectRelations = await this.projectRelationRepository.findAllByUser(userId);
const projectIds = projectRelations.map((pr) => pr.projectId);
return await this.agentRepository.findByProjectIdsPaginated(projectIds, options);
}
async findPublishedByUser(userId) {
const projectRelations = await this.projectRelationRepository.findAllByUser(userId);
const projectIds = projectRelations.map((pr) => pr.projectId);
if (projectIds.length === 0)
return [];
const agents = await this.agentRepository.find({
where: { projectId: (0, db_1.In)(projectIds) },
relations: { activeVersion: true },
order: { updatedAt: 'DESC' },
});
return agents.filter((agent) => agent.activeVersionId !== null);
}
async delete(agentId, projectId) {
const agent = await this.agentRepository.findByIdAndProjectId(agentId, projectId);
if (!agent) {
return false;
}
try {
await this.agentKnowledgeService.deleteAllFilesForAgent(projectId, agentId);
}
catch (error) {
this.logger.warn('Failed to delete knowledge files on agent delete', {
agentId,
error: error instanceof Error ? error.message : error,
});
}
await this.agentKnowledgeService.destroySandbox(projectId, agentId);
try {
await this.agentChatAttachmentService.deleteByAgent(agentId);
}
catch (error) {
this.logger.warn('Failed to delete chat attachments on agent delete', {
agentId,
error: error instanceof Error ? error.message : error,
});
}
const chatIntegrationService = di_1.Container.get(chat_integration_service_1.ChatIntegrationService);
for (const integration of agent.integrations ?? []) {
await chatIntegrationService.disconnectChannel(agentId, integration);
}
await this.agentExecutionService.deleteExecutionLogsForAgent(agentId);
await this.agentRepository.remove(agent);
this.runtimeCacheService.clearRuntimes(agentId);
await this.subAgentCleanupService.removeSubAgentFromParents(agentId, projectId);
this.eventService.emit('agent-deleted', { agentId, projectId });
try {
const { AgentTaskService } = await import('./agent-task.service.js');
await di_1.Container.get(AgentTaskService).requestReconcile(agentId);
}
catch (error) {
this.logger.warn('Failed to stop tasks on agent delete', {
agentId,
error: error instanceof Error ? error.message : error,
});
}
try {
await this.testChatService.clearAllTestChatMessages(agentId);
}
catch (error) {
this.logger.warn('Failed to clear test chat on agent delete', {
agentId,
error: error instanceof Error ? error.message : error,
});
}
this.logger.debug('Deleted SDK agent', { agentId, projectId });
return true;
}
};
exports.AgentsService = AgentsService;
exports.AgentsService = AgentsService = __decorate([
(0, di_1.Service)(),
__metadata("design:paramtypes", [backend_common_1.Logger, agent_repository_1.AgentRepository, db_1.ProjectRelationRepository, agent_chat_attachment_service_1.AgentChatAttachmentService, agent_knowledge_service_1.AgentKnowledgeService, agent_runtime_cache_service_1.AgentRuntimeCacheService, agent_test_chat_service_1.AgentTestChatService, agent_task_repository_1.AgentTaskRepository, sub_agent_cleanup_service_1.SubAgentCleanupService, event_service_1.EventService, agent_execution_service_1.AgentExecutionService])
], AgentsService);
//# sourceMappingURL=agents.service.js.map