UNPKG

n8n-nodes-handit

Version:

n8n community nodes for Handit tracing and prompt management

261 lines 13.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HanditTracing = void 0; const n8n_workflow_1 = require("n8n-workflow"); class HanditTracing { constructor() { this.description = { displayName: 'Handit Tracing', name: 'handitTracing', icon: 'file:handit.svg', group: ['transform'], version: 1, description: 'Collect workflow data and send to Handit API for tracing with enhanced node type support', defaults: { name: 'Handit Tracing', }, inputs: ["main"], outputs: ["main"], credentials: [ { name: 'handitApi', required: true, }, ], properties: [ { displayName: 'Operation', name: 'operation', type: 'options', options: [ { name: 'Trace Workflow', value: 'trace', description: 'Collect and send workflow data to Handit API', action: 'Trace workflow data', }, ], default: 'trace', noDataExpression: true, }, { displayName: 'Agent Name', name: 'agentName', type: 'string', default: 'demo agent', required: true, description: 'Name of the agent for tracing', displayOptions: { show: { operation: ['trace'], }, }, }, { displayName: 'Workflow Structure', name: 'workflowStructure', type: 'json', default: '{\n "Edit Fields": {\n "type": "tool",\n "inputs": []\n },\n "AI Agent": {\n "type": "llm",\n "inputs": ["Edit Fields"]\n }\n}', required: true, description: 'JSON object defining the workflow structure with node types and dependencies (parameters will be auto-captured)', displayOptions: { show: { operation: ['trace'], }, }, }, { displayName: 'API URL', name: 'apiUrl', type: 'string', default: 'https://handit-api-oss-299768392189.us-central1.run.app/api/track/bulk', description: 'Custom API endpoint URL (leave empty to use the default Handit API endpoint)', displayOptions: { show: { operation: ['trace'], }, }, }, ], }; } async execute() { const items = this.getInputData(); const returnData = []; const operation = this.getNodeParameter('operation', 0); if (operation === 'trace') { for (let i = 0; i < items.length; i++) { try { const agentName = this.getNodeParameter('agentName', i); const workflowStructureInput = this.getNodeParameter('workflowStructure', i); const apiUrl = this.getNodeParameter('apiUrl', i); const credentials = await this.getCredentials('handitApi'); if (!(credentials === null || credentials === void 0 ? void 0 : credentials.apiToken)) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Handit API credentials are required'); } let workflowStructure; try { workflowStructure = JSON.parse(workflowStructureInput); } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid JSON in workflow structure: ${error.message}`); } let workflowDataArray = []; try { function getAllNodes() { const allNodes = new Set(); Object.keys(workflowStructure).forEach(node => allNodes.add(node)); Object.values(workflowStructure).forEach(nodeConfig => { if (nodeConfig.inputs && Array.isArray(nodeConfig.inputs)) { nodeConfig.inputs.forEach(inputNode => allNodes.add(inputNode)); } }); return Array.from(allNodes); } const nodes = getAllNodes(); function resolveAllExpressions(value, inputData, allNodesData) { if (typeof value === 'string') { const regex = /{{\s*(.*?)\s*}}/g; return value.replace(regex, (_, code) => { try { const $json = inputData || {}; const $node = (nodeName) => ({ json: allNodesData[nodeName] || {} }); const contextFunction = new Function('$json', '$node', `return ${code}`); return contextFunction($json, $node); } catch (e) { return `{{ ${code} }}`; } }); } else if (Array.isArray(value)) { return value.map((item) => resolveAllExpressions(item, inputData, allNodesData)); } else if (value !== null && typeof value === 'object') { return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, resolveAllExpressions(v, inputData, allNodesData)])); } return value; } function findInputSource(currentNode, allNodesData) { const nodeConfig = workflowStructure[currentNode]; const possibleSources = (nodeConfig === null || nodeConfig === void 0 ? void 0 : nodeConfig.inputs) || []; for (const sourceNode of possibleSources) { if (allNodesData[sourceNode] && Object.keys(allNodesData[sourceNode]).length > 0) { return allNodesData[sourceNode]; } } return {}; } const allNodesData = {}; const inputData = this.getInputData(); for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; try { allNodesData[node] = inputData && inputData.length > 0 ? inputData[0].json || {} : {}; } catch (e) { allNodesData[node] = {}; } } for (let j = 0; j < nodes.length; j++) { const node = nodes[j]; const nodeConfig = workflowStructure[node]; const nodeType = nodeConfig ? nodeConfig.type : 'tool'; let output = {}; let previousSteps = {}; try { const inputData = this.getInputData(); if (inputData && inputData.length > 0) { output = inputData[0].json || {}; if (output['intermediateSteps']) { previousSteps = output['intermediateSteps']; delete output['intermediateSteps']; } } } catch (e) { } let nodeParameters = {}; let captureMethod = 'unknown'; try { const workflowProxy = this.getWorkflowDataProxy(0); if (workflowProxy && workflowProxy.$ && typeof workflowProxy.$ === 'function') { try { const nodeProxy = workflowProxy.$(node); if (nodeProxy && nodeProxy.params) { const rawParameters = JSON.parse(JSON.stringify(nodeProxy.params)) || {}; const inputData = findInputSource(node, allNodesData); nodeParameters = resolveAllExpressions(rawParameters, inputData, allNodesData); captureMethod = 'node_params_via_proxy_resolved'; } } catch (nodeError) { } } } catch (e) { } if (Object.keys(nodeParameters).length === 0) { const inputData = this.getInputData(); if (inputData && inputData.length > 0) { nodeParameters = inputData[0].json || {}; captureMethod = 'input_data_fallback'; } } const input = { ...nodeParameters, _captured_at: new Date().toISOString(), _node_type: nodeType, _input_sources: (nodeConfig === null || nodeConfig === void 0 ? void 0 : nodeConfig.inputs) || [], _capture_method: captureMethod, previousSteps, }; workflowDataArray.push({ nodeName: node, input: input, nodeType: nodeType, output: output || {}, }); } } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Error processing workflow data: ${error.message}`); } const dataToSend = { workflowData: workflowDataArray.filter((item) => item.output && typeof item.output === 'object' && Object.keys(item.output).length > 0), agentName: agentName, }; const requestOptions = { method: 'POST', url: apiUrl || 'https://handit-api-oss-299768392189.us-central1.run.app/api/track/bulk', body: dataToSend, json: true, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${credentials.apiToken}`, }, }; const response = await this.helpers.httpRequest(requestOptions); returnData.push({ success: true, message: 'Data sent successfully', response: response, data: dataToSend, }); } catch (error) { returnData.push({ success: false, error: error.message, data: {}, }); } } } return [this.helpers.returnJsonArray(returnData)]; } } exports.HanditTracing = HanditTracing; //# sourceMappingURL=HanditTracing.node.js.map