UNPKG

n8n

Version:

n8n Workflow Automation Tool

211 lines • 9.5 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.SubAgentForegroundRunner = void 0; const agents_1 = require("@n8n/agents"); const backend_common_1 = require("@n8n/backend-common"); const di_1 = require("@n8n/di"); const n8n_workflow_1 = require("n8n-workflow"); const uuid_1 = require("uuid"); const agent_execution_service_1 = require("../agent-execution.service"); const agent_telemetry_1 = require("../agent-telemetry"); const execution_recorder_1 = require("../execution-recorder"); const agent_stream_1 = require("../utils/agent-stream"); const sub_agent_source_resolver_1 = require("./sub-agent-source-resolver"); let SubAgentForegroundRunner = class SubAgentForegroundRunner { constructor(sourceResolver, agentExecutionService, logger) { this.sourceResolver = sourceResolver; this.agentExecutionService = agentExecutionService; this.logger = logger; } async runForeground(request, context) { if (request.executionMode !== undefined && request.executionMode !== 'foreground') { throw new n8n_workflow_1.UserError('Foreground sub-agent runner only supports foreground execution mode'); } const taskPath = request.taskPath; (0, agents_1.assertSubAgentTaskPath)(taskPath); const runtimeSource = await this.sourceResolver.resolveForRuntime(request.source, { projectId: context.projectId, }); const threadId = (0, uuid_1.v4)(); const resourceId = request.parentResourceId ?? threadId; const reconstructionService = await getReconstructionService(); const childConfig = context.instrumentation?.transformDelegatedAgentConfig?.(runtimeSource.source.config, { subAgentId: runtimeSource.source.sourceId, }) ?? runtimeSource.source.config; const { agent } = await reconstructionService.reconstructFromResolvedSource({ config: childConfig, memoryOwnerAgentId: runtimeSource.source.sourceId, projectId: context.projectId, credentialProvider: context.credentialProvider, toolDescriptors: runtimeSource.toolDescriptors, toolCodeByName: runtimeSource.toolCodeByName, skills: runtimeSource.skills, runtimeProfile: 'sub-agent', parentAgentIdForDelegation: context.parentAgentId, user: context.user, instrumentation: context.instrumentation, }); const abortSignal = context.abortSignal; const telemetry = (0, agents_1.deriveSubAgentTelemetry)(context.telemetry); const prompt = (0, agents_1.renderDelegateSubAgentPrompt)(request); try { const resultStream = await agent.stream(prompt, { ...(abortSignal !== undefined ? { abortSignal } : {}), ...(telemetry !== undefined ? { telemetry } : {}), persistence: { resourceId, threadId, }, executionCounter: context.executionCounter, }); const recorder = new execution_recorder_1.ExecutionRecorder(); let structuredOutput; let childSuspended = false; for await (const value of (0, agent_stream_1.streamAgentChunks)(resultStream.stream)) { recorder.record(value); if (value.type === 'tool-call-suspended') { childSuspended = true; } if (value.type === 'finish' && value.structuredOutput !== undefined) { structuredOutput = value.structuredOutput; } } const messageRecord = recorder.getMessageRecord(); await this.recordSubAgentExecution({ runtimeSource: runtimeSource.source, projectId: context.projectId, threadId, parentThreadId: request.parentThreadId, parentAgentId: context.parentAgentId, taskPath, prompt, record: messageRecord, }); if (childSuspended) { return { taskPath, threadId, status: 'failed', result: { runId: resultStream.runId, messages: [], finishReason: 'error', error: agents_1.DELEGATED_CHILD_SUSPEND_UNSUPPORTED_MESSAGE, getState: () => { throw new Error('getState is not implemented for sub-agent foreground runner'); }, }, }; } const result = buildGenerateResultFromRecord(resultStream.runId, messageRecord, structuredOutput); return { taskPath, threadId, status: result.finishReason === 'error' || result.error !== undefined ? 'failed' : 'completed', result, }; } finally { await agent.close().catch((error) => { this.logger.warn('Failed to close subagent after run', { taskPath, error: error instanceof Error ? error.message : String(error), }); }); } } async recordSubAgentExecution(params) { const { runtimeSource, projectId, threadId, parentThreadId, parentAgentId, taskPath, prompt, record, } = params; try { await this.agentExecutionService.recordMessage({ threadId, agentId: runtimeSource.sourceId, agentName: runtimeSource.config.name, projectId, userMessage: prompt, record, source: 'subagent', threadMetadata: { ...(parentThreadId !== undefined ? { parentThreadId } : {}), ...(parentAgentId !== undefined ? { parentAgentId } : {}), }, telemetry: { runType: 'production', configuration: (0, agent_telemetry_1.buildAgentConfigurationTelemetryFromConfig)(runtimeSource.config), }, }); } catch (error) { this.logger.warn('Failed to record subagent execution', { agentId: runtimeSource.sourceId, taskPath, error: error instanceof Error ? error.message : String(error), }); } } }; exports.SubAgentForegroundRunner = SubAgentForegroundRunner; exports.SubAgentForegroundRunner = SubAgentForegroundRunner = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [sub_agent_source_resolver_1.SubAgentSourceResolver, agent_execution_service_1.AgentExecutionService, backend_common_1.Logger]) ], SubAgentForegroundRunner); async function getReconstructionService() { const { AgentRuntimeReconstructionService } = await import('../agent-runtime-reconstruction.service.js'); return di_1.Container.get(AgentRuntimeReconstructionService); } function buildGenerateResultFromRecord(runId, record, structuredOutput) { const messages = createAssistantMessages(record.assistantResponse); const finishReason = toKnownFinishReason(record.finishReason); const result = { runId, messages, ...(record.model !== null ? { model: record.model } : {}), ...(finishReason !== undefined ? { finishReason } : {}), ...(record.usage !== null ? { usage: { ...record.usage, ...(record.totalCost !== null ? { cost: record.totalCost } : {}), }, } : {}), ...(structuredOutput !== undefined ? { structuredOutput } : {}), ...(record.error !== null ? { error: record.error } : {}), getState: () => { throw new Error('getState is not implemented for sub-agent foreground runner'); }, }; return result; } function createAssistantMessages(text) { if (!text.trim()) return []; return [ { role: 'assistant', content: [{ type: 'text', text }], }, ]; } function toKnownFinishReason(value) { if (value === 'stop' || value === 'length' || value === 'content-filter' || value === 'tool-calls' || value === 'error' || value === 'other' || value === 'max-iterations') { return value; } return undefined; } //# sourceMappingURL=sub-agent-foreground-runner.js.map