UNPKG

n8n

Version:

n8n Workflow Automation Tool

164 lines (160 loc) 8.94 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.InstanceAiBuilderDelegateAdapterService = exports.INSTANCE_AI_BUILDER_ADDENDUM = void 0; const di_1 = require("@n8n/di"); const instance_ai_1 = require("@n8n/instance-ai"); const typeorm_1 = require("@n8n/typeorm"); const n8n_workflow_1 = require("n8n-workflow"); const forbidden_error_1 = require("../../errors/response-errors/forbidden.error"); const check_access_1 = require("../../permissions.ee/check-access"); const agent_config_service_1 = require("./agent-config.service"); const agent_skills_service_1 = require("./agent-skills.service"); const agents_service_1 = require("./agents.service"); const agents_builder_service_1 = require("./builder/agents-builder.service"); const n8n_memory_1 = require("./integrations/n8n-memory"); const agent_thread_repository_1 = require("./repositories/agent-thread.repository"); const agent_config_hash_1 = require("./utils/agent-config-hash"); exports.INSTANCE_AI_BUILDER_ADDENDUM = `## Instance AI session rules You are running as a sub-agent inside n8n's instance AI chat; the user sees your questions as chat cards. Preview links work in this chat. Include a markdown Preview link after a successful build and when \`call_agent\` reports an unsupported interaction as \`approval_required\`, using the exact relative path from "When To Build vs When To Converse" (form: \`[Preview](<path>)\`). Do not invent absolute URLs. Do not omit the link and describe the path in plain text instead. You can publish and unpublish the target agent with \`publish_agent\` and \`unpublish_agent\`. Never tell the user to open the agent editor and click Publish. The Instance AI orchestrator can create workflows and data tables — never ask the user to create them manually. State missing prerequisites in your reply; the orchestrator will provision them and call you again.`; function isTextDeltaChunk(chunk) { return chunk.type === 'text-delta'; } function toBuilderTurnStream(chunks) { let resolveText; const text = new Promise((resolve) => { resolveText = resolve; }); let acc = ''; async function* pump() { try { for await (const chunk of chunks) { if (isTextDeltaChunk(chunk)) acc += chunk.delta; yield chunk; } } finally { resolveText(acc); } } return { fullStream: pump(), text }; } let InstanceAiBuilderDelegateAdapterService = class InstanceAiBuilderDelegateAdapterService { constructor(agentsService, agentsBuilderService, n8nMemory, agentThreadRepository, agentConfig, agentSkills) { this.agentsService = agentsService; this.agentsBuilderService = agentsBuilderService; this.n8nMemory = n8nMemory; this.agentThreadRepository = agentThreadRepository; this.agentConfig = agentConfig; this.agentSkills = agentSkills; } buildSubAgentSession(session) { return { threadId: session.threadId, hostThreadId: session.hostThreadId, runId: session.runId, instructionsAddendum: exports.INSTANCE_AI_BUILDER_ADDENDUM, modelConfig: session.modelConfig, ...(session.telemetry ? { telemetry: session.telemetry } : {}), ...(session.memoryTaskObserver ? { memoryTaskObserver: session.memoryTaskObserver } : {}), abortSignal: session.abortSignal, }; } createDelegate(user, projectId, credentialProvider) { const assertProjectScope = async (scope) => { if (!(await (0, check_access_1.userHasScopes)(user, [scope], false, { projectId }))) { throw new forbidden_error_1.ForbiddenError('You do not have permission to access agents in this project.'); } }; return { createAgent: async (name, id) => { await assertProjectScope('agent:create'); const agent = await this.agentsService.create(projectId, name, { id, adoptUnconfiguredOnCollision: true, }); return { agentId: agent.id, projectId }; }, streamBuild: async (agentId, message, session) => { await assertProjectScope('agent:update'); return toBuilderTurnStream(this.agentsBuilderService.buildAgent(agentId, projectId, message, credentialProvider, user, this.buildSubAgentSession(session))); }, resumeBuild: async (agentId, resume, session) => { await assertProjectScope('agent:update'); return toBuilderTurnStream(this.agentsBuilderService.resumeBuild(agentId, projectId, resume.runId, resume.toolCallId, resume.resumeData, credentialProvider, user, this.buildSubAgentSession(session))); }, findOpenSuspensions: async (agentId, session) => { await assertProjectScope('agent:update'); const checkpoint = await this.agentsBuilderService.findOpenCheckpointForThread(agentId, session.threadId); if (!checkpoint) return []; return Object.values(checkpoint.pendingToolCalls ?? {}) .filter((tc) => tc.suspended) .map((tc) => ({ runId: tc.runId, toolCallId: tc.toolCallId })); }, cancelOpenSuspension: async (agentId, runId) => { await assertProjectScope('agent:update'); await this.agentsBuilderService.cancelCheckpoint(agentId, runId); }, listAgents: async () => { await assertProjectScope('agent:read'); const agents = await this.agentsService.findByProjectId(projectId); return agents.map((agent) => ({ agentId: agent.id, name: agent.name, published: agent.activeVersionId !== null, updatedAt: agent.updatedAt.toISOString(), })); }, resolveAgentName: async (agentId) => { await assertProjectScope('agent:read'); return (await this.agentsService.findById(agentId, projectId))?.name; }, readAgentArtifact: async (agentId) => { await assertProjectScope('agent:read'); const config = await this.agentConfig.getConfig(agentId, projectId).catch((error) => { if (error instanceof n8n_workflow_1.UserError) return null; throw error; }); if (!config) return null; return { config, skills: await this.agentSkills.listSkills(agentId, projectId), configHash: (0, agent_config_hash_1.getAgentConfigHash)(config), }; }, }; } async deleteBuilderSessions(instanceAiThreadId) { const prefix = (0, instance_ai_1.instanceAiBuilderThreadPrefix)(instanceAiThreadId); const threads = await this.agentThreadRepository.find({ select: { id: true }, where: { id: (0, typeorm_1.Like)(`${prefix}%`) }, }); for (const { id } of threads) { const memory = this.n8nMemory.getImplementation(id.slice(prefix.length)); await memory.deleteMessagesByThread(id); await memory.deleteThread(id); } } }; exports.InstanceAiBuilderDelegateAdapterService = InstanceAiBuilderDelegateAdapterService; exports.InstanceAiBuilderDelegateAdapterService = InstanceAiBuilderDelegateAdapterService = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [agents_service_1.AgentsService, agents_builder_service_1.AgentsBuilderService, n8n_memory_1.N8nMemory, agent_thread_repository_1.AgentThreadRepository, agent_config_service_1.AgentConfigService, agent_skills_service_1.AgentSkillsService]) ], InstanceAiBuilderDelegateAdapterService); //# sourceMappingURL=instance-ai-builder-delegate.adapter.js.map