UNPKG

n8n

Version:

n8n Workflow Automation Tool

153 lines 7.19 kB
"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.AgentExecutionService = void 0; exports.threadBelongsTo = threadBelongsTo; const backend_common_1 = require("@n8n/backend-common"); const di_1 = require("@n8n/di"); const n8n_memory_1 = require("./integrations/n8n-memory"); const agent_execution_repository_1 = require("./repositories/agent-execution.repository"); const agent_execution_thread_repository_1 = require("./repositories/agent-execution-thread.repository"); let AgentExecutionService = class AgentExecutionService { constructor(logger, agentExecutionRepository, agentExecutionThreadRepository, n8nMemory) { this.logger = logger; this.agentExecutionRepository = agentExecutionRepository; this.agentExecutionThreadRepository = agentExecutionThreadRepository; this.n8nMemory = n8nMemory; } async recordMessage(params) { const { threadId, agentId, agentName, projectId, record, source, hitlStatus } = params; const { thread, created } = await this.agentExecutionThreadRepository.findOrCreate(threadId, agentId, agentName, projectId); if (!created) { await this.agentExecutionThreadRepository.bumpUpdatedAt(threadId); if (!thread.title) { await this.syncTitleFromMemory(threadId); } } const cleanedMessage = params.userMessage .replace(/<@[A-Z0-9]+>/gi, `@${agentName}`) .replace(/@[A-Z0-9]{8,}/gi, `@${agentName}`) .trim(); const status = record.error ? 'error' : 'success'; const startedAt = new Date(record.startTime); const stoppedAt = new Date(record.startTime + record.duration); const inserted = await this.agentExecutionRepository.save(this.agentExecutionRepository.create({ threadId, status, startedAt, stoppedAt, duration: record.duration, userMessage: cleanedMessage, assistantResponse: record.assistantResponse, model: record.model, promptTokens: record.usage?.promptTokens ?? null, completionTokens: record.usage?.completionTokens ?? null, totalTokens: record.usage?.totalTokens ?? null, cost: record.totalCost, toolCalls: record.toolCalls.length > 0 ? record.toolCalls : null, timeline: record.timeline.length > 0 ? record.timeline : null, error: record.error, hitlStatus: hitlStatus ?? null, workingMemory: record.workingMemory, source: source ?? null, })); if (hitlStatus === 'resumed' && record.model) { await this.backfillSuspendedExecutions(threadId, record.model); } if (record.usage) { await this.agentExecutionThreadRepository.incrementUsage(threadId, record.usage.promptTokens, record.usage.completionTokens, record.totalCost ?? 0, record.duration); } this.logger.debug('Recorded agent execution', { executionId: inserted.id, threadId, agentId, status, duration: record.duration, }); if (created) { await this.syncTitleFromMemory(threadId); } return inserted.id; } async backfillSuspendedExecutions(threadId, model) { const candidates = await this.agentExecutionRepository.findSuspendedWithoutModel(threadId); if (candidates.length === 0) return; await this.agentExecutionRepository.backfillModel(candidates.map((c) => c.id), model); } async syncTitleFromMemory(threadId) { try { const memoryThread = await this.n8nMemory.getThread(threadId); if (memoryThread?.title) { const emoji = memoryThread.metadata && typeof memoryThread.metadata.emoji === 'string' ? memoryThread.metadata.emoji : null; await this.agentExecutionThreadRepository.update(threadId, { title: memoryThread.title, ...(emoji && { emoji }), }); } } catch { } } async deleteThread(projectId, threadId) { const thread = await this.agentExecutionThreadRepository.findOneBy({ id: threadId, projectId, }); if (!thread) return false; await this.n8nMemory.deleteThread(threadId); await this.agentExecutionThreadRepository.delete({ id: threadId }); return true; } async getThreads(projectId, limit, cursor, agentId) { const page = await this.agentExecutionThreadRepository.findByProjectIdPaginated(projectId, limit, cursor, agentId); if (page.threads.length === 0) { return { threads: [], nextCursor: page.nextCursor }; } const messageMap = await this.agentExecutionRepository.findFirstUserMessageByThreadIds(page.threads.map((t) => t.id)); return { ...page, threads: page.threads.map((t) => ({ ...t, firstMessage: messageMap.get(t.id) ?? null, })), }; } async getThreadDetail(threadId, projectId, agentId) { const thread = await this.agentExecutionThreadRepository.findOneBy({ id: threadId }); if (!thread || !threadBelongsTo(thread, projectId, agentId)) return null; const executions = await this.agentExecutionRepository.findByThreadIdOrdered(threadId); return { thread, executions }; } async findThreadById(threadId) { return await this.agentExecutionThreadRepository.findOneBy({ id: threadId }); } }; exports.AgentExecutionService = AgentExecutionService; exports.AgentExecutionService = AgentExecutionService = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [backend_common_1.Logger, agent_execution_repository_1.AgentExecutionRepository, agent_execution_thread_repository_1.AgentExecutionThreadRepository, n8n_memory_1.N8nMemory]) ], AgentExecutionService); function threadBelongsTo(thread, projectId, agentId) { if (thread.projectId !== projectId) return false; if (agentId && thread.agentId !== agentId) return false; return true; } //# sourceMappingURL=agent-execution.service.js.map