n8n-nodes-confirm8 0.18.0 → 0.19.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,10 +1,5 @@
1
- import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, IDataObject } from 'n8n-workflow';
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
2
  export declare class Confirm8AgentTool implements INodeType {
3
3
  description: INodeTypeDescription;
4
- /**
5
- * MCP-style tool description with explicit schema
6
- */
7
- supportsMultipleCalls(): Promise<boolean>;
8
- getToolDescription(this: IExecuteFunctions): Promise<IDataObject>;
9
4
  execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
10
5
  }
@@ -10,7 +10,7 @@ class Confirm8AgentTool {
10
10
  icon: 'file:tool.svg',
11
11
  group: ['transform'],
12
12
  version: 1,
13
- description: 'MCP-style AI Agent tool for Confirm8 API with schema discovery',
13
+ description: 'AI Agent tool for Confirm8 API - use EXACT enum values: resource (user/client/item/task/service/product/order/ticket/property) and operation (getAll/get/create/update/activate/deactivate)',
14
14
  defaults: {
15
15
  name: 'Confirm8 AI Tool',
16
16
  },
@@ -26,7 +26,6 @@ class Confirm8AgentTool {
26
26
  default: '',
27
27
  placeholder: 'https://api.confirm8.com',
28
28
  required: true,
29
- description: 'Base URL of Confirm8 API',
30
29
  },
31
30
  {
32
31
  displayName: 'Bearer Token',
@@ -51,302 +50,59 @@ class Confirm8AgentTool {
51
50
  default: '',
52
51
  required: true,
53
52
  },
54
- // Tool parameters (AI provides)
53
+ // Tool parameters - MUST use exact enum values
55
54
  {
56
55
  displayName: 'Resource',
57
56
  name: 'resource',
58
- type: 'string',
59
- default: '',
57
+ type: 'options',
58
+ options: [
59
+ { name: 'User', value: 'user', description: 'Users/employees' },
60
+ { name: 'Client', value: 'client', description: 'Clients/customers' },
61
+ { name: 'Item', value: 'item', description: 'Items/inventory' },
62
+ { name: 'Item Type', value: 'itemType', description: 'Item categories' },
63
+ { name: 'Task', value: 'task', description: 'Tasks/checklists' },
64
+ { name: 'Service', value: 'service', description: 'Services' },
65
+ { name: 'Product', value: 'product', description: 'Products' },
66
+ { name: 'Order', value: 'order', description: 'Work orders' },
67
+ { name: 'Modality', value: 'modality', description: 'Order modalities' },
68
+ { name: 'Ticket', value: 'ticket', description: 'Tickets' },
69
+ { name: 'Property', value: 'property', description: 'Properties' },
70
+ ],
71
+ default: 'user',
72
+ description: 'IMPORTANT: Use EXACT value from list',
60
73
  },
61
74
  {
62
75
  displayName: 'Operation',
63
76
  name: 'operation',
64
- type: 'string',
65
- default: '',
77
+ type: 'options',
78
+ options: [
79
+ { name: 'Get All', value: 'getAll', description: 'List all records' },
80
+ { name: 'Get', value: 'get', description: 'Get single record' },
81
+ { name: 'Create', value: 'create', description: 'Create new record' },
82
+ { name: 'Update', value: 'update', description: 'Update record' },
83
+ { name: 'Activate', value: 'activate', description: 'Activate record' },
84
+ { name: 'Deactivate', value: 'deactivate', description: 'Deactivate record' },
85
+ ],
86
+ default: 'getAll',
87
+ description: 'IMPORTANT: Use EXACT value from list',
66
88
  },
67
89
  {
68
90
  displayName: 'Record ID',
69
91
  name: 'recordId',
70
92
  type: 'string',
71
93
  default: '',
94
+ description: 'ID of record (for get/update/activate/deactivate)',
72
95
  },
73
96
  {
74
97
  displayName: 'Data',
75
98
  name: 'data',
76
99
  type: 'string',
77
100
  default: '',
101
+ description: 'JSON data for create/update',
78
102
  },
79
103
  ],
80
104
  };
