n8n-nodes-graphorlm 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Graphor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # n8n-nodes-graphorlm
2
+
3
+ This is an n8n community node that lets you interact with [Graphor](https://graphorlm.com) - an intelligent document processing platform with RAG pipelines, document chat, and data extraction capabilities.
4
+
5
+ [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.
6
+
7
+ ## Installation
8
+
9
+ Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.
10
+
11
+ ### npm
12
+
13
+ ```bash
14
+ npm install n8n-nodes-graphorlm
15
+ ```
16
+
17
+ ### n8n Desktop/Cloud
18
+
19
+ 1. Go to **Settings** > **Community Nodes**
20
+ 2. Select **Install**
21
+ 3. Enter `n8n-nodes-graphorlm` and agree to the risks
22
+ 4. Click **Install**
23
+
24
+ ## Operations
25
+
26
+ ### Chat
27
+ - **Ask Question**: Ask questions about your documents using natural language with conversational memory support
28
+
29
+ ### Extraction
30
+ - **Extract Data**: Extract structured data from documents using JSON Schema definitions
31
+
32
+ ### Flow
33
+ - **List**: List all flows in your project
34
+ - **Run**: Execute a deployed RAG flow with a query
35
+ - **Deploy**: Deploy a flow to make it accessible via API
36
+
37
+ ### Source
38
+ - **List**: List all sources in your project
39
+ - **Upload File**: Upload a file (PDF, DOCX, images, audio, video)
40
+ - **Upload From URL**: Ingest content from a web page URL
41
+ - **Upload From GitHub**: Ingest content from a public GitHub repository
42
+ - **Upload From YouTube**: Ingest content from a YouTube video
43
+ - **Process**: Process a source with OCR/parsing (Basic, Hi-Res, Hi-Res FT, MAI, GraphorLM)
44
+ - **Get Elements**: Get structured elements from a processed source
45
+ - **Delete**: Delete a source from your project
46
+
47
+ ## Credentials
48
+
49
+ To use this node, you need a Graphor API token:
50
+
51
+ 1. Log in to your [Graphor account](https://app.graphorlm.com)
52
+ 2. Go to **Settings** > **API Tokens**
53
+ 3. Create a new API token
54
+ 4. Copy the token (it starts with `grlm_`)
55
+
56
+ ## Supported File Types
57
+
58
+ - **Documents**: PDF, DOC, DOCX, ODT, TXT, MD, HTML
59
+ - **Presentations**: PPT, PPTX
60
+ - **Spreadsheets**: CSV, TSV, XLS, XLSX
61
+ - **Images**: PNG, JPG, JPEG, TIFF, BMP, HEIC
62
+ - **Audio**: MP3, WAV, M4A, OGG, FLAC
63
+ - **Video**: MP4, MOV, AVI, MKV, WEBM
64
+
65
+ ## Processing Methods
66
+
67
+ | Method | Description |
68
+ |--------|-------------|
69
+ | **Basic** | Fast processing with heuristic classification |
70
+ | **Hi-Res** | High resolution processing with advanced layout detection |
71
+ | **Hi-Res FT** | Fine-tuned high resolution processing |
72
+ | **MAI** | Multi-modal AI processing |
73
+ | **GraphorLM** | Graphor proprietary processing method |
74
+
75
+ ## Compatibility
76
+
77
+ - n8n version 1.0.0 or later
78
+ - Node.js 18.0.0 or later
79
+
80
+ ## Resources
81
+
82
+ - [Graphor Documentation](https://docs.graphorlm.com)
83
+ - [Graphor API Reference](https://docs.graphorlm.com/api-reference/overview)
84
+ - [n8n Community Nodes Documentation](https://docs.n8n.io/integrations/community-nodes/)
85
+
86
+ ## License
87
+
88
+ [MIT](LICENSE)
@@ -0,0 +1,9 @@
1
+ import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class GraphorApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ authenticate: IAuthenticateGeneric;
8
+ test: ICredentialTestRequest;
9
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GraphorApi = void 0;
4
+ class GraphorApi {
5
+ constructor() {
6
+ this.name = 'graphorApi';
7
+ this.displayName = 'Graphor API';
8
+ this.documentationUrl = 'https://docs.graphorlm.com/guides/api-tokens';
9
+ this.properties = [
10
+ {
11
+ displayName: 'API Token',
12
+ name: 'apiToken',
13
+ type: 'string',
14
+ typeOptions: {
15
+ password: true,
16
+ },
17
+ default: '',
18
+ required: true,
19
+ description: 'Your Graphor API token (starts with grlm_)',
20
+ },
21
+ ];
22
+ this.authenticate = {
23
+ type: 'generic',
24
+ properties: {
25
+ headers: {
26
+ Authorization: '=Bearer {{$credentials.apiToken}}',
27
+ },
28
+ },
29
+ };
30
+ this.test = {
31
+ request: {
32
+ baseURL: 'https://sources.graphorlm.com',
33
+ url: '/',
34
+ method: 'GET',
35
+ },
36
+ };
37
+ }
38
+ }
39
+ exports.GraphorApi = GraphorApi;
@@ -0,0 +1,5 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class Graphor implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,712 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Graphor = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ class Graphor {
6
+ constructor() {
7
+ this.description = {
8
+ displayName: 'Graphor',
9
+ name: 'graphor',
10
+ icon: 'file:graphor.svg',
11
+ group: ['transform'],
12
+ version: 1,
13
+ subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
14
+ description: 'Interact with Graphor API for document processing, RAG, and AI-powered document chat',
15
+ defaults: {
16
+ name: 'Graphor',
17
+ },
18
+ inputs: ['main'],
19
+ outputs: ['main'],
20
+ credentials: [
21
+ {
22
+ name: 'graphorApi',
23
+ required: true,
24
+ },
25
+ ],
26
+ properties: [
27
+ // Resource Selection
28
+ {
29
+ displayName: 'Resource',
30
+ name: 'resource',
31
+ type: 'options',
32
+ noDataExpression: true,
33
+ options: [
34
+ {
35
+ name: 'Chat',
36
+ value: 'chat',
37
+ description: 'Ask questions about your documents',
38
+ },
39
+ {
40
+ name: 'Extraction',
41
+ value: 'extraction',
42
+ description: 'Extract structured data from documents',
43
+ },
44
+ {
45
+ name: 'Flow',
46
+ value: 'flow',
47
+ description: 'Manage and run RAG flows',
48
+ },
49
+ {
50
+ name: 'Source',
51
+ value: 'source',
52
+ description: 'Manage document sources',
53
+ },
54
+ ],
55
+ default: 'chat',
56
+ },
57
+ // ==================== CHAT OPERATIONS ====================
58
+ {
59
+ displayName: 'Operation',
60
+ name: 'operation',
61
+ type: 'options',
62
+ noDataExpression: true,
63
+ displayOptions: {
64
+ show: {
65
+ resource: ['chat'],
66
+ },
67
+ },
68
+ options: [
69
+ {
70
+ name: 'Ask Question',
71
+ value: 'askQuestion',
72
+ description: 'Ask a question about your documents',
73
+ action: 'Ask a question about your documents',
74
+ },
75
+ ],
76
+ default: 'askQuestion',
77
+ },
78
+ // Chat - Ask Question fields
79
+ {
80
+ displayName: 'Question',
81
+ name: 'question',
82
+ type: 'string',
83
+ required: true,
84
+ default: '',
85
+ displayOptions: {
86
+ show: {
87
+ resource: ['chat'],
88
+ operation: ['askQuestion'],
89
+ },
90
+ },
91
+ description: 'The question to ask about your documents',
92
+ },
93
+ {
94
+ displayName: 'Additional Fields',
95
+ name: 'additionalFields',
96
+ type: 'collection',
97
+ placeholder: 'Add Field',
98
+ default: {},
99
+ displayOptions: {
100
+ show: {
101
+ resource: ['chat'],
102
+ operation: ['askQuestion'],
103
+ },
104
+ },
105
+ options: [
106
+ {
107
+ displayName: 'Conversation ID',
108
+ name: 'conversationId',
109
+ type: 'string',
110
+ default: '',
111
+ description: 'Conversation identifier to maintain memory context across questions',
112
+ },
113
+ {
114
+ displayName: 'File Names',
115
+ name: 'fileNames',
116
+ type: 'string',
117
+ default: '',
118
+ description: 'Comma-separated list of file names to restrict search to specific documents',
119
+ },
120
+ {
121
+ displayName: 'Reset Conversation',
122
+ name: 'reset',
123
+ type: 'boolean',
124
+ default: false,
125
+ description: 'Whether to start a new conversation and ignore previous history',
126
+ },
127
+ {
128
+ displayName: 'Output Schema',
129
+ name: 'outputSchema',
130
+ type: 'json',
131
+ default: '',
132
+ description: 'JSON Schema to request structured output',
133
+ },
134
+ ],
135
+ },
136
+ // ==================== EXTRACTION OPERATIONS ====================
137
+ {
138
+ displayName: 'Operation',
139
+ name: 'operation',
140
+ type: 'options',
141
+ noDataExpression: true,
142
+ displayOptions: {
143
+ show: {
144
+ resource: ['extraction'],
145
+ },
146
+ },
147
+ options: [
148
+ {
149
+ name: 'Extract Data',
150
+ value: 'extractData',
151
+ description: 'Extract structured data from documents using JSON Schema',
152
+ action: 'Extract structured data from documents',
153
+ },
154
+ ],
155
+ default: 'extractData',
156
+ },
157
+ // Extraction - Extract Data fields
158
+ {
159
+ displayName: 'File Names',
160
+ name: 'fileNames',
161
+ type: 'string',
162
+ required: true,
163
+ default: '',
164
+ displayOptions: {
165
+ show: {
166
+ resource: ['extraction'],
167
+ operation: ['extractData'],
168
+ },
169
+ },
170
+ description: 'Comma-separated list of file names to extract from',
171
+ },
172
+ {
173
+ displayName: 'User Instruction',
174
+ name: 'userInstruction',
175
+ type: 'string',
176
+ required: true,
177
+ default: '',
178
+ displayOptions: {
179
+ show: {
180
+ resource: ['extraction'],
181
+ operation: ['extractData'],
182
+ },
183
+ },
184
+ description: 'Natural language instructions to guide the extraction',
185
+ },
186
+ {
187
+ displayName: 'Output Schema',
188
+ name: 'outputSchema',
189
+ type: 'json',
190
+ required: true,
191
+ default: '{\n "type": "object",\n "properties": {\n "field_name": {\n "type": "string",\n "description": "Description of the field"\n }\n }\n}',
192
+ displayOptions: {
193
+ show: {
194
+ resource: ['extraction'],
195
+ operation: ['extractData'],
196
+ },
197
+ },
198
+ description: 'JSON Schema defining the structure of the extracted data',
199
+ },
200
+ // ==================== FLOW OPERATIONS ====================
201
+ {
202
+ displayName: 'Operation',
203
+ name: 'operation',
204
+ type: 'options',
205
+ noDataExpression: true,
206
+ displayOptions: {
207
+ show: {
208
+ resource: ['flow'],
209
+ },
210
+ },
211
+ options: [
212
+ {
213
+ name: 'Deploy',
214
+ value: 'deploy',
215
+ description: 'Deploy a flow to make it accessible via API',
216
+ action: 'Deploy a flow',
217
+ },
218
+ {
219
+ name: 'List',
220
+ value: 'list',
221
+ description: 'List all flows in your project',
222
+ action: 'List all flows',
223
+ },
224
+ {
225
+ name: 'Run',
226
+ value: 'run',
227
+ description: 'Execute a deployed flow with a query',
228
+ action: 'Run a flow',
229
+ },
230
+ ],
231
+ default: 'run',
232
+ },
233
+ // Flow - Run fields
234
+ {
235
+ displayName: 'Flow Name',
236
+ name: 'flowName',
237
+ type: 'string',
238
+ required: true,
239
+ default: '',
240
+ displayOptions: {
241
+ show: {
242
+ resource: ['flow'],
243
+ operation: ['run', 'deploy'],
244
+ },
245
+ },
246
+ description: 'The name of the flow to execute',
247
+ },
248
+ {
249
+ displayName: 'Query',
250
+ name: 'query',
251
+ type: 'string',
252
+ default: '',
253
+ displayOptions: {
254
+ show: {
255
+ resource: ['flow'],
256
+ operation: ['run'],
257
+ },
258
+ },
259
+ description: 'The query or question to process through the flow',
260
+ },
261
+ {
262
+ displayName: 'Additional Fields',
263
+ name: 'additionalFieldsFlow',
264
+ type: 'collection',
265
+ placeholder: 'Add Field',
266
+ default: {},
267
+ displayOptions: {
268
+ show: {
269
+ resource: ['flow'],
270
+ operation: ['run'],
271
+ },
272
+ },
273
+ options: [
274
+ {
275
+ displayName: 'Page',
276
+ name: 'page',
277
+ type: 'number',
278
+ default: 1,
279
+ description: 'Page number for paginated results',
280
+ },
281
+ {
282
+ displayName: 'Page Size',
283
+ name: 'pageSize',
284
+ type: 'number',
285
+ default: 10,
286
+ description: 'Number of items per page',
287
+ },
288
+ ],
289
+ },
290
+ // Flow - Deploy fields
291
+ {
292
+ displayName: 'Tool Description',
293
+ name: 'toolDescription',
294
+ type: 'string',
295
+ default: '',
296
+ displayOptions: {
297
+ show: {
298
+ resource: ['flow'],
299
+ operation: ['deploy'],
300
+ },
301
+ },
302
+ description: 'Custom description for the deployed flow (used in tool definitions)',
303
+ },
304
+ // ==================== SOURCE OPERATIONS ====================
305
+ {
306
+ displayName: 'Operation',
307
+ name: 'operation',
308
+ type: 'options',
309
+ noDataExpression: true,
310
+ displayOptions: {
311
+ show: {
312
+ resource: ['source'],
313
+ },
314
+ },
315
+ options: [
316
+ {
317
+ name: 'Delete',
318
+ value: 'delete',
319
+ description: 'Delete a source from your project',
320
+ action: 'Delete a source',
321
+ },
322
+ {
323
+ name: 'Get Elements',
324
+ value: 'getElements',
325
+ description: 'Get structured elements from a processed source',
326
+ action: 'Get source elements',
327
+ },
328
+ {
329
+ name: 'List',
330
+ value: 'list',
331
+ description: 'List all sources in your project',
332
+ action: 'List all sources',
333
+ },
334
+ {
335
+ name: 'Process',
336
+ value: 'process',
337
+ description: 'Process a source with OCR/parsing',
338
+ action: 'Process a source',
339
+ },
340
+ {
341
+ name: 'Upload File',
342
+ value: 'uploadFile',
343
+ description: 'Upload a file to your project',
344
+ action: 'Upload a file',
345
+ },
346
+ {
347
+ name: 'Upload From GitHub',
348
+ value: 'uploadGithub',
349
+ description: 'Upload content from a GitHub repository',
350
+ action: 'Upload from Git Hub',
351
+ },
352
+ {
353
+ name: 'Upload From URL',
354
+ value: 'uploadUrl',
355
+ description: 'Upload content from a web page URL',
356
+ action: 'Upload from URL',
357
+ },
358
+ {
359
+ name: 'Upload From YouTube',
360
+ value: 'uploadYoutube',
361
+ description: 'Upload content from a YouTube video',
362
+ action: 'Upload from You Tube',
363
+ },
364
+ ],
365
+ default: 'list',
366
+ },
367
+ // Source - Upload File fields
368
+ {
369
+ displayName: 'Input Data Field Name',
370
+ name: 'binaryPropertyName',
371
+ type: 'string',
372
+ default: 'data',
373
+ required: true,
374
+ displayOptions: {
375
+ show: {
376
+ resource: ['source'],
377
+ operation: ['uploadFile'],
378
+ },
379
+ },
380
+ description: 'The name of the input field containing the binary file data',
381
+ },
382
+ // Source - Upload URL fields
383
+ {
384
+ displayName: 'URL',
385
+ name: 'url',
386
+ type: 'string',
387
+ required: true,
388
+ default: '',
389
+ displayOptions: {
390
+ show: {
391
+ resource: ['source'],
392
+ operation: ['uploadUrl'],
393
+ },
394
+ },
395
+ description: 'The public web page URL to scrape and ingest',
396
+ },
397
+ // Source - Upload GitHub fields
398
+ {
399
+ displayName: 'Repository URL',
400
+ name: 'githubUrl',
401
+ type: 'string',
402
+ required: true,
403
+ default: '',
404
+ displayOptions: {
405
+ show: {
406
+ resource: ['source'],
407
+ operation: ['uploadGithub'],
408
+ },
409
+ },
410
+ description: 'The public GitHub repository URL',
411
+ },
412
+ // Source - Upload YouTube fields
413
+ {
414
+ displayName: 'YouTube URL',
415
+ name: 'youtubeUrl',
416
+ type: 'string',
417
+ required: true,
418
+ default: '',
419
+ displayOptions: {
420
+ show: {
421
+ resource: ['source'],
422
+ operation: ['uploadYoutube'],
423
+ },
424
+ },
425
+ description: 'The public YouTube video URL',
426
+ },
427
+ // Source - Process fields
428
+ {
429
+ displayName: 'File Name',
430
+ name: 'fileName',
431
+ type: 'string',
432
+ required: true,
433
+ default: '',
434
+ displayOptions: {
435
+ show: {
436
+ resource: ['source'],
437
+ operation: ['process', 'delete', 'getElements'],
438
+ },
439
+ },
440
+ description: 'The name of the file to process/delete/get elements from',
441
+ },
442
+ {
443
+ displayName: 'Partition Method',
444
+ name: 'partitionMethod',
445
+ type: 'options',
446
+ default: 'basic',
447
+ displayOptions: {
448
+ show: {
449
+ resource: ['source'],
450
+ operation: ['process'],
451
+ },
452
+ },
453
+ options: [
454
+ {
455
+ name: 'Basic',
456
+ value: 'basic',
457
+ description: 'Fast processing with heuristic classification',
458
+ },
459
+ {
460
+ name: 'Hi-Res',
461
+ value: 'hi_res',
462
+ description: 'High resolution processing with advanced layout detection',
463
+ },
464
+ {
465
+ name: 'Hi-Res FT',
466
+ value: 'hi_res_ft',
467
+ description: 'Fine-tuned high resolution processing',
468
+ },
469
+ {
470
+ name: 'MAI',
471
+ value: 'mai',
472
+ description: 'Multi-modal AI processing',
473
+ },
474
+ {
475
+ name: 'GraphorLM',
476
+ value: 'graphorlm',
477
+ description: 'Graphor proprietary processing method',
478
+ },
479
+ ],
480
+ description: 'The processing method to use for document parsing',
481
+ },
482
+ ],
483
+ };
484
+ }
485
+ async execute() {
486
+ const items = this.getInputData();
487
+ const returnData = [];
488
+ const resource = this.getNodeParameter('resource', 0);
489
+ const operation = this.getNodeParameter('operation', 0);
490
+ for (let i = 0; i < items.length; i++) {
491
+ try {
492
+ let responseData;
493
+ // ==================== CHAT ====================
494
+ if (resource === 'chat') {
495
+ if (operation === 'askQuestion') {
496
+ const question = this.getNodeParameter('question', i);
497
+ const additionalFields = this.getNodeParameter('additionalFields', i);
498
+ const body = {
499
+ question,
500
+ };
501
+ if (additionalFields.conversationId) {
502
+ body.conversation_id = additionalFields.conversationId;
503
+ }
504
+ if (additionalFields.fileNames) {
505
+ body.file_names = additionalFields.fileNames.split(',').map((f) => f.trim());
506
+ }
507
+ if (additionalFields.reset !== undefined) {
508
+ body.reset = additionalFields.reset;
509
+ }
510
+ if (additionalFields.outputSchema) {
511
+ body.output_schema = JSON.parse(additionalFields.outputSchema);
512
+ }
513
+ const options = {
514
+ method: 'POST',
515
+ uri: 'https://sources.graphorlm.com/ask-sources',
516
+ body,
517
+ json: true,
518
+ };
519
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
520
+ }
521
+ }
522
+ // ==================== EXTRACTION ====================
523
+ if (resource === 'extraction') {
524
+ if (operation === 'extractData') {
525
+ const fileNames = this.getNodeParameter('fileNames', i);
526
+ const userInstruction = this.getNodeParameter('userInstruction', i);
527
+ const outputSchema = this.getNodeParameter('outputSchema', i);
528
+ const body = {
529
+ file_names: fileNames.split(',').map((f) => f.trim()),
530
+ user_instruction: userInstruction,
531
+ output_schema: JSON.parse(outputSchema),
532
+ };
533
+ const options = {
534
+ method: 'POST',
535
+ uri: 'https://sources.graphorlm.com/run-extraction',
536
+ body,
537
+ json: true,
538
+ };
539
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
540
+ }
541
+ }
542
+ // ==================== FLOW ====================
543
+ if (resource === 'flow') {
544
+ if (operation === 'list') {
545
+ const options = {
546
+ method: 'GET',
547
+ uri: 'https://flows.graphorlm.com',
548
+ json: true,
549
+ };
550
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
551
+ }
552
+ if (operation === 'run') {
553
+ const flowName = this.getNodeParameter('flowName', i);
554
+ const query = this.getNodeParameter('query', i);
555
+ const additionalFields = this.getNodeParameter('additionalFieldsFlow', i);
556
+ const body = {};
557
+ if (query) {
558
+ body.query = query;
559
+ }
560
+ if (additionalFields.page) {
561
+ body.page = additionalFields.page;
562
+ }
563
+ if (additionalFields.pageSize) {
564
+ body.page_size = additionalFields.pageSize;
565
+ }
566
+ const options = {
567
+ method: 'POST',
568
+ uri: `https://${flowName}.flows.graphorlm.com`,
569
+ body,
570
+ json: true,
571
+ };
572
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
573
+ }
574
+ if (operation === 'deploy') {
575
+ const flowName = this.getNodeParameter('flowName', i);
576
+ const toolDescription = this.getNodeParameter('toolDescription', i);
577
+ const body = {};
578
+ if (toolDescription) {
579
+ body.tool_description = toolDescription;
580
+ }
581
+ const options = {
582
+ method: 'POST',
583
+ uri: `https://${flowName}.flows.graphorlm.com/deploy`,
584
+ body,
585
+ json: true,
586
+ };
587
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
588
+ }
589
+ }
590
+ // ==================== SOURCE ====================
591
+ if (resource === 'source') {
592
+ if (operation === 'list') {
593
+ const options = {
594
+ method: 'GET',
595
+ uri: 'https://sources.graphorlm.com',
596
+ json: true,
597
+ };
598
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
599
+ }
600
+ if (operation === 'uploadFile') {
601
+ const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
602
+ const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
603
+ let uploadData;
604
+ if (binaryData.id) {
605
+ uploadData = await this.helpers.binaryToBuffer(await this.helpers.getBinaryStream(binaryData.id));
606
+ }
607
+ else {
608
+ uploadData = Buffer.from(binaryData.data, 'base64');
609
+ }
610
+ const options = {
611
+ method: 'POST',
612
+ uri: 'https://sources.graphorlm.com/upload',
613
+ formData: {
614
+ file: {
615
+ value: uploadData,
616
+ options: {
617
+ filename: binaryData.fileName || 'file',
618
+ contentType: binaryData.mimeType,
619
+ },
620
+ },
621
+ },
622
+ json: true,
623
+ };
624
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
625
+ }
626
+ if (operation === 'uploadUrl') {
627
+ const url = this.getNodeParameter('url', i);
628
+ const options = {
629
+ method: 'POST',
630
+ uri: 'https://sources.graphorlm.com/upload-url-source',
631
+ body: { url },
632
+ json: true,
633
+ };
634
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
635
+ }
636
+ if (operation === 'uploadGithub') {
637
+ const githubUrl = this.getNodeParameter('githubUrl', i);
638
+ const options = {
639
+ method: 'POST',
640
+ uri: 'https://sources.graphorlm.com/upload-github-source',
641
+ body: { url: githubUrl },
642
+ json: true,
643
+ };
644
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
645
+ }
646
+ if (operation === 'uploadYoutube') {
647
+ const youtubeUrl = this.getNodeParameter('youtubeUrl', i);
648
+ const options = {
649
+ method: 'POST',
650
+ uri: 'https://sources.graphorlm.com/upload-youtube-source',
651
+ body: { url: youtubeUrl },
652
+ json: true,
653
+ };
654
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
655
+ }
656
+ if (operation === 'process') {
657
+ const fileName = this.getNodeParameter('fileName', i);
658
+ const partitionMethod = this.getNodeParameter('partitionMethod', i);
659
+ const options = {
660
+ method: 'POST',
661
+ uri: 'https://sources.graphorlm.com/process',
662
+ body: {
663
+ file_name: fileName,
664
+ partition_method: partitionMethod,
665
+ },
666
+ json: true,
667
+ };
668
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
669
+ }
670
+ if (operation === 'getElements') {
671
+ const fileName = this.getNodeParameter('fileName', i);
672
+ const options = {
673
+ method: 'POST',
674
+ uri: 'https://sources.graphorlm.com/elements',
675
+ body: {
676
+ file_name: fileName,
677
+ },
678
+ json: true,
679
+ };
680
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
681
+ }
682
+ if (operation === 'delete') {
683
+ const fileName = this.getNodeParameter('fileName', i);
684
+ const options = {
685
+ method: 'DELETE',
686
+ uri: 'https://sources.graphorlm.com/delete',
687
+ body: {
688
+ file_name: fileName,
689
+ },
690
+ json: true,
691
+ };
692
+ responseData = await this.helpers.requestWithAuthentication.call(this, 'graphorApi', options);
693
+ }
694
+ }
695
+ const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
696
+ returnData.push(...executionData);
697
+ }
698
+ catch (error) {
699
+ if (this.continueOnFail()) {
700
+ const executionErrorData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } });
701
+ returnData.push(...executionErrorData);
702
+ continue;
703
+ }
704
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, {
705
+ itemIndex: i,
706
+ });
707
+ }
708
+ }
709
+ return [returnData];
710
+ }
711
+ }
712
+ exports.Graphor = Graphor;
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" fill="none">
2
+ <rect width="60" height="60" rx="12" fill="#C75B93"/>
3
+ <path d="M30 12c-7.732 0-14 6.268-14 14 0 7.732 6.268 14 14 14 3.866 0 7.366-1.567 9.899-4.101V40c0 4.418-3.582 8-8 8-2.761 0-5.291-1.118-7.121-2.929l-2.828 2.828C24.464 50.414 28.052 52 32 52c6.627 0 12-5.373 12-12V26c0-7.732-6.268-14-14-14zm0 24c-5.523 0-10-4.477-10-10s4.477-10 10-10 10 4.477 10 10-4.477 10-10 10z" fill="white"/>
4
+ </svg>
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "n8n-nodes-graphorlm",
3
+ "version": "0.1.0",
4
+ "description": "n8n community nodes for Graphor - Intelligent document processing, RAG pipelines, and document chat API",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "graphor",
8
+ "rag",
9
+ "document-processing",
10
+ "ai",
11
+ "llm",
12
+ "ocr",
13
+ "document-chat",
14
+ "extraction"
15
+ ],
16
+ "license": "MIT",
17
+ "homepage": "https://graphorlm.com",
18
+ "author": {
19
+ "name": "Graphor",
20
+ "email": "support@graphorlm.com"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/graphor/n8n-nodes-graphor.git"
25
+ },
26
+ "scripts": {
27
+ "build": "tsc && gulp build:icons",
28
+ "dev": "tsc --watch",
29
+ "format": "prettier nodes credentials --write",
30
+ "lint": "eslint 'nodes/**/*.ts' 'credentials/**/*.ts'",
31
+ "lintfix": "eslint 'nodes/**/*.ts' 'credentials/**/*.ts' --fix",
32
+ "prepublishOnly": "npm run build"
33
+ },
34
+ "files": [
35
+ "dist"
36
+ ],
37
+ "n8n": {
38
+ "n8nNodesApiVersion": 1,
39
+ "credentials": [
40
+ "dist/credentials/GraphorApi.credentials.js"
41
+ ],
42
+ "nodes": [
43
+ "dist/nodes/Graphor/Graphor.node.js"
44
+ ]
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^20.10.0",
48
+ "@typescript-eslint/parser": "^7.0.0",
49
+ "eslint": "^8.56.0",
50
+ "eslint-plugin-n8n-nodes-base": "^1.16.0",
51
+ "gulp": "^4.0.2",
52
+ "n8n-workflow": "^1.22.0",
53
+ "prettier": "^3.2.0",
54
+ "typescript": "^5.3.0"
55
+ },
56
+ "peerDependencies": {
57
+ "n8n-workflow": "*"
58
+ },
59
+ "engines": {
60
+ "node": ">=18.0.0"
61
+ }
62
+ }