n8n-nodes-cribops 0.1.17 → 0.1.18

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.
@@ -1,9 +1,9 @@
1
- import { INodeType, INodeTypeDescription, ITriggerFunctions, ITriggerResponse, IWebhookFunctions, IWebhookResponseData, IHookFunctions, ILoadOptionsFunctions, INodePropertyOptions } from 'n8n-workflow';
1
+ import { INodeType, INodeTypeDescription, IWebhookFunctions, IWebhookResponseData, IHookFunctions, ILoadOptionsFunctions, INodePropertyOptions } from 'n8n-workflow';
2
2
  export declare class CribopsTrigger implements INodeType {
3
3
  description: INodeTypeDescription;
4
4
  methods: {
5
5
  loadOptions: {
6
- getAgents(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
6
+ getWebhooks(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
7
7
  };
8
8
  };
9
9
  webhookMethods: {
@@ -13,6 +13,5 @@ export declare class CribopsTrigger implements INodeType {
13
13
  delete(this: IHookFunctions): Promise<boolean>;
14
14
  };
15
15
  };
16
- trigger(this: ITriggerFunctions): Promise<ITriggerResponse>;
17
16
  webhook(this: IWebhookFunctions): Promise<IWebhookResponseData>;
18
17
  }
@@ -10,7 +10,7 @@ class CribopsTrigger {
10
10
  icon: 'file:cribopstrigger.svg',
11
11
  group: ['trigger'],
12
12
  version: 1,
13
- description: 'Triggers when receiving messages from Cribops agents',
13
+ description: 'Triggers when receiving messages via Cribops webhook',
14
14
  defaults: {
15
15
  name: 'Cribops Trigger',
16
16
  },
@@ -27,92 +27,21 @@ class CribopsTrigger {
27
27
  name: 'default',
28
28
  httpMethod: 'POST',
29
29
  responseMode: 'onReceived',
30
- // Dynamic path to trigger UUID generation
31
- path: '={{$parameter["agentId"]}}',
32
- isFullPath: true,
30
+ path: '={{$parameter["webhookId"]}}',
31
+ isFullPath: false,
33
32
  },
34
33
  ],
35
- polling: true,
36
34
  properties: [
37
35
  {
38
- displayName: 'Trigger Mode',
39
- name: 'triggerMode',
36
+ displayName: 'Webhook Name or ID',
37
+ name: 'webhookId',
40
38
  type: 'options',
41
- options: [
42
- {
43
- name: 'Polling',
44
- value: 'polling',
45
- description: 'Poll the queue for messages at regular intervals',
46
- },
47
- {
48
- name: 'Webhook',
49
- value: 'webhook',
50
- description: 'Receive messages via webhook',
51
- },
52
- ],
53
- default: 'polling',
54
- description: 'How to receive messages from Cribops',
55
- },
56
- {
57
- displayName: 'Tenant ID',
58
- name: 'tenantId',
59
- type: 'string',
60
39
  required: true,
61
- default: '',
62
- description: 'The tenant ID for your Cribops organization',
63
- },
64
- {
65
- displayName: 'Agent Name or ID',
66
- name: 'agentId',
67
- type: 'options',
68
- required: true,
69
- displayOptions: {
70
- show: {
71
- triggerMode: ['webhook'],
72
- },
73
- },
74
40
  typeOptions: {
75
- loadOptionsMethod: 'getAgents',
41
+ loadOptionsMethod: 'getWebhooks',
76
42
  },
77
43
  default: '',
78
- description: 'The Cribops agent to receive messages from. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
79
- },
80
- {
81
- displayName: 'Queue Name',
82
- name: 'queueName',
83
- type: 'string',
84
- displayOptions: {
85
- show: {
86
- triggerMode: ['polling'],
87
- },
88
- },
89
- default: '',
90
- placeholder: 'e.g., stripe_events',
91
- description: 'Specific queue to poll (optional). Leave empty to poll all queues.',
92
- },
93
- {
94
- displayName: 'Poll Interval',
95
- name: 'pollInterval',
96
- type: 'number',
97
- displayOptions: {
98
- show: {
99
- triggerMode: ['polling'],
100
- },
101
- },
102
- default: 30,
103
- description: 'How often to poll for messages in seconds',
104
- },
105
- {
106
- displayName: 'Batch Size',
107
- name: 'batchSize',
108
- type: 'number',
109
- displayOptions: {
110
- show: {
111
- triggerMode: ['polling'],
112
- },
113
- },
114
- default: 10,
115
- description: 'Number of messages to retrieve per poll (max 100)',
44
+ description: 'The Cribops webhook to use. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
116
45
  },
117
46
  {
118
47
  displayName: 'Event Types',
@@ -134,8 +63,13 @@ class CribopsTrigger {
134
63
  value: 'file_attachment',
135
64
  description: 'File attachments',
136
65
  },
66
+ {
67
+ name: 'System Event',
68
+ value: 'system_event',
69
+ description: 'System events and notifications',
70
+ },
137
71
  ],
138
- default: ['user_message'],
72
+ default: ['user_message', 'agent_response'],
139
73
  description: 'Types of events to trigger on',
140
74
  },
141
75
  {
@@ -153,7 +87,14 @@ class CribopsTrigger {
153
87
  password: true,
154
88
  },
155
89
  default: '',
156
- description: 'Secret token for webhook authentication',
90
+ description: 'Secret token for webhook signature validation',
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',
157
98
  },
158
99
  ],
159
100
  },