81
105
  }
82
- /**
83
- * MCP-style tool description with explicit schema
84
- */
85
- async supportsMultipleCalls() {
86
- return true;
87
- }
88
- // This is what the AI sees - make it VERY explicit
89
- async getToolDescription() {
90
- return {
91
- name: 'confirm8_api',
92
- description: 'Access Confirm8 business management system. Use EXACT values from schema below.',
93
- // Define schema with ENUMS
94
- schema: {
95
- type: 'object',
96
- properties: {
97
- resource: {
98
- type: 'string',
99
- description: 'Resource to access. MUST be one of the exact values below.',
100
- enum: [
101
- 'user',
102
- 'client',
103
- 'item',
104
- 'itemType',
105
- 'task',
106
- 'service',
107
- 'product',
108
- 'order',
109
- 'modality',
110
- 'ticket',
111
- 'property'
112
- ],
113
- examples: ['user', 'client', 'task']
114
- },
115
- operation: {
116
- type: 'string',
117
- description: 'Operation to perform. MUST be one of the exact values below.',
118
- enum: [
119
- 'getAll',
120
- 'get',
121
- 'create',
122
- 'update',
123
- 'activate',
124
- 'deactivate',
125
- 'getByUsername',
126
- 'getTickets',
127
- 'getTasks',
128
- 'getPermissions',
129
- 'linkTasks',
130
- 'deleteLinkedTasks',
131
- 'deleteLinkedTasksByUser',
132
- 'uploadPhoto',
133
- 'uploadSignature'
134
- ],
135
- examples: ['getAll', 'get', 'create', 'update']
136
- },
137
- recordId: {
138
- type: 'string',
139
- description: 'ID of record (required for: get, update, activate, deactivate, getTickets, getTasks, getPermissions, uploadPhoto, uploadSignature)',
140
- examples: ['123', '456', 'abc-def-ghi']
141
- },
142
- data: {
143
- type: 'string',
144
- description: 'JSON string with data (required for: create, update, linkTasks, uploadPhoto, uploadSignature)',
145
- examples: [
146
- '{"name":"John Doe","email":"john@example.com"}',
147
- '{"status":"completed"}',
148
- '{"userId":"123","taskIds":["1","2","3"]}'
149
- ]
150
- }
151
- },
152
- required: ['resource', 'operation']
153
- },
154
- // Detailed mapping
155
- resources: {
156
- user: {
157
- description: 'Users and employees',
158
- operations: {
159
- getAll: { description: 'List all users', requires: [] },
160
- get: { description: 'Get user by ID', requires: ['recordId'] },
161
- create: { description: 'Create new user', requires: ['data'] },
162
- update: { description: 'Update user', requires: ['recordId', 'data'] },
163
- activate: { description: 'Activate user', requires: ['recordId'] },
164
- deactivate: { description: 'Deactivate user', requires: ['recordId'] },
165
- getByUsername: { description: 'Get user by username', requires: ['data.username'] },
166
- getTickets: { description: 'Get user tickets', requires: ['recordId'] },
167
- getTasks: { description: 'Get user tasks', requires: ['recordId'] },
168
- getPermissions: { description: 'Get user permissions', requires: ['recordId'] },
169
- linkTasks: { description: 'Link tasks to user', requires: ['data'] },
170
- uploadPhoto: { description: 'Upload user photo', requires: ['recordId', 'data'] },
171
- uploadSignature: { description: 'Upload signature', requires: ['recordId', 'data'] }
172
- }
173
- },
174
- client: {
175
- description: 'Clients and customers',
176
- operations: {
177
- getAll: { description: 'List all clients', requires: [] },
178
- get: { description: 'Get client by ID', requires: ['recordId'] },
179
- create: { description: 'Create new client', requires: ['data'] },
180
- update: { description: 'Update client', requires: ['recordId', 'data'] },
181
- activate: { description: 'Activate client', requires: ['recordId'] },
182
- deactivate: { description: 'Deactivate client', requires: ['recordId'] }
183
- }
184
- },
185
- item: {
186
- description: 'Items and inventory',
187
- operations: {
188
- getAll: { description: 'List all items', requires: [] },
189
- get: { description: 'Get item by ID', requires: ['recordId'] },
190
- create: { description: 'Create new item', requires: ['data'] },
191
- update: { description: 'Update item', requires: ['recordId', 'data'] },
192
- activate: { description: 'Activate item', requires: ['recordId'] },
193
- deactivate: { description: 'Deactivate item', requires: ['recordId'] }
194
- }
195
- },
196
- itemType: {
197
- description: 'Item type categories',
198
- operations: {
199
- getAll: { description: 'List all item types', requires: [] },
200
- get: { description: 'Get item type by ID', requires: ['recordId'] },
201
- create: { description: 'Create new item type', requires: ['data'] },
202
- update: { description: 'Update item type', requires: ['recordId', 'data'] },
203
- activate: { description: 'Activate item type', requires: ['recordId'] },
204
- deactivate: { description: 'Deactivate item type', requires: ['recordId'] }
205
- }
206
- },
207
- task: {
208
- description: 'Tasks and checklists',
209
- operations: {
210
- getAll: { description: 'List all tasks', requires: [] },
211
- get: { description: 'Get task by ID', requires: ['recordId'] },
212
- create: { description: 'Create new task', requires: ['data'] },
213
- update: { description: 'Update task', requires: ['recordId', 'data'] },
214
- activate: { description: 'Activate task', requires: ['recordId'] },
215
- deactivate: { description: 'Deactivate task', requires: ['recordId'] }
216
- }
217
- },
218
- service: {
219
- description: 'Services',
220
- operations: {
221
- getAll: { description: 'List all services', requires: [] },
222
- get: { description: 'Get service by ID', requires: ['recordId'] },
223
- create: { description: 'Create new service', requires: ['data'] },
224
- update: { description: 'Update service', requires: ['recordId', 'data'] },
225
- activate: { description: 'Activate service', requires: ['recordId'] },
226
- deactivate: { description: 'Deactivate service', requires: ['recordId'] }
227
- }
228
- },
229
- product: {
230
- description: 'Products',
231
- operations: {
232
- getAll: { description: 'List all products', requires: [] },
233
- get: { description: 'Get product by ID', requires: ['recordId'] },
234
- create: { description: 'Create new product', requires: ['data'] },
235
- update: { description: 'Update product', requires: ['recordId', 'data'] },
236
- activate: { description: 'Activate product', requires: ['recordId'] },
237
- deactivate: { description: 'Deactivate product', requires: ['recordId'] }
238
- }
239
- },
240
- order: {
241
- description: 'Work orders (WOS)',
242
- operations: {
243
- getAll: { description: 'List all orders', requires: [] },
244
- get: { description: 'Get order by ID', requires: ['recordId'] },
245
- create: { description: 'Create new order', requires: ['data'] },
246
- update: { description: 'Update order', requires: ['recordId', 'data'] },
247
- activate: { description: 'Activate order', requires: ['recordId'] },
248
- deactivate: { description: 'Deactivate order', requires: ['recordId'] }
249
- }
250
- },
251
- modality: {
252
- description: 'Order modalities',
253
- operations: {
254
- getAll: { description: 'List all modalities', requires: [] },
255
- get: { description: 'Get modality by ID', requires: ['recordId'] },
256
- create: { description: 'Create new modality', requires: ['data'] },
257
- update: { description: 'Update modality', requires: ['recordId', 'data'] },
258
- activate: { description: 'Activate modality', requires: ['recordId'] },
259
- deactivate: { description: 'Deactivate modality', requires: ['recordId'] }
260
- }
261
- },
262
- ticket: {
263
- description: 'Tickets and occurrences',
264
- operations: {
265
- getAll: { description: 'List all tickets', requires: [] },
266
- get: { description: 'Get ticket by ID', requires: ['recordId'] },
267
- create: { description: 'Create new ticket', requires: ['data'] },
268
- update: { description: 'Update ticket', requires: ['recordId', 'data'] },
269
- activate: { description: 'Activate ticket', requires: ['recordId'] },
270
- deactivate: { description: 'Deactivate ticket', requires: ['recordId'] }
271
- }
272
- },
273
- property: {
274
- description: 'Properties',
275
- operations: {
276
- getAll: { description: 'List all properties', requires: [] },
277
- get: { description: 'Get property by ID', requires: ['recordId'] },
278
- create: { description: 'Create new property', requires: ['data'] },
279
- update: { description: 'Update property', requires: ['recordId', 'data'] },
280
- activate: { description: 'Activate property', requires: ['recordId'] },
281
- deactivate: { description: 'Deactivate property', requires: ['recordId'] }
282
- }
283
- }
284
- },
285
- // Common operation patterns
286
- operationPatterns: {
287
- 'list all X / show all X / get all X': 'operation=getAll',
288
- 'show X / get X [id]': 'operation=get, recordId=[id]',
289
- 'create X / add X / new X': 'operation=create, data={...}',
290
- 'update X / modify X / change X': 'operation=update, recordId=[id], data={...}',
291
- 'activate X / enable X': 'operation=activate, recordId=[id]',
292
- 'deactivate X / disable X': 'operation=deactivate, recordId=[id]'
293
- },
294
- // Explicit examples
295
- examples: [
296
- {
297
- input: 'list all users',
298
- params: { resource: 'user', operation: 'getAll' }
299
- },
300
- {
301
- input: 'show user 123',
302
- params: { resource: 'user', operation: 'get', recordId: '123' }
303
- },
304
- {
305
- input: 'create client ABC Corp',
306
- params: {
307
- resource: 'client',
308
- operation: 'create',
309
- data: '{"name":"ABC Corp"}'
310
- }
311
- },
312
- {
313
- input: 'update task 456 to completed',
314
- params: {
315
- resource: 'task',
316
- operation: 'update',
317
- recordId: '456',
318
- data: '{"status":"completed"}'
319
- }
320
- },
321
- {
322
- input: 'list todos usuarios',
323
- params: { resource: 'user', operation: 'getAll' }
324
- },
325
- {
326
- input: 'mostrar clientes',
327
- params: { resource: 'client', operation: 'getAll' }
328
- }
329
- ],
330
- // CRITICAL: Exact value mapping
331
- valueMapping: {
332
- 'users/usuarios/usuários/employees/funcionários': 'user',
333
- 'clients/clientes/customers': 'client',
334
- 'items/itens': 'item',
335
- 'tasks/tarefas': 'task',
336
- 'services/serviços/servicos': 'service',
337
- 'products/produtos': 'product',
338
- 'orders/ordens/pedidos': 'order',
339
- 'tickets/chamados': 'ticket',
340
- 'properties/propriedades': 'property',
341
- 'list/listar/mostrar/show/get all/buscar todos': 'getAll',
342
- 'get/buscar/obter/show one': 'get',
343
- 'create/criar/adicionar/add/new/novo': 'create',
344
- 'update/atualizar/modificar/modify/change': 'update',
345
- 'activate/ativar/enable/habilitar': 'activate',
346
- 'deactivate/desativar/disable/desabilitar': 'deactivate'
347
- }
348
- };
349
- }
350
106
  async execute() {
351
107
  const items = this.getInputData();
352
108
  const returnData = [];
@@ -367,37 +123,40 @@ class Confirm8AgentTool {
367
123
  data = JSON.parse(dataParam);
368
124
  }
369
125
  catch (e) {
370
- // Ignore
126
+ // Ignore parse errors
371
127
  }
372
128
  }
