@ctera/n8n-nodes-ctera-ai 0.1.2 → 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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # n8n-nodes-ctera-ai
2
2
 
3
- n8n community node for CTERA AI MCP integration - enables semantic search, chat, and expert discovery.
3
+ n8n community node for CTERA AI MCP integration - enables semantic search, file search, chat, and expert discovery.
4
4
 
5
5
  [n8n](https://n8n.io/) is a workflow automation platform.
6
6
 
@@ -16,9 +16,62 @@ Then restart n8n. The **CTERA Data Intelligence** node will appear in your node
16
16
  ## Operations
17
17
 
18
18
  - **List Experts** - Get all available AI experts (knowledge bases)
19
- - **Semantic Search** - Search within an expert's knowledge base
19
+ - **Semantic Search** - Search within an expert's knowledge base (returns text chunks for RAG)
20
+ - **File Search** - Search files and return metadata with optional snippets (returns file-level results)
20
21
  - **Chat** - Have a conversation with an AI expert
21
22
 
23
+ ## File Search Operation
24
+
25
+ The File Search operation searches files within an expert's knowledge base and returns file-level metadata with optional content snippets.
26
+
27
+ ### Parameters
28
+
29
+ | Parameter | Type | Default | Description |
30
+ |-----------|------|---------|-------------|
31
+ | Query | string | required | Search expression with free-text and optional `key:value` filters |
32
+ | Limit | number | 100 | Maximum number of results (max: 250) |
33
+ | Offset | number | 0 | Pagination offset |
34
+ | Sort By | select | relevance | Sort order: `relevance`, `modified_at`, `created_at`, `name` |
35
+ | Include Snippet | boolean | false | Include text snippet per file |
36
+ | Include Markdown | boolean | false | Include full markdown body per file |
37
+
38
+ ### Search Expression Syntax
39
+
40
+ The query parameter supports free-text search combined with metadata filters:
41
+
42
+ ```
43
+ # Free-text search
44
+ API documentation
45
+
46
+ # Free-text with classifier filters
47
+ API documentation department:Engineering
48
+
49
+ # Multiple filters
50
+ security policy department:Legal urgency:high
51
+ ```
52
+
53
+ ### Output
54
+
55
+ Each file hit becomes a separate n8n item with the following fields:
56
+
57
+ | Field | Type | Description |
58
+ |-------|------|-------------|
59
+ | fileId | string | Document UUID |
60
+ | name | string | File name |
61
+ | path | string | File path |
62
+ | sizeBytes | number | File size in bytes |
63
+ | mimeType | string | MIME content type |
64
+ | createdAt | string | ISO timestamp of creation |
65
+ | modifiedAt | string | ISO timestamp of last modification |
66
+ | storageSystem | string | Storage system identifier |
67
+ | bucketOrShare | string | Bucket or share name |
68
+ | score | number | Relevance score (0-1) |
69
+ | standardMetadata | object | Standard file metadata (guid, dataset_id, permissions) |
70
+ | customMetadata | object | Custom metadata (classifier_tags, classifications) |
71
+ | snippet | string | Text snippet (when include_snippet=true) |
72
+ | markdownBody | string | Full markdown content (when include_markdown=true) |
73
+ | _meta | object | Pagination info (total, limit, offset) |
74
+
22
75
  ## Credentials
23
76
 
24
77
  **1. Log into Admin UI** with your SSO credentials
@@ -45,6 +98,8 @@ curl -k -X POST "https://YOUR_ADMIN_URL/admin/api/mcp-tokens/generate" \
45
98
  - **Daily Intelligence Reports** - Schedule searches across experts for recent updates
46
99
  - **Q&A Chatbots** - Build webhook-based chatbots using the Chat operation
47
100
  - **Document Discovery** - Monitor for new content and send notifications
101
+ - **File Metadata Analysis** - Use File Search to find files by metadata filters and process each result
102
+ - **Compliance Scanning** - Search for files matching specific classifier tags
48
103
 
49
104
  ## Resources
50
105
 
@@ -53,6 +53,11 @@ class CteraAi {
53
53
  value: 'search',
54
54
  description: 'Retrieve raw text chunks for Retrieval-Augmented Generation',
55
55
  },
56
+ {
57
+ name: 'File Search (Files & Metadata)',
58
+ value: 'fileSearch',
59
+ description: 'Search files and return metadata with optional snippets',
60
+ },
56
61
  {
57
62
  name: 'Chat (Generative Answer)',
58
63
  value: 'chat',
@@ -130,6 +135,80 @@ class CteraAi {
130
135
  },
131
136
  ],
132
137
  },
