n8n-nodes-cribops 0.1.20 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -245
- package/dist/credentials/CribopsApi.credentials.js +3 -10
- package/dist/credentials/HiveApi.credentials.d.ts +7 -0
- package/dist/credentials/HiveApi.credentials.js +44 -0
- package/dist/nodes/Cribops/Cribops.node.d.ts +1 -6
- package/dist/nodes/Cribops/Cribops.node.js +343 -494
- package/dist/nodes/CribopsTrigger/CribopsTrigger.node.d.ts +1 -6
- package/dist/nodes/CribopsTrigger/CribopsTrigger.node.js +122 -140
- package/dist/nodes/HiveAccelerator/HiveAccelerator.node.d.ts +5 -0
- package/dist/nodes/HiveAccelerator/HiveAccelerator.node.js +461 -0
- package/dist/nodes/HiveAccelerator/hive.svg +7 -0
- package/dist/package.json +11 -5
- package/dist/utils/CribopsHttp.d.ts +190 -56
- package/dist/utils/CribopsHttp.js +100 -75
- package/dist/utils/HiveClient.d.ts +138 -0
- package/dist/utils/HiveClient.js +113 -0
- package/package.json +11 -5
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import { INodeType, INodeTypeDescription, IWebhookFunctions, IWebhookResponseData, IHookFunctions
|
|
1
|
+
import { INodeType, INodeTypeDescription, IWebhookFunctions, IWebhookResponseData, IHookFunctions } from 'n8n-workflow';
|
|
2
2
|
export declare class CribopsTrigger implements INodeType {
|
|
3
3
|
description: INodeTypeDescription;
|
|
4
|
-
methods: {
|
|
5
|
-
loadOptions: {
|
|
6
|
-
getWebhooks(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
7
|
-
};
|
|
8
|
-
};
|
|
9
4
|
webhookMethods: {
|
|
10
5
|
default: {
|
|
11
6
|
checkExists(this: IHookFunctions): Promise<boolean>;
|
|
@@ -5,14 +5,14 @@ const n8n_workflow_1 = require("n8n-workflow");
|
|
|
5
5
|
const CribopsHttp_1 = require("../../utils/CribopsHttp");
|
|
6
6
|
class CribopsTrigger {
|
|
7
7
|
description = {
|
|
8
|
-
displayName: 'Cribops Trigger',
|
|
8
|
+
displayName: 'Cribops Webhook Trigger',
|
|
9
9
|
name: 'cribopsTrigger',
|
|
10
10
|
icon: 'file:cribopstrigger.svg',
|
|
11
11
|
group: ['trigger'],
|
|
12
12
|
version: 1,
|
|
13
|
-
description: '
|
|
13
|
+
description: 'Receive webhooks from Cribops queue at a controlled rate',
|
|
14
14
|
defaults: {
|
|
15
|
-
name: 'Cribops Trigger',
|
|
15
|
+
name: 'Cribops Webhook Trigger',
|
|
16
16
|
},
|
|
17
17
|
inputs: [],
|
|
18
18
|
outputs: ["main" /* NodeConnectionType.Main */],
|
|
@@ -27,148 +27,128 @@ class CribopsTrigger {
|
|
|
27
27
|
name: 'default',
|
|
28
28
|
httpMethod: 'POST',
|
|
29
29
|
responseMode: 'onReceived',
|
|
30
|
-
path: '={{$parameter["
|
|
30
|
+
path: '={{$parameter["webhookPath"]}}',
|
|
31
31
|
isFullPath: false,
|
|
32
32
|
},
|
|
33
33
|
],
|
|
34
34
|
properties: [
|
|
35
35
|
{
|
|
36
|
-
displayName: 'Webhook
|
|
37
|
-
name: '
|
|
38
|
-
type: '
|
|
36
|
+
displayName: 'Webhook Path',
|
|
37
|
+
name: 'webhookPath',
|
|
38
|
+
type: 'string',
|
|
39
39
|
required: true,
|
|
40
|
-
typeOptions: {
|
|
41
|
-
loadOptionsMethod: 'getWebhooks',
|
|
42
|
-
},
|
|
43
40
|
default: '',
|
|
44
|
-
|
|
41
|
+
placeholder: 'my-webhook-endpoint',
|
|
42
|
+
description: 'The path for this webhook endpoint (will be appended to your n8n webhook URL)',
|
|
45
43
|
},
|
|
46
44
|
{
|
|
47
|
-
displayName: '
|
|
48
|
-
name: '
|
|
49
|
-
type: '
|
|
45
|
+
displayName: 'Options',
|
|
46
|
+
name: 'options',
|
|
47
|
+
type: 'collection',
|
|
48
|
+
placeholder: 'Add Option',
|
|
49
|
+
default: {},
|
|
50
50
|
options: [
|
|
51
51
|
{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
displayName: 'Include Cribops Metadata',
|
|
53
|
+
name: 'includeCribopsMetadata',
|
|
54
|
+
type: 'boolean',
|
|
55
|
+
default: true,
|
|
56
|
+
description: 'Include Cribops tracking ID, queue info, and processing metadata',
|
|
55
57
|
},
|
|
56
58
|
{
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
displayName: 'Include Original Headers',
|
|
60
|
+
name: 'includeHeaders',
|
|
61
|
+
type: 'boolean',
|
|
62
|
+
default: false,
|
|
63
|
+
description: 'Include the original webhook headers',
|
|
60
64
|
},
|
|
61
65
|
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
displayName: 'Report Performance',
|
|
67
|
+
name: 'reportPerformance',
|
|
68
|
+
type: 'boolean',
|
|
69
|
+
default: true,
|
|
70
|
+
description: 'Automatically report processing time back to Cribops',
|
|
65
71
|
},
|
|
66
72
|
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
displayName: 'Report Errors',
|
|
74
|
+
name: 'reportErrors',
|
|
75
|
+
type: 'boolean',
|
|
76
|
+
default: true,
|
|
77
|
+
description: 'Automatically report errors back to Cribops for monitoring',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
displayName: 'Validate Signature',
|
|
81
|
+
name: 'validateSignature',
|
|
82
|
+
type: 'boolean',
|
|
83
|
+
default: true,
|
|
84
|
+
description: 'Validate webhook signature from Cribops',
|
|
70
85
|
},
|
|
71
|
-
],
|
|
72
|
-
default: ['user_message', 'agent_response'],
|
|
73
|
-
description: 'Types of events to trigger on',
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
displayName: 'Additional Fields',
|
|
77
|
-
name: 'additionalFields',
|
|
78
|
-
type: 'collection',
|
|
79
|
-
placeholder: 'Add Field',
|
|
80
|
-
default: {},
|
|
81
|
-
options: [
|
|
82
86
|
{
|
|
83
|
-
displayName: 'Secret
|
|
84
|
-
name: '
|
|
87
|
+
displayName: 'Signature Secret',
|
|
88
|
+
name: 'signatureSecret',
|
|
85
89
|
type: 'string',
|
|
86
90
|
typeOptions: {
|
|
87
91
|
password: true,
|
|
88
92
|
},
|
|
93
|
+
displayOptions: {
|
|
94
|
+
show: {
|
|
95
|
+
validateSignature: [true],
|
|
96
|
+
},
|
|
97
|
+
},
|
|
89
98
|
default: '',
|
|
90
|
-
description: 'Secret
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
displayName: 'Include Headers',
|
|
94
|
-
name: 'includeHeaders',
|
|
95
|
-
type: 'boolean',
|
|
96
|
-
default: false,
|
|
97
|
-
description: 'Whether to include the webhook headers in the output',
|
|
99
|
+
description: 'Secret key shared with Cribops for signature validation',
|
|
98
100
|
},
|
|
99
101
|
],
|
|
100
102
|
},
|
|
101
103
|
],
|
|
102
104
|
};
|
|
103
|
-
methods = {
|
|
104
|
-
loadOptions: {
|
|
105
|
-
async getWebhooks() {
|
|
106
|
-
const credentials = await this.getCredentials('cribopsApi');
|
|
107
|
-
const cribopsHttp = new CribopsHttp_1.CribopsHttp({
|
|
108
|
-
baseUrl: credentials.baseUrl,
|
|
109
|
-
apiToken: credentials.apiToken,
|
|
110
|
-
});
|
|
111
|
-
try {
|
|
112
|
-
// Get organization ID from credentials if provided
|
|
113
|
-
const organizationId = credentials.organizationId;
|
|
114
|
-
const webhooks = await cribopsHttp.getWebhooks(organizationId);
|
|
115
|
-
// Filter for N8N type webhooks that are active and not linked
|
|
116
|
-
const availableWebhooks = webhooks.filter((webhook) => webhook.type === 'N8N' &&
|
|
117
|
-
webhook.status === 'active' &&
|
|
118
|
-
!webhook.linked_workflow_id);
|
|
119
|
-
return availableWebhooks.map((webhook) => ({
|
|
120
|
-
name: webhook.name,
|
|
121
|
-
value: webhook.id,
|
|
122
|
-
description: webhook.description || `Type: ${webhook.type}`,
|
|
123
|
-
}));
|
|
124
|
-
}
|
|
125
|
-
catch (error) {
|
|
126
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load webhooks: ${error instanceof Error ? error.message : String(error)}`);
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
};
|
|
131
105
|
webhookMethods = {
|
|
132
106
|
default: {
|
|
133
107
|
async checkExists() {
|
|
134
|
-
// Always return false to
|
|
135
|
-
// The actual webhook already exists in Cribops backend
|
|
108
|
+
// Always return false to ensure webhook is registered
|
|
136
109
|
return false;
|
|
137
110
|
},
|
|
138
111
|
async create() {
|
|
139
112
|
const webhookUrl = this.getNodeWebhookUrl('default');
|
|
140
|
-
const
|
|
113
|
+
const webhookPath = this.getNodeParameter('webhookPath');
|
|
114
|
+
const options = this.getNodeParameter('options');
|
|
141
115
|
const credentials = await this.getCredentials('cribopsApi');
|
|
142
116
|
const workflowId = this.getWorkflow().id;
|
|
143
117
|
const workflowName = this.getWorkflow().name;
|
|
118
|
+
if (!webhookPath) {
|
|
119
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Webhook path is required');
|
|
120
|
+
}
|
|
144
121
|
const cribopsHttp = new CribopsHttp_1.CribopsHttp({
|
|
145
122
|
baseUrl: credentials.baseUrl,
|
|
146
123
|
apiToken: credentials.apiToken,
|
|
147
124
|
});
|
|
148
125
|
try {
|
|
149
|
-
//
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
126
|
+
// Register this N8N endpoint with Cribops so it knows where to send webhooks
|
|
127
|
+
const registrationData = {
|
|
128
|
+
webhook_path: webhookPath,
|
|
129
|
+
n8n_webhook_url: webhookUrl,
|
|
153
130
|
test_webhook_url: webhookUrl.replace('/webhook/', '/webhook-test/'),
|
|
131
|
+
workflow_id: workflowId,
|
|
154
132
|
workflow_name: workflowName || 'Unnamed Workflow',
|
|
133
|
+
report_performance: options.reportPerformance !== false,
|
|
134
|
+
report_errors: options.reportErrors !== false,
|
|
135
|
+
signature_secret: options.signatureSecret ? String(options.signatureSecret) : null,
|
|
155
136
|
};
|
|
156
|
-
|
|
157
|
-
await cribopsHttp.request('POST', `/api/v1/webhooks/${webhookId}/link`, body);
|
|
137
|
+
await cribopsHttp.registerN8NEndpoint(registrationData);
|
|
158
138
|
// Store webhook data for later use
|
|
159
139
|
const webhookData = this.getWorkflowStaticData('node');
|
|
160
|
-
webhookData.
|
|
140
|
+
webhookData.webhookPath = webhookPath;
|
|
161
141
|
webhookData.webhookUrl = webhookUrl;
|
|
162
142
|
return true;
|
|
163
143
|
}
|
|
164
144
|
catch (error) {
|
|
165
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to
|
|
145
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to register N8N endpoint with Cribops: ${error instanceof Error ? error.message : String(error)}`);
|
|
166
146
|
}
|
|
167
147
|
},
|
|
168
148
|
async delete() {
|
|
169
149
|
const webhookData = this.getWorkflowStaticData('node');
|
|
170
150
|
const credentials = await this.getCredentials('cribopsApi');
|
|
171
|
-
if (!webhookData.
|
|
151
|
+
if (!webhookData.webhookPath) {
|
|
172
152
|
return true;
|
|
173
153
|
}
|
|
174
154
|
const cribopsHttp = new CribopsHttp_1.CribopsHttp({
|
|
@@ -176,15 +156,15 @@ class CribopsTrigger {
|
|
|
176
156
|
apiToken: credentials.apiToken,
|
|
177
157
|
});
|
|
178
158
|
try {
|
|
179
|
-
//
|
|
180
|
-
await cribopsHttp.
|
|
181
|
-
delete webhookData.
|
|
159
|
+
// Unregister the N8N endpoint
|
|
160
|
+
await cribopsHttp.unregisterN8NEndpoint(webhookData.webhookPath);
|
|
161
|
+
delete webhookData.webhookPath;
|
|
182
162
|
delete webhookData.webhookUrl;
|
|
183
163
|
return true;
|
|
184
164
|
}
|
|
185
165
|
catch (error) {
|
|
186
166
|
// Log error but don't fail
|
|
187
|
-
console.error('Failed to
|
|
167
|
+
console.error('Failed to unregister N8N endpoint:', error);
|
|
188
168
|
return true;
|
|
189
169
|
}
|
|
190
170
|
},
|
|
@@ -193,68 +173,70 @@ class CribopsTrigger {
|
|
|
193
173
|
async webhook() {
|
|
194
174
|
const body = this.getBodyData();
|
|
195
175
|
const headers = this.getHeaderData();
|
|
196
|
-
const
|
|
197
|
-
const
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
if (
|
|
201
|
-
|
|
202
|
-
const signature = headers['x-cribops-signature']
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
// For now, simple token comparison
|
|
206
|
-
if (additionalFields.secretToken !== signature && `Bearer ${additionalFields.secretToken}` !== authHeader) {
|
|
176
|
+
const options = this.getNodeParameter('options');
|
|
177
|
+
const webhookPath = this.getNodeParameter('webhookPath');
|
|
178
|
+
const credentials = await this.getCredentials('cribopsApi');
|
|
179
|
+
const startTime = Date.now();
|
|
180
|
+
// Validate signature if enabled (Cribops signs webhooks it sends)
|
|
181
|
+
if (options.validateSignature) {
|
|
182
|
+
const signature = headers['x-cribops-signature'];
|
|
183
|
+
const secret = options.signatureSecret;
|
|
184
|
+
if (!signature) {
|
|
207
185
|
return {
|
|
208
186
|
webhookResponse: {
|
|
209
187
|
status: 401,
|
|
210
|
-
body: { error: '
|
|
188
|
+
body: { error: 'Missing Cribops signature' },
|
|
211
189
|
},
|
|
212
190
|
};
|
|
213
191
|
}
|
|
192
|
+
// TODO: Implement HMAC validation with shared secret
|
|
214
193
|
}
|
|
215
|
-
//
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
194
|
+
// Extract Cribops metadata from the webhook
|
|
195
|
+
const cribopsMetadata = {
|
|
196
|
+
webhook_id: body.webhook_id || headers['x-cribops-webhook-id'],
|
|
197
|
+
queue_name: body.queue_name || headers['x-cribops-queue'],
|
|
198
|
+
original_source: body.original_source || headers['x-cribops-source'],
|
|
199
|
+
received_at: body.received_at || headers['x-cribops-received-at'],
|
|
200
|
+
attempt_number: body.attempt_number || headers['x-cribops-attempt'] || 1,
|
|
201
|
+
};
|
|
202
|
+
// Prepare webhook data
|
|
203
|
+
const webhookData = {
|
|
204
|
+
// The actual webhook payload
|
|
205
|
+
payload: body.payload || body,
|
|
206
|
+
// Processing metadata
|
|
207
|
+
processed_at: new Date().toISOString(),
|
|
208
|
+
webhook_path: webhookPath,
|
|
209
|
+
};
|
|
210
|
+
// Include Cribops metadata if requested
|
|
211
|
+
if (options.includeCribopsMetadata !== false) {
|
|
212
|
+
webhookData.cribops = cribopsMetadata;
|
|
213
|
+
}
|
|
214
|
+
// Include original headers if requested
|
|
215
|
+
if (options.includeHeaders) {
|
|
216
|
+
webhookData.original_headers = body.original_headers || headers;
|
|
217
|
+
}
|
|
218
|
+
// Track processing time for performance reporting
|
|
219
|
+
const processingTime = Date.now() - startTime;
|
|
220
|
+
// If performance reporting is enabled, we'll report after workflow completes
|
|
221
|
+
if (options.reportPerformance !== false && cribopsMetadata.webhook_id) {
|
|
222
|
+
// Store for later reporting
|
|
223
|
+
const staticData = this.getWorkflowStaticData('node');
|
|
224
|
+
staticData.performanceTracking = {
|
|
225
|
+
webhook_id: cribopsMetadata.webhook_id,
|
|
226
|
+
start_time: startTime,
|
|
227
|
+
receive_time: processingTime,
|
|
223
228
|
};
|
|
224
229
|
}
|
|
225
|
-
// Prepare output data with all relevant fields
|
|
226
|
-
const outputData = {
|
|
227
|
-
// Core webhook data
|
|
228
|
-
webhook_id: webhookId,
|
|
229
|
-
event_type: eventType,
|
|
230
|
-
// Message content
|
|
231
|
-
message: body.message || body.content || body.text,
|
|
232
|
-
// Conversation/thread tracking
|
|
233
|
-
conversation_id: body.conversation_id || body.conversationId || body.thread_id || body.threadId,
|
|
234
|
-
// User/agent identification
|
|
235
|
-
user_id: body.user_id || body.userId || body.from_user || body.fromUser,
|
|
236
|
-
agent_id: body.agent_id || body.agentId || body.to_agent || body.toAgent,
|
|
237
|
-
// Response handling
|
|
238
|
-
response_webhook: body.response_webhook || body.responseWebhook || body.callback_url || body.callbackUrl,
|
|
239
|
-
// Metadata
|
|
240
|
-
metadata: body.metadata || {},
|
|
241
|
-
// File attachments if any
|
|
242
|
-
attachments: body.attachments || body.files || [],
|
|
243
|
-
// Timestamp
|
|
244
|
-
timestamp: body.timestamp || body.created_at || body.createdAt || new Date().toISOString(),
|
|
245
|
-
// Include any other fields from the webhook
|
|
246
|
-
...body,
|
|
247
|
-
};
|
|
248
|
-
// Include headers if requested
|
|
249
|
-
const workflowData = additionalFields.includeHeaders
|
|
250
|
-
? { json: outputData, headers }
|
|
251
|
-
: { json: outputData };
|
|
252
230
|
// Return the data to the workflow
|
|
253
231
|
return {
|
|
254
|
-
workflowData: [[
|
|
232
|
+
workflowData: [[{ json: webhookData }]],
|
|
255
233
|
webhookResponse: {
|
|
256
234
|
status: 200,
|
|
257
|
-
body: {
|
|
235
|
+
body: {
|
|
236
|
+
received: true,
|
|
237
|
+
webhook_id: cribopsMetadata.webhook_id,
|
|
238
|
+
processing_time_ms: processingTime,
|
|
239
|
+
},
|
|
258
240
|
},
|
|
259
241
|
};
|
|
260
242
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
2
|
+
export declare class HiveAccelerator implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
|
+
}
|