n8n-nodes-confirm8 0.13.0 → 0.16.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.
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, IDataObject } from 'n8n-workflow';
|
|
2
|
+
export declare class Confirm8AgentTool implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
/**
|
|
5
|
+
* Complete tool description for AI Agent
|
|
6
|
+
* The AI will use this to understand ALL available operations
|
|
7
|
+
*/
|
|
8
|
+
getToolDescription(): IDataObject;
|
|
9
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Confirm8AgentTool = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
class Confirm8AgentTool {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.description = {
|
|
8
|
+
displayName: 'Confirm8 AI Tool',
|
|
9
|
+
name: 'confirm8AgentTool',
|
|
10
|
+
icon: 'file:tool.svg',
|
|
11
|
+
group: ['transform'],
|
|
12
|
+
version: 1,
|
|
13
|
+
description: 'Autonomous AI Agent tool for Confirm8 API - AI decides everything',
|
|
14
|
+
defaults: {
|
|
15
|
+
name: 'Confirm8 AI Tool',
|
|
16
|
+
},
|
|
17
|
+
// CRITICAL: Makes this node usable as an AI Agent Tool
|
|
18
|
+
usableAsTool: true,
|
|
19
|
+
inputs: ['main'],
|
|
20
|
+
outputs: ['main'],
|
|
21
|
+
properties: [
|
|
22
|
+
// ONLY API Configuration - AI decides the rest
|
|
23
|
+
{
|
|
24
|
+
displayName: 'Base URL',
|
|
25
|
+
name: 'baseUrl',
|
|
26
|
+
type: 'string',
|
|
27
|
+
default: '',
|
|
28
|
+
placeholder: 'https://api.confirm8.com',
|
|
29
|
+
required: true,
|
|
30
|
+
description: 'Base URL of Confirm8 API',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
displayName: 'Bearer Token',
|
|
34
|
+
name: 'bearerToken',
|
|
35
|
+
type: 'string',
|
|
36
|
+
typeOptions: { password: true },
|
|
37
|
+
default: '',
|
|
38
|
+
required: true,
|
|
39
|
+
description: 'Authentication token',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
displayName: 'X-API-DOMAIN',
|
|
43
|
+
name: 'apiDomain',
|
|
44
|
+
type: 'string',
|
|
45
|
+
default: '',
|
|
46
|
+
required: true,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
displayName: 'X-APIKEY-TOKEN',
|
|
50
|
+
name: 'apiKeyToken',
|
|
51
|
+
type: 'string',
|
|
52
|
+
typeOptions: { password: true },
|
|
53
|
+
default: '',
|
|
54
|
+
required: true,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Complete tool description for AI Agent
|
|
61
|
+
* The AI will use this to understand ALL available operations
|
|
62
|
+
*/
|
|
63
|
+
getToolDescription() {
|
|
64
|
+
return {
|
|
65
|
+
name: 'confirm8_api',
|
|
66
|
+
description: 'Complete Confirm8 API access tool. Use this to interact with the Confirm8 system. ' +
|
|
67
|
+
'You can fetch, create, update, activate, or deactivate any resource. ' +
|
|
68
|
+
'\n\n**Available Resources:**\n' +
|
|
69
|
+
'- user (users/employees)\n' +
|
|
70
|
+
'- client (clients/customers)\n' +
|
|
71
|
+
'- item (items/products inventory)\n' +
|
|
72
|
+
'- itemType (item type categories)\n' +
|
|
73
|
+
'- task (tasks/checklists)\n' +
|
|
74
|
+
'- service (services)\n' +
|
|
75
|
+
'- product (products/insumos)\n' +
|
|
76
|
+
'- order (work orders/WOS)\n' +
|
|
77
|
+
'- modality (order modalities)\n' +
|
|
78
|
+
'- ticket (tickets/occurrences)\n' +
|
|
79
|
+
'- property (properties)\n' +
|
|
80
|
+
'\n**Available Operations:**\n' +
|
|
81
|
+
'- getAll: List all records (no ID needed)\n' +
|
|
82
|
+
'- get: Get single record (requires recordId)\n' +
|
|
83
|
+
'- create: Create new record (requires data)\n' +
|
|
84
|
+
'- update: Update existing record (requires recordId and data)\n' +
|
|
85
|
+
'- activate: Activate/enable record (requires recordId)\n' +
|
|
86
|
+
'- deactivate: Deactivate/disable record (requires recordId)\n' +
|
|
87
|
+
'\n**Special User Operations:**\n' +
|
|
88
|
+
'- getByUsername: Get user by username (requires username in data)\n' +
|
|
89
|
+
'- getTickets: Get user tickets (requires recordId)\n' +
|
|
90
|
+
'- getTasks: Get user tasks (requires recordId)\n' +
|
|
91
|
+
'- getPermissions: Get user permissions (requires recordId)\n' +
|
|
92
|
+
'- linkTasks: Link tasks to user (requires data with userId and taskIds)\n' +
|
|
93
|
+
'- deleteLinkedTasks: Delete all linked tasks\n' +
|
|
94
|
+
'- deleteLinkedTasksByUser: Delete tasks by user (requires employeeId in data)\n' +
|
|
95
|
+
'- uploadPhoto: Upload user photo (requires recordId and photo data)\n' +
|
|
96
|
+
'- uploadSignature: Upload user signature (requires recordId and signature data)\n' +
|
|
97
|
+
'\n**Examples:**\n' +
|
|
98
|
+
'- List all users: resource="user", operation="getAll"\n' +
|
|
99
|
+
'- Get client 123: resource="client", operation="get", recordId="123"\n' +
|
|
100
|
+
'- Create product: resource="product", operation="create", data={"name":"Product X","price":99.99}\n' +
|
|
101
|
+
'- Update task: resource="task", operation="update", recordId="456", data={"status":"completed"}\n' +
|
|
102
|
+
'- Activate user: resource="user", operation="activate", recordId="789"\n' +
|
|
103
|
+
'- Get user tickets: resource="user", operation="getTickets", recordId="123"',
|
|
104
|
+
properties: [
|
|
105
|
+
{
|
|
106
|
+
displayName: 'Resource',
|
|
107
|
+
name: 'resource',
|
|
108
|
+
type: 'string',
|
|
109
|
+
required: true,
|
|
110
|
+
description: 'Resource type: user, client, item, itemType, task, service, product, order, modality, ticket, or property',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
displayName: 'Operation',
|
|
114
|
+
name: 'operation',
|
|
115
|
+
type: 'string',
|
|
116
|
+
required: true,
|
|
117
|
+
description: 'Operation: getAll, get, create, update, activate, deactivate, or special operations (getByUsername, getTickets, getTasks, etc.)',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
displayName: 'Record ID',
|
|
121
|
+
name: 'recordId',
|
|
122
|
+
type: 'string',
|
|
123
|
+
required: false,
|
|
124
|
+
description: 'ID of the record (required for get, update, activate, deactivate, and some special operations)',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
displayName: 'Data',
|
|
128
|
+
name: 'data',
|
|
129
|
+
type: 'json',
|
|
130
|
+
required: false,
|
|
131
|
+
description: 'JSON data for create/update operations or additional parameters. Example: {"name":"John","email":"john@example.com"}',
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
async execute() {
|
|
137
|
+
const items = this.getInputData();
|
|
138
|
+
const returnData = [];
|
|
139
|
+
for (let i = 0; i < items.length; i++) {
|
|
140
|
+
try {
|
|
141
|
+
// Get API configuration (only thing configured in the UI)
|
|
142
|
+
const baseUrl = this.getNodeParameter('baseUrl', i);
|
|
143
|
+
const bearerToken = this.getNodeParameter('bearerToken', i);
|
|
144
|
+
const apiDomain = this.getNodeParameter('apiDomain', i);
|
|
145
|
+
const apiKeyToken = this.getNodeParameter('apiKeyToken', i);
|
|
146
|
+
// Get operation parameters from the TOOL CALL (provided by AI)
|
|
147
|
+
const resource = this.getNodeParameter('resource', i);
|
|
148
|
+
const operation = this.getNodeParameter('operation', i);
|
|
149
|
+
const recordId = this.getNodeParameter('recordId', i, '');
|
|
150
|
+
// Parse data if provided
|
|
151
|
+
let data = {};
|
|
152
|
+
try {
|
|
153
|
+
const dataParam = this.getNodeParameter('data', i, '');
|
|
154
|
+
if (dataParam) {
|
|
155
|
+
if (typeof dataParam === 'string') {
|
|
156
|
+
data = JSON.parse(dataParam);
|
|
157
|
+
}
|
|
158
|
+
else if (typeof dataParam === 'object') {
|
|
159
|
+
data = dataParam;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch (e) {
|
|
164
|
+
// Data is optional
|
|
165
|
+
}
|
|
166
|
+
// Map resource to API endpoint
|
|
167
|
+
const resourceMap = {
|
|
168
|
+
user: 'users',
|
|
169
|
+
client: 'clients',
|
|
170
|
+
item: 'items',
|
|
171
|
+
itemType: 'itemTypes',
|
|
172
|
+
task: 'tasks',
|
|
173
|
+
service: 'services',
|
|
174
|
+
product: 'products',
|
|
175
|
+
order: 'wos',
|
|
176
|
+
modality: 'modalities',
|
|
177
|
+
ticket: 'tickets',
|
|
178
|
+
property: 'properties',
|
|
179
|
+
};
|
|
180
|
+
const baseEndpoint = resourceMap[resource] || resource;
|
|
181
|
+
let endpoint = '';
|
|
182
|
+
let method = 'GET';
|
|
183
|
+
let body = {};
|
|
184
|
+
// Build request based on operation
|
|
185
|
+
switch (operation) {
|
|
186
|
+
case 'getAll':
|
|
187
|
+
endpoint = `/${baseEndpoint}`;
|
|
188
|
+
method = 'GET';
|
|
189
|
+
break;
|
|
190
|
+
case 'get':
|
|
191
|
+
if (!recordId) {
|
|
192
|
+
throw new Error('recordId is required for get operation');
|
|
193
|
+
}
|
|
194
|
+
endpoint = `/${baseEndpoint}/${recordId}`;
|
|
195
|
+
method = 'GET';
|
|
196
|
+
break;
|
|
197
|
+
case 'create':
|
|
198
|
+
endpoint = `/${baseEndpoint}`;
|
|
199
|
+
method = 'POST';
|
|
200
|
+
body = data;
|
|
201
|
+
break;
|
|
202
|
+
case 'update':
|
|
203
|
+
if (!recordId) {
|
|
204
|
+
throw new Error('recordId is required for update operation');
|
|
205
|
+
}
|
|
206
|
+
endpoint = `/${baseEndpoint}/${recordId}`;
|
|
207
|
+
method = 'PUT';
|
|
208
|
+
body = data;
|
|
209
|
+
break;
|
|
210
|
+
case 'activate':
|
|
211
|
+
if (!recordId) {
|
|
212
|
+
throw new Error('recordId is required for activate operation');
|
|
213
|
+
}
|
|
214
|
+
endpoint = `/${baseEndpoint}/${recordId}/active`;
|
|
215
|
+
// Different resources use different methods
|
|
216
|
+
if (['client', 'item', 'itemType', 'task', 'service', 'product', 'order', 'modality'].includes(resource)) {
|
|
217
|
+
method = 'PUT';
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
method = 'PATCH';
|
|
221
|
+
}
|
|
222
|
+
break;
|
|
223
|
+
case 'deactivate':
|
|
224
|
+
if (!recordId) {
|
|
225
|
+
throw new Error('recordId is required for deactivate operation');
|
|
226
|
+
}
|
|
227
|
+
endpoint = `/${baseEndpoint}/${recordId}/inactive`;
|
|
228
|
+
// Different resources use different methods
|
|
229
|
+
if (['client', 'item', 'itemType', 'task', 'service', 'product', 'order', 'modality'].includes(resource)) {
|
|
230
|
+
method = 'PUT';
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
method = 'PATCH';
|
|
234
|
+
}
|
|
235
|
+
break;
|
|
236
|
+
// Special User Operations
|
|
237
|
+
case 'getByUsername':
|
|
238
|
+
if (!data.username) {
|
|
239
|
+
throw new Error('username is required in data for getByUsername operation');
|
|
240
|
+
}
|
|
241
|
+
endpoint = `/users/${data.username}/user`;
|
|
242
|
+
method = 'GET';
|
|
243
|
+
break;
|
|
244
|
+
case 'getTickets':
|
|
245
|
+
if (!recordId) {
|
|
246
|
+
throw new Error('recordId is required for getTickets operation');
|
|
247
|
+
}
|
|
248
|
+
endpoint = `/users/${recordId}/tickets`;
|
|
249
|
+
method = 'GET';
|
|
250
|
+
break;
|
|
251
|
+
case 'getTasks':
|
|
252
|
+
if (!recordId) {
|
|
253
|
+
throw new Error('recordId is required for getTasks operation');
|
|
254
|
+
}
|
|
255
|
+
endpoint = `/users/${recordId}/tasks`;
|
|
256
|
+
method = 'GET';
|
|
257
|
+
break;
|
|
258
|
+
case 'getPermissions':
|
|
259
|
+
if (!recordId) {
|
|
260
|
+
throw new Error('recordId is required for getPermissions operation');
|
|
261
|
+
}
|
|
262
|
+
endpoint = `/users/${recordId}/permissions`;
|
|
263
|
+
method = 'GET';
|
|
264
|
+
break;
|
|
265
|
+
case 'linkTasks':
|
|
266
|
+
endpoint = '/users/tasks';
|
|
267
|
+
method = 'POST';
|
|
268
|
+
body = data;
|
|
269
|
+
break;
|
|
270
|
+
case 'deleteLinkedTasks':
|
|
271
|
+
endpoint = '/users/tasks';
|
|
272
|
+
method = 'DELETE';
|
|
273
|
+
break;
|
|
274
|
+
case 'deleteLinkedTasksByUser':
|
|
275
|
+
if (!data.employeeId) {
|
|
276
|
+
throw new Error('employeeId is required in data for deleteLinkedTasksByUser operation');
|
|
277
|
+
}
|
|
278
|
+
endpoint = `/users/tasks/${data.employeeId}`;
|
|
279
|
+
method = 'DELETE';
|
|
280
|
+
break;
|
|
281
|
+
case 'uploadPhoto':
|
|
282
|
+
if (!recordId) {
|
|
283
|
+
throw new Error('recordId is required for uploadPhoto operation');
|
|
284
|
+
}
|
|
285
|
+
endpoint = `/users/${recordId}/photos`;
|
|
286
|
+
method = 'PATCH';
|
|
287
|
+
body = data;
|
|
288
|
+
break;
|
|
289
|
+
case 'uploadSignature':
|
|
290
|
+
if (!recordId) {
|
|
291
|
+
throw new Error('recordId is required for uploadSignature operation');
|
|
292
|
+
}
|
|
293
|
+
endpoint = `/users/${recordId}/signatures`;
|
|
294
|
+
method = 'PATCH';
|
|
295
|
+
body = data;
|
|
296
|
+
break;
|
|
297
|
+
default:
|
|
298
|
+
throw new Error(`Unknown operation: ${operation}`);
|
|
299
|
+
}
|
|
300
|
+
// Make HTTP request
|
|
301
|
+
const url = `${baseUrl}${endpoint}`;
|
|
302
|
+
const options = {
|
|
303
|
+
method,
|
|
304
|
+
uri: url,
|
|
305
|
+
headers: {
|
|
306
|
+
'Authorization': `Bearer ${bearerToken}`,
|
|
307
|
+
'X-API-DOMAIN': apiDomain,
|
|
308
|
+
'X-APIKEY-TOKEN': apiKeyToken,
|
|
309
|
+
'Content-Type': 'application/json',
|
|
310
|
+
},
|
|
311
|
+
json: true,
|
|
312
|
+
};
|
|
313
|
+
if (method !== 'GET' && method !== 'DELETE' && Object.keys(body).length > 0) {
|
|
314
|
+
options.body = body;
|
|
315
|
+
}
|
|
316
|
+
const responseData = await this.helpers.request(options);
|
|
317
|
+
returnData.push({
|
|
318
|
+
json: {
|
|
319
|
+
success: true,
|
|
320
|
+
operation,
|
|
321
|
+
resource,
|
|
322
|
+
endpoint,
|
|
323
|
+
data: responseData,
|
|
324
|
+
},
|
|
325
|
+
pairedItem: { item: i },
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
if (this.continueOnFail()) {
|
|
330
|
+
returnData.push({
|
|
331
|
+
json: {
|
|
332
|
+
success: false,
|
|
333
|
+
error: error || 'Unknown error',
|
|
334
|
+
resource: this.getNodeParameter('resource', i, ''),
|
|
335
|
+
operation: this.getNodeParameter('operation', i, ''),
|
|
336
|
+
},
|
|
337
|
+
pairedItem: { item: i },
|
|
338
|
+
});
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex: i });
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return [returnData];
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
exports.Confirm8AgentTool = Confirm8AgentTool;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-confirm8",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Simple n8n node for Confirm8 API - no credentials needed",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bill Hebert",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
},
|
|
22
22
|
"n8n": {
|
|
23
23
|
"nodes": [
|
|
24
|
-
"dist/nodes/Confirm8/ApiConfirm8.node.js"
|
|
24
|
+
"dist/nodes/Confirm8/ApiConfirm8.node.js",
|
|
25
|
+
"dist/nodes/Confirm8Tool/Confirm8AgentTool.node.js"
|
|
25
26
|
]
|
|
26
27
|
},
|
|
27
28
|
"peerDependencies": {
|