138
+ {
139
+ displayName: 'File Search Options',
140
+ name: 'fileSearchOptions',
141
+ type: 'collection',
142
+ placeholder: 'Add Option',
143
+ default: {},
144
+ displayOptions: {
145
+ show: {
146
+ operation: ['fileSearch'],
147
+ },
148
+ },
149
+ options: [
150
+ {
151
+ displayName: 'Limit',
152
+ name: 'limit',
153
+ type: 'number',
154
+ default: 100,
155
+ description: 'Maximum number of results to return',
156
+ typeOptions: {
157
+ minValue: 1,
158
+ maxValue: 250,
159
+ },
160
+ },
161
+ {
162
+ displayName: 'Offset',
163
+ name: 'offset',
164
+ type: 'number',
165
+ default: 0,
166
+ description: 'Pagination offset',
167
+ typeOptions: {
168
+ minValue: 0,
169
+ },
170
+ },
171
+ {
172
+ displayName: 'Sort By',
173
+ name: 'sort_by',
174
+ type: 'options',
175
+ options: [
176
+ {
177
+ name: 'Relevance',
178
+ value: 'relevance',
179
+ },
180
+ {
181
+ name: 'Modified Date',
182
+ value: 'modified_at',
183
+ },
184
+ {
185
+ name: 'Created Date',
186
+ value: 'created_at',
187
+ },
188
+ {
189
+ name: 'Name',
190
+ value: 'name',
191
+ },
192
+ ],
193
+ default: 'relevance',
194
+ description: 'Sort order for results',
195
+ },
196
+ {
197
+ displayName: 'Include Snippet',
198
+ name: 'include_snippet',
199
+ type: 'boolean',
200
+ default: false,
201
+ description: 'Whether to return text snippet per file',
202
+ },
203
+ {
204
+ displayName: 'Include Markdown',
205
+ name: 'include_markdown',
206
+ type: 'boolean',
207
+ default: false,
208
+ description: 'Whether to return full markdown body per file',
209
+ },
210
+ ],
211
+ },
133
212
  ],
134
213
  };
135
214
  }
@@ -170,6 +249,28 @@ class CteraAi {
170
249
  params.window_size = additionalOptions.window_size;
171
250
  }
172
251
  }
252
+ else if (operation === 'fileSearch') {
253
+ toolName = 'expert_file_search';
254
+ serverUrl = this.getNodeParameter('expertEndpointUrl', i);
255
+ const query = this.getNodeParameter('query', i);
256
+ const fileSearchOptions = this.getNodeParameter('fileSearchOptions', i, {});
257
+ params.query = query;
258
+ if (fileSearchOptions.limit !== undefined) {
259
+ params.limit = fileSearchOptions.limit;
260
+ }
261
+ if (fileSearchOptions.offset !== undefined) {
262
+ params.offset = fileSearchOptions.offset;
263
+ }
264
+ if (fileSearchOptions.sort_by) {
265
+ params.sort_by = fileSearchOptions.sort_by;
266
+ }
267
+ if (fileSearchOptions.include_snippet !== undefined) {
268
+ params.include_snippet = fileSearchOptions.include_snippet;
269
+ }
270
+ if (fileSearchOptions.include_markdown !== undefined) {
271
+ params.include_markdown = fileSearchOptions.include_markdown;
272
+ }
273
+ }
173
274
  else if (operation === 'chat') {
174
275
  toolName = 'expert_chat';
175
276
  serverUrl = this.getNodeParameter('expertEndpointUrl', i);
@@ -230,15 +331,69 @@ class CteraAi {
230
331
  else {
231
332
  result = parsedResponse.result;
232
333
  }
233
- returnData.push({
234
- json: {
235
- ...items[i].json,
236
- operation,
237
- toolName,
238
- result,
239
- },
240
- pairedItem: { item: i },
241
- });
334
+ // Handle fileSearch with fan-out pattern - each hit becomes a separate item
335
+ if (operation === 'fileSearch' && result && result.hits && Array.isArray(result.hits)) {
336
+ // Map snake_case to camelCase for n8n conventions
337
+ for (const hit of result.hits) {
338
+ returnData.push({
339
+ json: {
340
+ ...items[i].json,
341
+ operation,
342
+ toolName,
343
+ // Map to camelCase field names
344
+ fileId: hit.id,
345
+ name: hit.name,
346
+ path: hit.path,
347
+ sizeBytes: hit.size_bytes,
348
+ mimeType: hit.mime_type,
349
+ createdAt: hit.created_at,
350
+ modifiedAt: hit.modified_at,
351
+ storageSystem: hit.storage_system,
352
+ bucketOrShare: hit.bucket_or_share,
353
+ score: hit.score,
354
+ standardMetadata: hit.standard_metadata,
355
+ customMetadata: hit.custom_metadata,
356
+ snippet: hit.snippet,
357
+ markdownBody: hit.markdown_body,
358
+ // Include pagination info from response
359
+ _meta: {
360
+ total: result.total,
361
+ limit: result.limit,
362
+ offset: result.offset,
363
+ },
364
+ },
365
+ pairedItem: { item: i },
366
+ });
367
+ }
368
+ // If no hits, still return an item indicating empty results
369
+ if (result.hits.length === 0) {
370
+ returnData.push({
371
+ json: {
372
+ ...items[i].json,
373
+ operation,
374
+ toolName,
375
+ result: [],
376
+ _meta: {
377
+ total: result.total || 0,
378
+ limit: result.limit || 0,
379
+ offset: result.offset || 0,
380
+ },
381
+ },
382
+ pairedItem: { item: i },
383
+ });
384
+ }
385
+ }
386
+ else {
387
+ returnData.push({
388
+ json: {
389
+ ...items[i].json,
390
+ operation,
391
+ toolName,
392
+ result,
393
+ },
394
+ pairedItem: { item: i },
395
+ });
396
+ }
242
397
  }
243
398
  catch (error) {
244
399
  if (this.continueOnFail()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctera/n8n-nodes-ctera-ai",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "n8n community node for CTERA AI MCP integration - enables semantic search, chat, and expert discovery",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",