373
- // Normalize resource and operation (handle common variations)
129
+ // Normalize common variations
374
130
  const resourceMap = {
375
- 'users': 'user', 'usuarios': 'user', 'usuários': 'user', 'employees': 'user',
131
+ 'users': 'user', 'usuarios': 'user', 'usuários': 'user', 'employees': 'user', 'funcionários': 'user',
376
132
  'clients': 'client', 'clientes': 'client', 'customers': 'client',
377
133
  'items': 'item', 'itens': 'item',
134
+ 'itemtypes': 'itemType', 'tipos': 'itemType',
378
135
  'tasks': 'task', 'tarefas': 'task',
379
136
  'services': 'service', 'serviços': 'service', 'servicos': 'service',
380
137
  'products': 'product', 'produtos': 'product',
381
- 'orders': 'order', 'ordens': 'order', 'pedidos': 'order',
138
+ 'orders': 'order', 'ordens': 'order', 'pedidos': 'order', 'wos': 'order',
139
+ 'modalities': 'modality', 'modalidades': 'modality',
382
140
  'tickets': 'ticket', 'chamados': 'ticket',
383
141
  'properties': 'property', 'propriedades': 'property',
384
- 'modalities': 'modality', 'modalidades': 'modality'
385
142
  };
386
143
  const operationMap = {
387
144
  'list': 'getAll', 'listar': 'getAll', 'mostrar': 'getAll', 'show': 'getAll',
388
- 'buscar': 'get', 'obter': 'get',
145
+ 'buscar': 'getAll', 'busque': 'getAll', 'buscar todos': 'getAll', 'get all': 'getAll',
146
+ 'show all': 'getAll', 'list all': 'getAll', 'todos': 'getAll',
147
+ 'obter': 'get', 'pegar': 'get',
389
148
  'criar': 'create', 'adicionar': 'create', 'add': 'create', 'novo': 'create', 'new': 'create',
390
- 'atualizar': 'update', 'modificar': 'update', 'modify': 'update',
149
+ 'atualizar': 'update', 'modificar': 'update', 'modify': 'update', 'editar': 'update',
391
150
  'ativar': 'activate', 'enable': 'activate', 'habilitar': 'activate',
392
- 'desativar': 'deactivate', 'disable': 'deactivate', 'desabilitar': 'deactivate'
151
+ 'desativar': 'deactivate', 'disable': 'deactivate', 'desabilitar': 'deactivate',
393
152
  };
