extract_code
Extract code nodes from workflows into separate files for improved editing and organization.
Instructions
Extract code nodes to separate files in workflows/nodes/ for better editing
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| workflow | No | Specific workflow to extract code from (optional, extracts all if not specified) |
Implementation Reference
- src/tools/handler.ts:202-222 (handler)ToolHandler.handleTool switch case for 'extract_code': initializes NodeManager and calls extractNodes for specific workflow or extractAllNodes for all, returning formatted text response.case 'extract_code': const codeManager = new NodeManager(this.workflowsPath); await codeManager.initialize(); const workflowToExtract = args?.workflow as string | undefined; if (workflowToExtract) { const workflowPath = path.join(this.workflowsPath, 'flows', `${workflowToExtract}.json`); const result = await codeManager.extractNodes(workflowPath); return { content: [{ type: 'text', text: result.extracted.length > 0 ? `✅ Extracted ${result.extracted.length} code nodes from ${workflowToExtract}\n\n` + result.extracted.map((n: any) => `• ${n.nodeName} → ${n.filePath}`).join('\n') : `📭 No code nodes found in ${workflowToExtract}` }] }; } else { return await codeManager.extractAllNodes(); }
- src/tools/registry.ts:351-359 (schema)Input schema for 'extract_code' tool: optional 'workflow' string parameter.inputSchema: { type: 'object', properties: { workflow: { type: 'string', description: 'Specific workflow to extract code from (optional, extracts all if not specified)', }, }, },
- src/tools/registry.ts:348-360 (registration)Registration of 'extract_code' tool in getToolDefinitions() array, including name, description, and inputSchema.{ name: 'extract_code', description: 'Extract code nodes to separate files in workflows/nodes/ for better editing', inputSchema: { type: 'object', properties: { workflow: { type: 'string', description: 'Specific workflow to extract code from (optional, extracts all if not specified)', }, }, }, },
- src/nodes/manager.ts:64-129 (helper)NodeManager.extractNodes(): core logic to parse workflow, identify extractable nodes (code, LLM prompts, SQL, templates, JSON), extract content to files in workflows/nodes/, replace with file refs in workflow, update metadata.async extractNodes(workflowPath: string): Promise<{ extracted: ExtractedNode[]; modified: boolean; }> { const content = await fs.readFile(workflowPath, 'utf-8'); const workflow = JSON.parse(content); const workflowName = path.basename(workflowPath, '.json'); const extracted: ExtractedNode[] = []; let modified = false; if (!workflow.nodes) { return { extracted, modified }; } for (const node of workflow.nodes) { let result: ExtractedNode | null = null; // Check node type and extract accordingly switch (node.type) { case 'n8n-nodes-base.code': result = await this.extractCodeNode(node, workflowName); break; case 'n8n-nodes-base.openAi': case '@n8n/n8n-nodes-langchain.openAi': case 'n8n-nodes-base.anthropic': case '@n8n/n8n-nodes-langchain.anthropic': case 'n8n-nodes-base.googleAi': case '@n8n/n8n-nodes-langchain.googleAi': result = await this.extractLLMNode(node, workflowName); break; case 'n8n-nodes-base.postgres': case 'n8n-nodes-base.mysql': case 'n8n-nodes-base.microsoftSql': result = await this.extractSQLNode(node, workflowName); break; case 'n8n-nodes-base.html': case 'n8n-nodes-base.emailSend': result = await this.extractTemplateNode(node, workflowName); break; case 'n8n-nodes-base.httpRequest': // Try to extract JSON configuration result = await this.extractJSONNode(node, workflowName); break; } if (result) { extracted.push(result); modified = true; } } if (modified) { // Save modified workflow with references await fs.writeFile(workflowPath, JSON.stringify(workflow, null, 2)); } // Update metadata await this.updateMetadata(workflowName, extracted); return { extracted, modified }; }
- src/nodes/manager.ts:536-560 (helper)NodeManager.extractAllNodes(): iterates over all workflow JSON files, calls extractNodes on each, collects results and formats response for tool.async extractAllNodes(): Promise<any> { const flowsDir = path.join(this.workflowsPath, 'flows'); const files = await fs.readdir(flowsDir); const results = []; for (const file of files) { if (file.endsWith('.json') && !file.includes('package.json')) { const filePath = path.join(flowsDir, file); const result = await this.extractNodes(filePath); if (result.extracted.length > 0) { results.push({ workflow: file.replace('.json', ''), extracted: result.extracted }); } } } return { content: [{ type: 'text', text: this.formatExtractionResults(results) }] }; }