@@ -161,22 +102,25 @@ class CribopsTrigger {
161
102
  };
162
103
  methods = {
163
104
  loadOptions: {
164
- async getAgents() {
105
+ async getWebhooks() {
165
106
  const credentials = await this.getCredentials('cribopsApi');
166
107
  const cribopsHttp = new CribopsHttp_1.CribopsHttp({
167
108
  baseUrl: credentials.baseUrl,
168
109
  apiToken: credentials.apiToken,
169
110
  });
170
111
  try {
171
- const agents = await cribopsHttp.getAgents();
172
- return agents.map((agent) => ({
173
- name: agent.name,
174
- value: agent.id,
175
- description: `ID: ${agent.id}`,
112
+ // Call the API to get available webhooks
113
+ // The API endpoint would be something like GET /api/v1/webhooks
114
+ const response = await cribopsHttp.request('GET', '/api/v1/webhooks');
115
+ const webhooks = response.data || [];
116
+ return webhooks.map((webhook) => ({
117
+ name: webhook.name || webhook.id,
118
+ value: webhook.id,
119
+ description: webhook.description || `Webhook ID: ${webhook.id}`,
176
120
  }));
177
121
  }
178
122
  catch (error) {
179
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load agents: ${error instanceof Error ? error.message : String(error)}`);
123
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load webhooks: ${error instanceof Error ? error.message : String(error)}`);
180
124
  }
181
125
  },
182
126
  },
@@ -184,26 +128,13 @@ class CribopsTrigger {
184
128
  webhookMethods = {
185
129
  default: {
186
130
  async checkExists() {
187
- const webhookUrl = this.getNodeWebhookUrl('default');
188
- const agentId = this.getNodeParameter('agentId');
189
- const credentials = await this.getCredentials('cribopsApi');
190
- const cribopsHttp = new CribopsHttp_1.CribopsHttp({
191
- baseUrl: credentials.baseUrl,
192
- apiToken: credentials.apiToken,
193
- });
194
- try {
195
- // Check if webhook exists for this agent
196
- // This would need to be implemented in your Cribops API
197
- // For now, return false to always create
198
- return false;
199
- }
200
- catch (error) {
201
- return false;
202
- }
131
+ // Always return false to create webhook registration
132
+ // The actual webhook already exists in Cribops backend
133
+ return false;
203
134
  },
204
135
  async create() {
205
136
  const webhookUrl = this.getNodeWebhookUrl('default');
206
- const agentId = this.getNodeParameter('agentId');
137
+ const webhookId = this.getNodeParameter('webhookId');
207
138
  const eventTypes = this.getNodeParameter('eventTypes', []);
208
139
  const additionalFields = this.getNodeParameter('additionalFields', {});
209
140
  const credentials = await this.getCredentials('cribopsApi');
@@ -212,30 +143,29 @@ class CribopsTrigger {
212
143
  apiToken: credentials.apiToken,
213
144
  });
214
145
  try {
215
- // Register webhook with Cribops
216
- // This is a placeholder - implement actual API call
146
+ // Register this n8n webhook URL with the Cribops webhook
217
147
  const body = {
218
- url: webhookUrl,
219
- agent_id: agentId,
148
+ webhook_id: webhookId,
149
+ target_url: webhookUrl,
220
150
  event_types: eventTypes,
221
151
  secret: additionalFields.secretToken || undefined,
222
152
  };
223
- // TODO: Make actual API call to register webhook
224
- // await cribopsHttp.registerWebhook(agentId, body);
153
+ // Register the n8n webhook URL with Cribops
154
+ await cribopsHttp.request('POST', `/api/v1/webhooks/${webhookId}/targets`, body);
225
155
  // Store webhook data for later use
226
156
  const webhookData = this.getWorkflowStaticData('node');
227
- webhookData.webhookId = `webhook_${agentId}_${Date.now()}`;
228
- webhookData.agentId = agentId;
157
+ webhookData.webhookId = webhookId;
158
+ webhookData.targetUrl = webhookUrl;
229
159
  return true;
230
160
  }
231
161
  catch (error) {
232
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to register webhook: ${error instanceof Error ? error.message : String(error)}`);
162
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to register webhook target: ${error instanceof Error ? error.message : String(error)}`);
233
163
  }
234
164
  },
235
165
  async delete() {
236
166
  const webhookData = this.getWorkflowStaticData('node');
237
167
  const credentials = await this.getCredentials('cribopsApi');
238
- if (!webhookData.webhookId) {
168
+ if (!webhookData.webhookId || !webhookData.targetUrl) {
239
169
  return true;
240
170
  }
241
171
  const cribopsHttp = new CribopsHttp_1.CribopsHttp({
@@ -243,118 +173,36 @@ class CribopsTrigger {
243
173
  apiToken: credentials.apiToken,
244
174
  });
245
175
  try {
246
- // Unregister webhook from Cribops
247
- // TODO: Make actual API call to unregister webhook
248
- // await cribopsHttp.deleteWebhook(webhookData.agentId, webhookData.webhookId);
176
+ // Unregister the n8n webhook URL from Cribops
177
+ await cribopsHttp.request('DELETE', `/api/v1/webhooks/${webhookData.webhookId}/targets`, {
178
+ target_url: webhookData.targetUrl,
179
+ });
249
180
  delete webhookData.webhookId;
250
- delete webhookData.agentId;
181
+ delete webhookData.targetUrl;
251
182
  return true;
252
183
  }
253
184
  catch (error) {
254
- return false;
185
+ // Log error but don't fail
186
+ console.error('Failed to unregister webhook target:', error);
187
+ return true;
255
188
  }
256
189
  },
257
190
  },
258
191
  };
259
- async trigger() {
260
- const triggerMode = this.getNodeParameter('triggerMode');
261
- if (triggerMode === 'webhook') {
262
- // Webhook mode - minimal implementation as webhooks are handled by webhook() method
263
- return {
264
- closeFunction: async () => { },
265
- manualTriggerFunction: async () => {
266
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'This node only works with webhooks in webhook mode. Please activate the workflow.');
267
- },
268
- };
269
- }
270
- // Polling mode
271
- const credentials = await this.getCredentials('cribopsApi');
272
- const tenantId = this.getNodeParameter('tenantId');
273
- const pollInterval = this.getNodeParameter('pollInterval', 30);
274
- const batchSize = this.getNodeParameter('batchSize', 10);
275
- const queueName = this.getNodeParameter('queueName', '') || undefined;
276
- const cribopsHttp = new CribopsHttp_1.CribopsHttp({
277
- baseUrl: credentials.baseUrl,
278
- apiToken: credentials.apiToken,
279
- });
280
- let intervalId;
281
- const poll = async () => {
282
- try {
283
- const messages = await cribopsHttp.pollQueue(tenantId, batchSize, queueName);
284
- if (messages.length > 0) {
285
- const messageIds = messages.map(msg => msg.id);
286
- // Process each message
287
- for (const message of messages) {
288
- // Parse the webhook data if it's JSON
289
- let parsedData = message.data.data;
290
- try {
291
- parsedData = JSON.parse(message.data.data);
292
- }
293
- catch (e) {
294
- // Keep as string if not valid JSON
295
- }
296
- // Emit the message
297
- this.emit([
298
- [
299
- {
300
- json: {
301
- id: message.id,
302
- correlation_id: message.correlation_id,
303
- queue_name: message.queue_name,
304
- data: parsedData,
305
- headers: message.data.headers,
306
- params: message.data.params,
307
- inserted_at: message.inserted_at,
308
- // Extract useful fields from headers
309
- tenant_id: message.data.headers['x-cribops-tenant-id'] || tenantId,
310
- path: message.data.headers['x-cribops-path'],
311
- },
312
- },
313
- ],
314
- ]);
315
- }
316
- // Acknowledge messages after processing
317
- try {
318
- await cribopsHttp.acknowledgeMessages(tenantId, messageIds);
319
- }
320
- catch (ackError) {
321
- console.error('Failed to acknowledge messages:', ackError);
322
- }
323
- }
324
- }
325
- catch (error) {
326
- console.error('Polling error:', error);
327
- // Don't throw - continue polling
328
- }
329
- };
330
- // Start polling
331
- poll(); // Initial poll
332
- intervalId = setInterval(poll, pollInterval * 1000);
333
- // Manual trigger function for testing
334
- const manualTriggerFunction = async () => {
335
- await poll();
336
- };
337
- // Cleanup function
338
- const closeFunction = async () => {
339
- if (intervalId) {
340
- clearInterval(intervalId);
341
- }
342
- };
343
- return {
344
- closeFunction,
345
- manualTriggerFunction,
346
- };
347
- }
348
192
  async webhook() {
349
193
  const body = this.getBodyData();
350
194
  const headers = this.getHeaderData();
351
195
  const eventTypes = this.getNodeParameter('eventTypes', []);
352
196
  const additionalFields = this.getNodeParameter('additionalFields', {});
353
- const agentId = this.getNodeParameter('agentId');
197
+ const webhookId = this.getNodeParameter('webhookId');
354
198
  // Validate secret token if provided
355
199
  if (additionalFields.secretToken) {
356
- const receivedToken = headers['x-cribops-signature'] || headers['authorization'];
357
- if (receivedToken !== additionalFields.secretToken) {
200
+ // Check for signature in headers (could be HMAC signature or bearer token)
201
+ const signature = headers['x-cribops-signature'] || headers['x-webhook-signature'];
202
+ const authHeader = headers['authorization'];
203
+ // You can implement HMAC signature validation here if needed
204
+ // For now, simple token comparison
205
+ if (additionalFields.secretToken !== signature && `Bearer ${additionalFields.secretToken}` !== authHeader) {
358
206
  return {
359
207
  webhookResponse: {
360
208
  status: 401,
@@ -363,8 +211,9 @@ class CribopsTrigger {
363
211
  };
364
212
  }
365
213
  }
366
- // Filter by event type
367
- if (eventTypes.length > 0 && body.type && !eventTypes.includes(body.type)) {
214
+ // Filter by event type if specified
215
+ const eventType = body.event_type || body.type || body.eventType;
216
+ if (eventTypes.length > 0 && eventType && !eventTypes.includes(eventType)) {
368
217
  return {
369
218
  webhookResponse: {
370
219
  status: 200,
@@ -372,27 +221,40 @@ class CribopsTrigger {
372
221
  },
373
222
  };
374
223
  }
375
- // Enrich the output with agent_id and other useful metadata
224
+ // Prepare output data with all relevant fields
376
225
  const outputData = {
226
+ // Core webhook data
227
+ webhook_id: webhookId,
228
+ event_type: eventType,
229
+ // Message content
230
+ message: body.message || body.content || body.text,
231
+ // Conversation/thread tracking
232
+ conversation_id: body.conversation_id || body.conversationId || body.thread_id || body.threadId,
233
+ // User/agent identification
234
+ user_id: body.user_id || body.userId || body.from_user || body.fromUser,
235
+ agent_id: body.agent_id || body.agentId || body.to_agent || body.toAgent,
236
+ // Response handling
237
+ response_webhook: body.response_webhook || body.responseWebhook || body.callback_url || body.callbackUrl,
238
+ // Metadata
239
+ metadata: body.metadata || {},
240
+ // File attachments if any
241
+ attachments: body.attachments || body.files || [],
242
+ // Timestamp
243
+ timestamp: body.timestamp || body.created_at || body.createdAt || new Date().toISOString(),
244
+ // Include any other fields from the webhook
377
245
  ...body,
378
- agent_id: agentId,
379
- // Ensure conversation_id is available (handle different field names)
380
- conversation_id: body.conversation_id || body.conversationId || body.thread_id,
381
- // Ensure response_webhook is available if it exists
382
- response_webhook: body.response_webhook || body.responseWebhook || body.callback_url,
383
246
  };
384
- // Log what we're outputting for debugging
385
- console.log('CribopsTrigger output:', JSON.stringify(outputData, null, 2));
247
+ // Include headers if requested
248
+ const workflowData = additionalFields.includeHeaders
249
+ ? { json: outputData, headers }
250
+ : { json: outputData };
386
251
  // Return the data to the workflow
387
252
  return {
388
- workflowData: [
389
- [
390
- {
391
- json: outputData,
392
- headers,
393
- },
394
- ],
395
- ],
253
+ workflowData: [[workflowData]],
254
+ webhookResponse: {
255
+ status: 200,
256
+ body: { received: true },
257
+ },
396
258
  };
397
259
  }
398
260
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-cribops",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "n8n community node for Cribops AI platform integration",
5
5
  "keywords": [
6
6
  "n8n-community-node-package"
@@ -1,4 +1,4 @@
1
- import { IDataObject } from 'n8n-workflow';
1
+ import { IDataObject, IHttpRequestMethods, IHttpRequestOptions } from 'n8n-workflow';
2
2
  export interface CribopsHttpConfig {
3
3
  baseUrl: string;
4
4
  apiToken: string;
@@ -57,4 +57,5 @@ export declare class CribopsHttp {
57
57
  status: string;
58
58
  updated_count: number;
59
59
  }>;
60
+ request<T = any>(method: IHttpRequestMethods, endpoint: string, data?: IDataObject, options?: Partial<IHttpRequestOptions>): Promise<T>;
60
61
  }
@@ -144,5 +144,9 @@ class CribopsHttp {
144
144
  throw new Error(`Failed to mark messages as failed for tenant ${tenantId}: ${error}`);
145
145
  }
146
146
  }
147
+ // Generic request method for custom API calls
148
+ async request(method, endpoint, data, options) {
149
+ return this.makeRequest(method, endpoint, data, options);
150
+ }
147
151
  }
148
152
  exports.CribopsHttp = CribopsHttp;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-cribops",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "n8n community node for Cribops AI platform integration",
5
5
  "keywords": [
6
6
  "n8n-community-node-package"