{ "id": "A2F85aYzVDvQnUrc", "name": "Project Orchestrator", "nodes": [ { "parameters": { "jsCode": "// Get raw inputs\nconst inputItem = items[0].json;\nconst rawOutput = inputItem.stdout;\nconst rawError = inputItem.stderr || \"\";\n\n// If stdout is empty but stderr has content, the agent likely failed to start\nif (!rawOutput.trim() && rawError.trim()) {\n throw new Error(`OpenCode Agent failed to produce output. Error logs: ${rawError}`);\n}\n\ntry {\n // OpenCode outputs newline-delimited JSON (NDJSON)\n const lines = rawOutput.split('\\n').filter(line => line.trim() !== '');\n if (lines.length === 0) {\n throw new Error(\"No output events received from agent.\");\n }\n \n const events = lines.map(line => JSON.parse(line));\n\n // Extract text responses (agent's messages to user)\n const textEvents = events.filter(e => e.type === 'text');\n const response = textEvents.map(e => e.part?.text || '').join('\\n').trim();\n\n // Extract tool usage summary\n const toolEvents = events.filter(e => e.type === 'tool_use');\n const tools = toolEvents.map(e => ({\n tool: e.part?.tool,\n status: e.part?.state?.status,\n input: e.part?.state?.input\n }));\n\n // Extract step finish events for token/cost stats\n const stepFinishes = events.filter(e => e.type === 'step_finish');\n \n // Validation: If no steps finished and no text was produced, it's a failure\n if (stepFinishes.length === 0 && textEvents.length === 0) {\n throw new Error(\"Agent session ended prematurely without output.\");\n }\n\n const totalTokens = stepFinishes.reduce((acc, e) => {\n const t = e.part?.tokens || {};\n return {\n input: (acc.input || 0) + (t.input || 0),\n output: (acc.output || 0) + (t.output || 0),\n reasoning: (acc.reasoning || 0) + (t.reasoning || 0)\n };\n }, {});\n const totalCost = stepFinishes.reduce((acc, e) => acc + (e.part?.cost || 0), 0);\n\n // Get session info from first event\n const sessionID = events[0]?.sessionID || null;\n\n // Clean up logs\n const cleanLogs = rawError.split('\\n').filter(line => line.trim() !== '');\n\n return [{\n json: {\n response: response.replace(/\\n+/g, ' ').trim(),\n sessionID,\n stats: {\n exit_code: inputItem.code,\n signal: inputItem.signal,\n total_cost: totalCost,\n tokens: totalTokens,\n steps: stepFinishes.length,\n tool_calls: toolEvents.length\n },\n tools,\n cli_logs: cleanLogs\n }\n }];\n\n} catch (error) {\n // Fail the node if parsing or validation fails\n throw new Error(\"Failed to validate OpenCode output: \" + error.message);\n}\n" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -96, 48 ], "name": "Code in JavaScript", "id": "2dd84c9e-0fc0-4b34-911e-4a2cea1aae86" }, { "parameters": { "authentication": "privateKey", "command": "/home/b3nw/projects/core/project-orchestrator/bin/run-agent.sh", "cwd": "/home/b3nw/projects/" }, "type": "n8n-nodes-base.ssh", "position": [ -304, 48 ], "typeVersion": 1, "id": "f7a8fc32-699d-4e5b-afad-eb269855dbab", "name": "execute run_agent.sh", "credentials": { "sshPrivateKey": { "id": "S2dcVMjrpg0I0kdV", "name": "vscode-dev.local.ben.io" } } }, { "parameters": { "authentication": "privateKey", "command": "/home/b3nw/projects/core/project-orchestrator/bin/session-cleanup.sh", "cwd": "/home/b3nw/projects/core/project-orchestrator" }, "type": "n8n-nodes-base.ssh", "position": [ -304, -128 ], "typeVersion": 1, "id": "67e5e087-a6db-4013-87b3-a7fbb02421d1", "name": "execute cleanup_sessions.sh", "credentials": { "sshPrivateKey": { "id": "S2dcVMjrpg0I0kdV", "name": "vscode-dev.local.ben.io" } } }, { "parameters": { "rule": { "interval": [ { "daysInterval": 7, "triggerAtMinute": 30 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -528, -128 ], "id": "fc10c6c7-dd2c-4458-9d75-624f8a22124c", "name": "Weekly Trigger" }, { "parameters": { "rule": { "interval": [ {} ] } }, "name": "Nightly Trigger", "id": "343d37fc-f49d-4a30-969d-11abfed0594f", "position": [ -512, 48 ], "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3 } ], "connections": { "execute run_agent.sh": { "main": [ [ { "type": "main", "index": 0, "node": "Code in JavaScript" } ] ] }, "Weekly Trigger": { "main": [ [ { "node": "execute cleanup_sessions.sh", "type": "main", "index": 0 } ] ] }, "Nightly Trigger": { "main": [ [ { "node": "execute run_agent.sh", "index": 0, "type": "main" } ] ] } }, "settings": { "executionOrder": "v1", "callerPolicy": "workflowsFromSameOwner", "availableInMCP": false }, "triggerCount": 2, "versionId": "ae676149-56f0-4096-89d3-cdb6ab12fe44", "owner": { "type": "personal", "projectId": "FeLO36wNUAcn61Wj", "projectName": "Ben W ", "personalEmail": "admin@ben.io" }, "parentFolderId": "LTWZD96boqxk9sIs", "isArchived": false }