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.
@@ -1,19 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Cribops = void 0;
4
- const n8n_workflow_1 = require("n8n-workflow");
5
4
  const CribopsHttp_1 = require("../../utils/CribopsHttp");
6
5
  class Cribops {
7
6
  description = {
8
- displayName: 'Cribops',
7
+ displayName: 'Cribops Webhook',
9
8
  name: 'cribops',
10
9
  icon: 'file:cribops.svg',
11
- group: ['communication'],
10
+ group: ['transform'],
12
11
  version: 1,
13
12
  subtitle: '={{$parameter["operation"]}}',
14
- description: 'Interact with Cribops AI agents',
13
+ description: 'Report errors, performance, and send callbacks to Cribops',
15
14
  defaults: {
16
- name: 'Cribops',
15
+ name: 'Cribops Webhook',
17
16
  },
18
17
  inputs: ["main" /* NodeConnectionType.Main */],
19
18
  outputs: ["main" /* NodeConnectionType.Main */],
@@ -37,620 +36,470 @@ class Cribops {
37
36
  noDataExpression: true,
38
37
  options: [
39
38
  {
40
- name: 'Get Agent',
41
- value: 'getAgent',
42
- description: 'Get information about a specific agent',
43
- action: 'Get information about a specific agent',
39
+ name: 'Report Error',
40
+ value: 'reportError',
41
+ description: 'Report workflow error to Cribops for monitoring',
42
+ action: 'Report workflow error to cribops',
44
43
  },
45
44
  {
46
- name: 'List Agents',
47
- value: 'listAgents',
48
- description: 'List all available agents',
49
- action: 'List all available agents',
45
+ name: 'Report Performance',
46
+ value: 'reportPerformance',
47
+ description: 'Send performance metrics for this webhook processing',
48
+ action: 'Send performance metrics',
50
49
  },
51
50
  {
52
- name: 'Poll Queue',
53
- value: 'pollQueue',
54
- description: 'Poll messages from the queue',
55
- action: 'Poll messages from the queue',
51
+ name: 'Send Callback',
52
+ value: 'sendCallback',
53
+ description: 'Send completion callback for long-running workflows',
54
+ action: 'Send completion callback',
56
55
  },
57
56
  {
58
- name: 'Reply to Conversation',
59
- value: 'replyToConversation',
60
- description: 'Reply to an existing conversation',
61
- action: 'Reply to an existing conversation',
57
+ name: 'Send Progress',
58
+ value: 'sendProgress',
59
+ description: 'Send progress update for long-running workflows',
60
+ action: 'Send progress update',
62
61
  },
63
62
  {
64
- name: 'Send Message',
65
- value: 'sendMessage',
66
- description: 'Send a message to a Cribops agent',
67
- action: 'Send a message to a cribops agent',
68
- },
69
- {
70
- name: 'Send Typing Indicator',
71
- value: 'sendTypingIndicator',
72
- description: 'Send typing indicator to a conversation',
73
- action: 'Send typing indicator to a conversation',
63
+ name: 'Send Workflow for Analysis',
64
+ value: 'analyzeWorkflow',
65
+ description: 'Send workflow definition to get optimization recommendations',
66
+ action: 'Send workflow for analysis',
74
67
  },
75
68
  ],
76
- default: 'sendMessage',
69
+ default: 'reportError',
77
70
  },
71
+ // Common webhook ID parameter
78
72
  {
79
- displayName: 'Agent',
80
- name: 'agentId',
81
- type: 'resourceLocator',
82
- default: { mode: 'list', value: '' },
73
+ displayName: 'Webhook ID',
74
+ name: 'webhookId',
75
+ type: 'string',
83
76
  required: true,
84
77
  displayOptions: {
85
78
  show: {
86
- operation: ['sendMessage', 'replyToConversation', 'getAgent', 'sendTypingIndicator'],
79
+ operation: ['reportError', 'reportPerformance', 'sendCallback', 'sendProgress'],
87
80
  },
88
81
  },
89
- modes: [
90
- {
91
- displayName: 'From List',
92
- name: 'list',
93
- type: 'list',
94
- placeholder: 'Select an agent...',
95
- typeOptions: {
96
- searchListMethod: 'searchAgents',
97
- searchable: true,
98
- },
82
+ default: '={{$json["cribops"]["webhook_id"]}}',
83
+ description: 'The Cribops webhook ID to report on',
84
+ },
85
+ // Report Error Operation
86
+ {
87
+ displayName: 'Error Details',
88
+ name: 'errorDetails',
89
+ type: 'collection',
90
+ placeholder: 'Add Error Detail',
91
+ default: {},
92
+ displayOptions: {
93
+ show: {
94
+ operation: ['reportError'],
99
95
  },
96
+ },
97
+ options: [
100
98
  {
101
- displayName: 'By ID',
102
- name: 'id',
99
+ displayName: 'Error Message',
100
+ name: 'message',
103
101
  type: 'string',
104
- placeholder: 'agent_123',
105
- validation: [
102
+ default: '',
103
+ },
104
+ {
105
+ displayName: 'Error Type',
106
+ name: 'type',
107
+ type: 'options',
108
+ options: [
109
+ {
110
+ name: 'Connection Error',
111
+ value: 'connection_error',
112
+ },
113
+ {
114
+ name: 'Authentication Failed',
115
+ value: 'auth_failed',
116
+ },
117
+ {
118
+ name: 'Rate Limited',
119
+ value: 'rate_limited',
120
+ },
106
121
  {
107
- type: 'regex',
108
- properties: {
109
- regex: '^[a-zA-Z0-9_-]+$',
110
- errorMessage: 'Agent ID must contain only letters, numbers, hyphens, and underscores',
111
- },
122
+ name: 'Timeout',
123
+ value: 'timeout',
124
+ },
125
+ {
126
+ name: 'Invalid Data',
127
+ value: 'invalid_data',
128
+ },
129
+ {
130
+ name: 'Server Error',
131
+ value: 'server_error',
132
+ },
133
+ {
134
+ name: 'Other',
135
+ value: 'other',
112
136
  },
113
137
  ],
138
+ default: 'other',
139
+ description: 'Type of error encountered',
140
+ },
141
+ {
142
+ displayName: 'Stack Trace',
143
+ name: 'stackTrace',
144
+ type: 'string',
145
+ typeOptions: {
146
+ rows: 5,
147
+ },
148
+ default: '',
149
+ description: 'Error stack trace for debugging',
150
+ },
151
+ {
152
+ displayName: 'Node Name',
153
+ name: 'nodeName',
154
+ type: 'string',
155
+ default: '',
156
+ description: 'Name of the node that failed',
157
+ },
158
+ {
159
+ displayName: 'Retry Recommended',
160
+ name: 'retryRecommended',
161
+ type: 'boolean',
162
+ default: true,
163
+ description: 'Whether retrying might succeed',
114
164
  },
115
165
  ],
116
166
  },
167
+ // Report Performance Operation
117
168
  {
118
- displayName: 'Conversation ID',
119
- name: 'conversationId',
120
- type: 'string',
121
- required: true,
122
- default: '',
123
- placeholder: 'conversation_123',
169
+ displayName: 'Performance Metrics',
170
+ name: 'performanceMetrics',
171
+ type: 'collection',
172
+ placeholder: 'Add Metric',
173
+ default: {},
124
174
  displayOptions: {
125
175
  show: {
126
- operation: ['replyToConversation'],
176
+ operation: ['reportPerformance'],
127
177
  },
128
178
  },
129
- description: 'ID of the conversation to reply to',
179
+ options: [
180
+ {
181
+ displayName: 'Processing Time (Ms)',
182
+ name: 'processingTime',
183
+ type: 'number',
184
+ default: 0,
185
+ description: 'Total time to process the webhook in milliseconds',
186
+ },
187
+ {
188
+ displayName: 'Memory Usage (MB)',
189
+ name: 'memoryUsage',
190
+ type: 'number',
191
+ default: 0,
192
+ description: 'Peak memory usage during processing',
193
+ },
194
+ {
195
+ displayName: 'Items Processed',
196
+ name: 'itemsProcessed',
197
+ type: 'number',
198
+ default: 1,
199
+ description: 'Number of items processed',
200
+ },
201
+ {
202
+ displayName: 'External API Calls',
203
+ name: 'apiCalls',
204
+ type: 'number',
205
+ default: 0,
206
+ description: 'Number of external API calls made',
207
+ },
208
+ {
209
+ displayName: 'Success',
210
+ name: 'success',
211
+ type: 'boolean',
212
+ default: true,
213
+ description: 'Whether the processing was successful',
214
+ },
215
+ ],
130
216
  },
217
+ // Send Callback Operation
131
218
  {
132
- displayName: 'Conversation ID',
133
- name: 'conversationId',
134
- type: 'string',
135
- required: true,
136
- default: '',
137
- placeholder: 'conversation_123',
219
+ displayName: 'Callback Type',
220
+ name: 'callbackType',
221
+ type: 'options',
138
222
  displayOptions: {
139
223
  show: {
140
- operation: ['sendTypingIndicator'],
224
+ operation: ['sendCallback'],
141
225
  },
142
226
  },
143
- description: 'ID of the conversation to send typing indicator to',
227
+ options: [
228
+ {
229
+ name: 'Success',
230
+ value: 'success',
231
+ },
232
+ {
233
+ name: 'Failure',
234
+ value: 'failure',
235
+ },
236
+ {
237
+ name: 'Partial Success',
238
+ value: 'partial',
239
+ },
240
+ ],
241
+ default: 'success',
242
+ description: 'Type of callback to send',
144
243
  },
145
244
  {
146
- displayName: 'Typing',
147
- name: 'typing',
148
- type: 'boolean',
149
- required: true,
150
- default: true,
245
+ displayName: 'Callback Data',
246
+ name: 'callbackData',
247
+ type: 'json',
151
248
  displayOptions: {
152
249
  show: {
153
- operation: ['sendTypingIndicator'],
250
+ operation: ['sendCallback'],
154
251
  },
155
252
  },
156
- description: 'Whether to show typing indicator (true) or stop typing (false)',
253
+ default: '{}',
254
+ description: 'Data to include in the callback',
157
255
  },
158
256
  {
159
- displayName: 'Tenant ID',
160
- name: 'tenantId',
257
+ displayName: 'Summary',
258
+ name: 'summary',
161
259
  type: 'string',
162
- required: true,
163
- default: '',
164
- placeholder: 'my-tenant',
165
260
  displayOptions: {
166
261
  show: {
167
- operation: ['pollQueue'],
262
+ operation: ['sendCallback'],
168
263
  },
169
264
  },
170
- description: 'The tenant ID for your Cribops organization',
265
+ default: '',
266
+ description: 'Brief summary of the processing result',
171
267
  },
268
+ // Send Progress Operation
172
269
  {
173
- displayName: 'Batch Size',
174
- name: 'batchSize',
270
+ displayName: 'Progress',
271
+ name: 'progress',
175
272
  type: 'number',
176
- default: 10,
273
+ typeOptions: {
274
+ minValue: 0,
275
+ maxValue: 100,
276
+ },
177
277
  displayOptions: {
178
278
  show: {
179
- operation: ['pollQueue'],
279
+ operation: ['sendProgress'],
180
280
  },
181
281
  },
182
- description: 'Number of messages to retrieve (max 100)',
282
+ default: 0,
283
+ description: 'Progress percentage (0-100)',
183
284
  },
184
285
  {
185
- displayName: 'Queue Name',
186
- name: 'queueName',
286
+ displayName: 'Progress Message',
287
+ name: 'progressMessage',
187
288
  type: 'string',
188
- default: '',
189
- placeholder: 'e.g., stripe_events',
190
289
  displayOptions: {
191
290
  show: {
192
- operation: ['pollQueue'],
291
+ operation: ['sendProgress'],
193
292
  },
194
293
  },
195
- description: 'Specific queue to poll (optional). Leave empty to poll all queues.',
294
+ default: '',
295
+ description: 'Current status message',
196
296
  },
197
297
  {
198
- displayName: 'Message',
199
- name: 'message',
200
- type: 'string',
201
- required: true,
202
- default: '',
203
- placeholder: 'Hello, how can you help me?',
298
+ displayName: 'Items Completed',
299
+ name: 'itemsCompleted',
300
+ type: 'number',
204
301
  displayOptions: {
205
302
  show: {
206
- operation: ['sendMessage', 'replyToConversation'],
303
+ operation: ['sendProgress'],
207
304
  },
208
305
  },
209
- description: 'The message to send',
306
+ default: 0,
307
+ description: 'Number of items completed',
210
308
  },
211
309
  {
212
- displayName: 'Conversation ID',
213
- name: 'conversationId',
214
- type: 'string',
215
- default: '',
216
- placeholder: 'conversation_123',
310
+ displayName: 'Total Items',
311
+ name: 'totalItems',
312
+ type: 'number',
217
313
  displayOptions: {
218
314
  show: {
219
- operation: ['sendMessage'],
315
+ operation: ['sendProgress'],
220
316
  },
221
317
  },
222
- description: 'ID of the conversation (leave empty to start a new conversation)',
318
+ default: 0,
319
+ description: 'Total number of items to process',
223
320
  },
321
+ // Analyze Workflow Operation
224
322
  {
225
- displayName: 'User ID',
226
- name: 'userId',
227
- type: 'string',
228
- default: '',
229
- placeholder: 'user_123',
323
+ displayName: 'Include Workflow Definition',
324
+ name: 'includeDefinition',
325
+ type: 'boolean',
230
326
  displayOptions: {
231
327
  show: {
232
- operation: ['sendMessage'],
328
+ operation: ['analyzeWorkflow'],
233
329
  },
234
330
  },
235
- description: 'ID of the user sending the message',
331
+ default: true,
332
+ description: 'Whether to include the full workflow definition',
236
333
  },
237
334
  {
238
- displayName: 'File Attachment',
239
- name: 'fileAttachment',
240
- type: 'fixedCollection',
335
+ displayName: 'Workflow Metrics',
336
+ name: 'workflowMetrics',
337
+ type: 'collection',
338
+ placeholder: 'Add Metric',
241
339
  default: {},
242
- placeholder: 'Add file attachment',
243
340
  displayOptions: {
244
341
  show: {
245
- operation: ['sendMessage'],
342
+ operation: ['analyzeWorkflow'],
246
343
  },
247
344
  },
248
- typeOptions: {
249
- multipleValues: false,
250
- },
251
345
  options: [
252
346
  {
253
- name: 'file',
254
- displayName: 'File',
255
- values: [
256
- {
257
- displayName: 'File URL',
258
- name: 'url',
259
- type: 'string',
260
- default: '',
261
- placeholder: 'https://example.com/file.pdf',
262
- description: 'URL of the file to attach',
263
- },
264
- {
265
- displayName: 'File Name',
266
- name: 'name',
267
- type: 'string',
268
- default: '',
269
- placeholder: 'document.pdf',
270
- description: 'Name of the file (optional)',
271
- },
272
- {
273
- displayName: 'File Type',
274
- name: 'type',
275
- type: 'string',
276
- default: '',
277
- placeholder: 'application/pdf',
278
- description: 'MIME type of the file (optional)',
279
- },
280
- ],
347
+ displayName: 'Average Execution Time',
348
+ name: 'avgExecutionTime',
349
+ type: 'number',
350
+ default: 0,
351
+ description: 'Average execution time in milliseconds',
281
352
  },
282
- ],
283
- },
284
- {
285
- displayName: 'Additional Fields',
286
- name: 'additionalFields',
287
- type: 'collection',
288
- placeholder: 'Add Field',
289
- default: {},
290
- options: [
291
353
  {
292
- displayName: 'Metadata',
293
- name: 'metadata',
294
- type: 'fixedCollection',
295
- placeholder: 'Add Metadata',
296
- default: {},
297
- typeOptions: {
298
- multipleValues: true,
299
- },
300
- options: [
301
- {
302
- name: 'metadataValues',
303
- displayName: 'Metadata',
304
- values: [
305
- {
306
- displayName: 'Key',
307
- name: 'key',
308
- type: 'string',
309
- default: '',
310
- description: 'Metadata key',
311
- },
312
- {
313
- displayName: 'Value',
314
- name: 'value',
315
- type: 'string',
316
- default: '',
317
- description: 'Metadata value',
318
- },
319
- ],
320
- },
321
- ],
354
+ displayName: 'Daily Executions',
355
+ name: 'dailyExecutions',
356
+ type: 'number',
357
+ default: 0,
358
+ description: 'Average number of executions per day',
359
+ },
360
+ {
361
+ displayName: 'Failure Rate',
362
+ name: 'failureRate',
363
+ type: 'number',
364
+ default: 0,
365
+ description: 'Percentage of failed executions',
322
366
  },
323
367
  {
324
- displayName: 'Timeout',
325
- name: 'timeout',
368
+ displayName: 'Node Count',
369
+ name: 'nodeCount',
326
370
  type: 'number',
327
- default: 30000,
328
- description: 'Request timeout in milliseconds',
371
+ default: 0,
372
+ description: 'Number of nodes in the workflow',
329
373
  },
330
374
  ],
331
375
  },
332
376
  ],
333
377
  };
334
- methods = {
335
- listSearch: {
336
- searchAgents: async function (filter) {
337
- const credentials = await this.getCredentials('cribopsApi');
338
- const cribopsHttp = new CribopsHttp_1.CribopsHttp({
339
- baseUrl: credentials.baseUrl,
340
- apiToken: credentials.apiToken,
341
- });
342
- try {
343
- const agents = await cribopsHttp.getAgents();
344
- const results = agents
345
- .filter((agent) => !filter || agent.name.toLowerCase().includes(filter.toLowerCase()))
346
- .map((agent) => ({
347
- name: `${agent.name} (${agent.id})`,
348
- value: agent.id,
349
- }));
350
- return {
351
- results,
352
- };
353
- }
354
- catch (error) {
355
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load agents: ${error}`, {
356
- description: 'Make sure your API credentials are correct and the Cribops API is accessible',
357
- });
358
- }
359
- },
360
- },
361
- };
362
378
  async execute() {
363
379
  const items = this.getInputData();
364
- const results = [];
380
+ const returnData = [];
365
381
  const credentials = await this.getCredentials('cribopsApi');
366
382
  const cribopsHttp = new CribopsHttp_1.CribopsHttp({
367
383
  baseUrl: credentials.baseUrl,
368
384
  apiToken: credentials.apiToken,
369
385
  });
386
+ const operation = this.getNodeParameter('operation', 0);
370
387
  for (let i = 0; i < items.length; i++) {
371
- const operation = this.getNodeParameter('operation', i);
372
388
  try {
373
389
  let responseData;
374
- switch (operation) {
375
- case 'replyToConversation':
376
- responseData = await replyToConversation(this, cribopsHttp, i);
377
- break;
378
- case 'sendMessage':
379
- responseData = await sendMessage(this, cribopsHttp, i);
380
- break;
381
- case 'sendTypingIndicator':
382
- responseData = await sendTypingIndicator(this, cribopsHttp, i);
383
- break;
384
- case 'getAgent':
385
- responseData = await getAgent(this, cribopsHttp, i);
386
- break;
387
- case 'listAgents':
388
- responseData = await listAgents(this, cribopsHttp, i);
389
- break;
390
- case 'pollQueue':
391
- responseData = await pollQueue(this, cribopsHttp, i);
392
- break;
393
- default:
394
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`, { itemIndex: i });
390
+ if (operation === 'reportError') {
391
+ const webhookId = this.getNodeParameter('webhookId', i);
392
+ const errorDetails = this.getNodeParameter('errorDetails', i);
393
+ const errorData = {
394
+ webhook_id: webhookId,
395
+ error: {
396
+ message: String(errorDetails.message || 'Unknown error'),
397
+ type: String(errorDetails.type || 'other'),
398
+ stack_trace: errorDetails.stackTrace ? String(errorDetails.stackTrace) : undefined,
399
+ node_name: errorDetails.nodeName ? String(errorDetails.nodeName) : undefined,
400
+ retry_recommended: errorDetails.retryRecommended !== false,
401
+ timestamp: new Date().toISOString(),
402
+ workflow_id: this.getWorkflow().id,
403
+ workflow_name: this.getWorkflow().name,
404
+ },
405
+ };
406
+ responseData = await cribopsHttp.reportError(errorData);
395
407
  }
396
- results.push({
408
+ else if (operation === 'reportPerformance') {
409
+ const webhookId = this.getNodeParameter('webhookId', i);
410
+ const metrics = this.getNodeParameter('performanceMetrics', i);
411
+ const performanceData = {
412
+ webhook_id: webhookId,
413
+ metrics: {
414
+ processing_time_ms: Number(metrics.processingTime || 0),
415
+ memory_usage_mb: metrics.memoryUsage ? Number(metrics.memoryUsage) : undefined,
416
+ items_processed: Number(metrics.itemsProcessed || 1),
417
+ api_calls: metrics.apiCalls ? Number(metrics.apiCalls) : undefined,
418
+ success: metrics.success !== false,
419
+ timestamp: new Date().toISOString(),
420
+ workflow_id: this.getWorkflow().id,
421
+ workflow_name: this.getWorkflow().name,
422
+ },
423
+ };
424
+ responseData = await cribopsHttp.reportPerformance(performanceData);
425
+ }
426
+ else if (operation === 'sendCallback') {
427
+ const webhookId = this.getNodeParameter('webhookId', i);
428
+ const callbackType = this.getNodeParameter('callbackType', i);
429
+ const callbackData = this.getNodeParameter('callbackData', i);
430
+ const summary = this.getNodeParameter('summary', i);
431
+ const callback = {
432
+ webhook_id: webhookId,
433
+ type: callbackType,
434
+ data: JSON.parse(callbackData),
435
+ summary: summary || undefined,
436
+ timestamp: new Date().toISOString(),
437
+ workflow_id: this.getWorkflow().id,
438
+ workflow_name: this.getWorkflow().name,
439
+ };
440
+ responseData = await cribopsHttp.sendCallback(callback);
441
+ }
442
+ else if (operation === 'sendProgress') {
443
+ const webhookId = this.getNodeParameter('webhookId', i);
444
+ const progress = this.getNodeParameter('progress', i);
445
+ const progressMessage = this.getNodeParameter('progressMessage', i);
446
+ const itemsCompleted = this.getNodeParameter('itemsCompleted', i);
447
+ const totalItems = this.getNodeParameter('totalItems', i);
448
+ const progressData = {
449
+ webhook_id: webhookId,
450
+ progress: {
451
+ percentage: progress,
452
+ message: progressMessage,
453
+ items_completed: itemsCompleted,
454
+ total_items: totalItems,
455
+ timestamp: new Date().toISOString(),
456
+ },
457
+ };
458
+ responseData = await cribopsHttp.sendProgress(progressData);
459
+ }
460
+ else if (operation === 'analyzeWorkflow') {
461
+ const includeDefinition = this.getNodeParameter('includeDefinition', i);
462
+ const metrics = this.getNodeParameter('workflowMetrics', i);
463
+ const workflowInfo = this.getWorkflow();
464
+ const analysisData = {
465
+ workflow_id: workflowInfo.id,
466
+ workflow_name: workflowInfo.name,
467
+ metrics: {
468
+ avg_execution_time_ms: Number(metrics.avgExecutionTime || 0),
469
+ daily_executions: Number(metrics.dailyExecutions || 0),
470
+ failure_rate: Number(metrics.failureRate || 0),
471
+ node_count: Number(metrics.nodeCount || 0),
472
+ },
473
+ };
474
+ if (includeDefinition) {
475
+ // Get workflow data from the workflow static data if available
476
+ // This is a placeholder - in production you might need to get this differently
477
+ analysisData.workflow_definition = {
478
+ nodes: [],
479
+ connections: {},
480
+ };
481
+ }
482
+ responseData = await cribopsHttp.analyzeWorkflow(analysisData);
483
+ }
484
+ returnData.push({
397
485
  json: responseData,
398
486
  pairedItem: { item: i },
399
487
  });
400
488
  }
401
489
  catch (error) {
402
490
  if (this.continueOnFail()) {
403
- results.push({
491
+ returnData.push({
404
492
  json: {
405
- error: error.message,
493
+ error: error instanceof Error ? error.message : String(error),
406
494
  },
407
495
  pairedItem: { item: i },
408
496
  });
497
+ continue;
409
498
  }
410
- else {
411
- throw error;
412
- }
499
+ throw error;
413
500
  }
414
501
  }
415
- return [results];
502
+ return [returnData];
416
503
  }
417
504
  }
418
505
  exports.Cribops = Cribops;
419
- // Simple UUID v4 generator
420
- function generateUUID() {
421
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
422
- const r = Math.random() * 16 | 0;
423
- const v = c === 'x' ? r : (r & 0x3 | 0x8);
424
- return v.toString(16);
425
- });
426
- }
427
- async function replyToConversation(executeFunctions, cribopsHttp, itemIndex) {
428
- const agentId = executeFunctions.getNodeParameter('agentId', itemIndex, '', { extractValue: true });
429
- const conversationId = executeFunctions.getNodeParameter('conversationId', itemIndex);
430
- const message = executeFunctions.getNodeParameter('message', itemIndex);
431
- // Get the response webhook URL from the input data
432
- const inputData = executeFunctions.getInputData()[itemIndex];
433
- let responseWebhook = inputData.json.response_webhook;
434
- // If not found directly, check if it's in the original trigger data (passed through by typing indicator)
435
- if (!responseWebhook && inputData.json._originalTriggerData) {
436
- const originalTriggerData = inputData.json._originalTriggerData;
437
- responseWebhook = originalTriggerData.response_webhook;
438
- }
439
- // If still not found, try to find it in the workflow execution data from the CribopsTrigger node
440
- if (!responseWebhook) {
441
- try {
442
- const workflowData = executeFunctions.getWorkflowDataProxy(itemIndex);
443
- const cribopsTriggerData = workflowData.$('Cribops Trigger');
444
- if (cribopsTriggerData && cribopsTriggerData.item && cribopsTriggerData.item.json) {
445
- responseWebhook = cribopsTriggerData.item.json.response_webhook;
446
- }
447
- }
448
- catch (error) {
449
- // Ignore errors if Cribops Trigger node is not found
450
- }
451
- }
452
- // Log the raw values to debug expression evaluation
453
- console.log('Debug - agentId:', agentId);
454
- console.log('Debug - conversationId:', conversationId);
455
- console.log('Debug - message:', message);
456
- console.log('Debug - responseWebhook:', responseWebhook);
457
- // Check if expressions were not evaluated (contain literal expression syntax)
458
- if (conversationId.includes('{{') || conversationId.includes('}}')) {
459
- throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), `Conversation ID contains unevaluated expression: ${conversationId}. Please ensure the expression is properly formatted.`, { itemIndex });
460
- }
461
- if (!conversationId || conversationId.trim() === '') {
462
- throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), 'Conversation ID is required but was empty', { itemIndex });
463
- }
464
- if (!responseWebhook) {
465
- console.log('Warning: response_webhook not found in input data:', JSON.stringify(inputData.json, null, 2));
466
- // Fallback: try to use the agent webhook endpoint
467
- console.log('Falling back to agent webhook endpoint');
468
- const fallbackMessageData = {
469
- id: generateUUID(),
470
- content: message,
471
- conversationId: conversationId,
472
- agentId: agentId,
473
- type: 'agent_response',
474
- timestamp: new Date().toISOString(),
475
- };
476
- return await cribopsHttp.sendMessage(agentId, fallbackMessageData);
477
- }
478
- // Try to get user_id and organization_id from trigger data
479
- let userId = inputData.json.user_id || '';
480
- let organizationId = inputData.json.organization_id || '';
481
- // If not found, try to get from workflow data
482
- if ((!userId || !organizationId) && responseWebhook) {
483
- try {
484
- const workflowData = executeFunctions.getWorkflowDataProxy(itemIndex);
485
- const cribopsTriggerData = workflowData.$('Cribops Trigger');
486
- if (cribopsTriggerData && cribopsTriggerData.item && cribopsTriggerData.item.json) {
487
- userId = userId || cribopsTriggerData.item.json.user_id || '';
488
- organizationId = organizationId || cribopsTriggerData.item.json.organization_id || '';
489
- }
490
- }
491
- catch (error) {
492
- // Ignore errors
493
- }
494
- }
495
- const messageData = {
496
- conversation_id: conversationId,
497
- content: message,
498
- message_id: generateUUID(),
499
- timestamp: new Date().toISOString(),
500
- // Include additional fields that might be needed
501
- user_id: userId,
502
- organization_id: organizationId,
503
- };
504
- try {
505
- console.log('Debug - Response webhook URL:', responseWebhook);
506
- console.log('Debug - Request body:', JSON.stringify(messageData, null, 2));
507
- // Send to the response webhook URL
508
- // Note: The standard workflow uses form parameters, not JSON
509
- const formData = new URLSearchParams();
510
- Object.keys(messageData).forEach(key => {
511
- formData.append(key, String(messageData[key]));
512
- });
513
- const requestOptions = {
514
- method: 'POST',
515
- url: responseWebhook,
516
- headers: {
517
- 'Authorization': `Bearer ${cribopsHttp['config'].apiToken}`,
518
- 'Content-Type': 'application/x-www-form-urlencoded',
519
- },
520
- body: formData.toString(),
521
- json: false,
522
- };
523
- const response = await executeFunctions.helpers.httpRequest(requestOptions);
524
- return response;
525
- }
526
- catch (error) {
527
- // Enhanced error logging for 422 errors
528
- if (error.response?.status === 422) {
529
- console.error('422 Error Details:');
530
- console.error('Response body:', JSON.stringify(error.response.body, null, 2));
531
- console.error('Request that failed:', {
532
- agentId: agentId,
533
- body: messageData,
534
- conversationId: conversationId
535
- });
536
- const errorDetails = error.response.body?.errors || error.response.body?.message || 'Unknown validation error';
537
- throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), `Validation error (422): ${JSON.stringify(errorDetails)}. ConversationId: "${conversationId}"`, { itemIndex, description: `Full error: ${JSON.stringify(error.response.body)}` });
538
- }
539
- throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), `Failed to reply to conversation: ${error instanceof Error ? error.message : String(error)}`, { itemIndex });
540
- }
541
- }
542
- async function sendMessage(executeFunctions, cribopsHttp, itemIndex) {
543
- const agentId = executeFunctions.getNodeParameter('agentId', itemIndex, '', { extractValue: true });
544
- const message = executeFunctions.getNodeParameter('message', itemIndex);
545
- const conversationId = executeFunctions.getNodeParameter('conversationId', itemIndex, '');
546
- const userId = executeFunctions.getNodeParameter('userId', itemIndex, '');
547
- const fileAttachment = executeFunctions.getNodeParameter('fileAttachment', itemIndex, {});
548
- const additionalFields = executeFunctions.getNodeParameter('additionalFields', itemIndex, {});
549
- const messageData = {
550
- id: generateUUID(),
551
- content: message,
552
- conversationId: conversationId || `conversation_${Date.now()}`,
553
- userId: userId || undefined,
554
- type: 'user_message',
555
- timestamp: new Date().toISOString(),
556
- };
557
- // Add file attachment if provided
558
- if (fileAttachment.file) {
559
- const file = fileAttachment.file;
560
- if (file.url) {
561
- messageData.fileUrl = file.url;
562
- messageData.fileName = file.name || 'file';
563
- messageData.fileType = file.type || 'application/octet-stream';
564
- }
565
- }
566
- // Add metadata if provided
567
- if (additionalFields.metadata) {
568
- const metadata = additionalFields.metadata;
569
- const metadataValues = metadata.metadataValues;
570
- if (metadataValues && metadataValues.length > 0) {
571
- messageData.metadata = {};
572
- metadataValues.forEach((item) => {
573
- messageData.metadata[item.key] = item.value;
574
- });
575
- }
576
- }
577
- return await cribopsHttp.sendMessage(agentId, messageData);
578
- }
579
- async function getAgent(executeFunctions, cribopsHttp, itemIndex) {
580
- const agentId = executeFunctions.getNodeParameter('agentId', itemIndex, '', { extractValue: true });
581
- return await cribopsHttp.getAgent(agentId);
582
- }
583
- async function listAgents(executeFunctions, cribopsHttp, itemIndex) {
584
- const agents = await cribopsHttp.getAgents();
585
- return { agents, count: agents.length };
586
- }
587
- async function pollQueue(executeFunctions, cribopsHttp, itemIndex) {
588
- const tenantId = executeFunctions.getNodeParameter('tenantId', itemIndex);
589
- const batchSize = executeFunctions.getNodeParameter('batchSize', itemIndex, 10);
590
- const queueName = executeFunctions.getNodeParameter('queueName', itemIndex, '') || undefined;
591
- const messages = await cribopsHttp.pollQueue(tenantId, batchSize, queueName);
592
- // Process each message to parse the data if it's JSON
593
- const processedMessages = messages.map(message => {
594
- let parsedData = message.data.data;
595
- try {
596
- parsedData = JSON.parse(message.data.data);
597
- }
598
- catch (e) {
599
- // Keep as string if not valid JSON
600
- }
601
- return {
602
- id: message.id,
603
- correlation_id: message.correlation_id,
604
- queue_name: message.queue_name,
605
- data: parsedData,
606
- headers: message.data.headers,
607
- params: message.data.params,
608
- inserted_at: message.inserted_at,
609
- // Extract useful fields from headers
610
- tenant_id: message.data.headers['x-cribops-tenant-id'] || tenantId,
611
- path: message.data.headers['x-cribops-path'],
612
- };
613
- });
614
- // Auto-acknowledge messages after processing
615
- if (messages.length > 0) {
616
- const messageIds = messages.map(msg => msg.id);
617
- try {
618
- await cribopsHttp.acknowledgeMessages(tenantId, messageIds);
619
- }
620
- catch (ackError) {
621
- // Log error but don't fail the operation
622
- console.error('Failed to acknowledge messages:', ackError);
623
- }
624
- }
625
- return { messages: processedMessages, count: processedMessages.length };
626
- }
627
- async function sendTypingIndicator(executeFunctions, cribopsHttp, itemIndex) {
628
- const agentId = executeFunctions.getNodeParameter('agentId', itemIndex, '', { extractValue: true });
629
- const conversationId = executeFunctions.getNodeParameter('conversationId', itemIndex);
630
- const typing = executeFunctions.getNodeParameter('typing', itemIndex);
631
- // Check if we have a response_webhook in the input data to extract the correct base URL
632
- const inputData = executeFunctions.getInputData()[itemIndex];
633
- const responseWebhook = inputData.json.response_webhook;
634
- let typingResult;
635
- if (responseWebhook) {
636
- // Extract base URL from response webhook
637
- const webhookUrl = new URL(responseWebhook);
638
- const baseUrl = `${webhookUrl.protocol}//${webhookUrl.host}`;
639
- // Create a temporary HTTP client with the correct base URL
640
- const dynamicCribopsHttp = new CribopsHttp_1.CribopsHttp({
641
- baseUrl: baseUrl,
642
- apiToken: cribopsHttp['config'].apiToken,
643
- });
644
- typingResult = await dynamicCribopsHttp.sendTypingIndicator(agentId, conversationId, typing);
645
- }
646
- else {
647
- // Fallback to the configured base URL
648
- typingResult = await cribopsHttp.sendTypingIndicator(agentId, conversationId, typing);
649
- }
650
- // Preserve the original trigger data for subsequent nodes
651
- return {
652
- ...typingResult,
653
- // Pass through the original trigger data so replyToConversation can access it
654
- _originalTriggerData: inputData.json
655
- };
656
- }