394
153
  // Normalize
395
- resource = resourceMap[resource.toLowerCase()] || resource;
396
- operation = operationMap[operation.toLowerCase()] || operation;
154
+ resource = resourceMap[resource.toLowerCase().trim()] || resource;
155
+ operation = operationMap[operation.toLowerCase().trim()] || operation;
397
156
  if (!resource || !operation) {
398
157
  throw new Error('Resource and operation are required');
399
158
  }
400
- // Map to API endpoints
159
+ // Map to endpoints
401
160
  const endpointMap = {
402
161
  user: 'users',
403
162
  client: 'clients',
@@ -411,7 +170,10 @@ class Confirm8AgentTool {
411
170
  ticket: 'tickets',
412
171
  property: 'properties',
413
172
  };
414
- const baseEndpoint = endpointMap[resource] || resource;
173
+ const baseEndpoint = endpointMap[resource];
174
+ if (!baseEndpoint) {
175
+ throw new Error(`Unknown resource: ${resource}. Must be one of: user, client, item, itemType, task, service, product, order, modality, ticket, property`);
176
+ }
415
177
  let endpoint = '';
416
178
  let method = 'GET';
417
179
  let body = {};
@@ -422,7 +184,7 @@ class Confirm8AgentTool {
422
184
  break;
423
185
  case 'get':
424
186
  if (!recordId)
425
- throw new Error('recordId required');
187
+ throw new Error('recordId required for get operation');
426
188
  endpoint = `/${baseEndpoint}/${recordId}`;
427
189
  break;
428
190
  case 'create':
@@ -432,76 +194,27 @@ class Confirm8AgentTool {
432
194
  break;
433
195
  case 'update':
434
196
  if (!recordId)
435
- throw new Error('recordId required');
197
+ throw new Error('recordId required for update operation');
436
198
  endpoint = `/${baseEndpoint}/${recordId}`;
437
199
  method = 'PUT';
438
200
  body = data;
439
201
  break;
440
202
  case 'activate':
441
203
  if (!recordId)
442
- throw new Error('recordId required');
204
+ throw new Error('recordId required for activate operation');
443
205
  endpoint = `/${baseEndpoint}/${recordId}/active`;
444
206
  method = ['client', 'item', 'itemType', 'task', 'service', 'product', 'order', 'modality'].includes(resource)
445
207
  ? 'PUT' : 'PATCH';
446
208
  break;
447
209
  case 'deactivate':
448
210
  if (!recordId)
449
- throw new Error('recordId required');
211
+ throw new Error('recordId required for deactivate operation');
450
212
  endpoint = `/${baseEndpoint}/${recordId}/inactive`;
451
213
  method = ['client', 'item', 'itemType', 'task', 'service', 'product', 'order', 'modality'].includes(resource)
452
214
  ? 'PUT' : 'PATCH';
453
215
  break;
454
- case 'getByUsername':
455
- if (!data.username)
456
- throw new Error('username required in data');
457
- endpoint = `/users/${data.username}/user`;
458
- break;
459
- case 'getTickets':
460
- if (!recordId)
461
- throw new Error('recordId required');
462
- endpoint = `/users/${recordId}/tickets`;
463
- break;
464
- case 'getTasks':
465
- if (!recordId)
466
- throw new Error('recordId required');
467
- endpoint = `/users/${recordId}/tasks`;
468
- break;
469
- case 'getPermissions':
470
- if (!recordId)
471
- throw new Error('recordId required');
472
- endpoint = `/users/${recordId}/permissions`;
473
- break;
474
- case 'linkTasks':
475
- endpoint = '/users/tasks';
476
- method = 'POST';
477
- body = data;
478
- break;
479
- case 'deleteLinkedTasks':
480
- endpoint = '/users/tasks';
481
- method = 'DELETE';
482
- break;
483
- case 'deleteLinkedTasksByUser':
484
- if (!data.employeeId)
485
- throw new Error('employeeId required');
486
- endpoint = `/users/tasks/${data.employeeId}`;
487
- method = 'DELETE';
488
- break;
489
- case 'uploadPhoto':
490
- if (!recordId)
491
- throw new Error('recordId required');
492
- endpoint = `/users/${recordId}/photos`;
493
- method = 'PATCH';
494
- body = data;
495
- break;
496
- case 'uploadSignature':
497
- if (!recordId)
498
- throw new Error('recordId required');
499
- endpoint = `/users/${recordId}/signatures`;
500
- method = 'PATCH';
501
- body = data;
502
- break;
503
216
  default:
504
- throw new Error(`Unknown operation: ${operation}`);
217
+ throw new Error(`Unknown operation: ${operation}. Must be one of: getAll, get, create, update, activate, deactivate`);
505
218
  }
506
219
  // Make request
507
220
  const url = `${baseUrl}${endpoint}`;
@@ -525,7 +238,14 @@ class Confirm8AgentTool {
525
238
  success: true,
526
239
  operation,
527
240
  resource,
241
+ normalized: {
242
+ originalResource: this.getNodeParameter('resource', i, ''),
243
+ originalOperation: this.getNodeParameter('operation', i, ''),
244
+ normalizedResource: resource,
245
+ normalizedOperation: operation,
246
+ },
528
247
  endpoint,
248
+ method,
529
249
  data: responseData,
530
250
  },
531
251
  pairedItem: { item: i },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-confirm8",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "description": "Simple n8n node for Confirm8 API - no credentials needed",
5
5
  "license": "MIT",
6
6
  "author": "Bill Hebert",