n8n-nodes-cala 0.3.3 → 0.4.1

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
@@ -26,13 +26,22 @@ You need a Cala API key to use this node:
26
26
  3. In n8n, create new credentials of type **Cala API**
27
27
  4. Enter your API key
28
28
 
29
- ## Endpoint
29
+ ## Operations
30
30
 
31
- The node provides access to the **Knowledge Search** endpoint, which searches trusted knowledge using natural language queries.
31
+ The node exposes a **Knowledge** resource with four operations:
32
32
 
33
- ### Example
33
+ | Operation | Description |
34
+ |-----------|-------------|
35
+ | **Search** | Answer natural language questions with sourced, researched content |
36
+ | **Query** | Filter entities by attributes using structured dot-notation syntax |
37
+ | **Search Entities** | Find entities by name with fuzzy matching |
38
+ | **Get Entity** | Get the full profile of an entity by its numeric ID |
34
39
 
35
- **Input:** "How many students were enrolled at MIT in 2024?"
40
+ ### Search
41
+
42
+ Ask a natural language question and get back a researched answer with sources.
43
+
44
+ **Input:** `"How many students were enrolled at MIT in 2024?"`
36
45
 
37
46
  **Output:**
38
47
  ```json
@@ -47,7 +56,7 @@ The node provides access to the **Knowledge Search** endpoint, which searches tr
47
56
  "context": [
48
57
  {
49
58
  "id": "a1b2c3d4-5678-90ab-cdef-123456789abc",
50
- "content": "In 2024, the Massachusetts Institute of Technology enrolled approximately 11,800 students: 4,600 undergraduates and 7,200 graduate students.",
59
+ "content": "In 2024, the Massachusetts Institute of Technology enrolled approximately 11,800 students.",
51
60
  "origins": [
52
61
  {
53
62
  "source": { "name": "MIT", "url": "https://mit.edu" },
@@ -57,12 +66,27 @@ The node provides access to the **Knowledge Search** endpoint, which searches tr
57
66
  }
58
67
  ],
59
68
  "entities": [
60
- { "id": 1, "name": "MIT", "entity_type": "ORGANIZATION" },
61
- { "id": 2, "name": "Massachusetts Institute of Technology", "entity_type": "ORGANIZATION" }
69
+ { "id": 1, "name": "MIT", "entity_type": "ORGANIZATION" }
62
70
  ]
63
71
  }
64
72
  ```
65
73
 
74
+ ### Query
75
+
76
+ Filter entities by attributes using dot-notation syntax.
77
+
78
+ **Input:** `"startups.location=Spain.funding>10M.funding<=50M"`
79
+
80
+ ### Search Entities
81
+
82
+ Find entities by name (supports fuzzy matching). Returns a list of matches with IDs.
83
+
84
+ **Input:** `"OpenAI"` → returns entity IDs you can pass to **Get Entity**.
85
+
86
+ ### Get Entity
87
+
88
+ Get the full profile of an entity by its numeric ID (from Search or Search Entities results).
89
+
66
90
  ## Resources
67
91
 
68
92
  - [Cala Documentation](https://docs.cala.ai)
@@ -1,9 +1,8 @@
1
- import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
1
+ import { ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
2
  export declare class CalaApi implements ICredentialType {
3
3
  name: string;
4
4
  displayName: string;
5
5
  documentationUrl: string;
6
6
  properties: INodeProperties[];
7
- authenticate: IAuthenticateGeneric;
8
7
  test: ICredentialTestRequest;
9
8
  }
@@ -19,19 +19,14 @@ class CalaApi {
19
19
  description: 'Your Cala API key',
20
20
  },
21
21
  ];
22
- this.authenticate = {
23
- type: 'generic',
24
- properties: {
25
- headers: {
26
- 'X-API-KEY': '={{$credentials.apiKey}}',
27
- },
28
- },
29
- };
30
22
  this.test = {
31
23
  request: {
32
24
  baseURL: 'https://api.cala.ai',
33
25
  url: '/v1/knowledge/search',
34
26
  method: 'POST',
27
+ headers: {
28
+ 'X-API-KEY': '={{$credentials.apiKey}}',
29
+ },
35
30
  body: {
36
31
  input: 'test',
37
32
  },
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Cala = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const BASE_URL = 'https://api.cala.ai';
4
6
  class Cala {
5
7
  constructor() {
6
8
  this.description = {
@@ -9,7 +11,7 @@ class Cala {
9
11
  icon: 'file:cala.svg',
10
12
  group: ['transform'],
11
13
  version: 1,
12
- subtitle: 'Knowledge Search',
14
+ subtitle: '={{$parameter["operation"]}}',
13
15
  description: 'Search trusted knowledge with Cala AI',
14
16
  defaults: {
15
17
  name: 'Cala',
@@ -23,14 +25,118 @@ class Cala {
23
25
  },
24
26
  ],
25
27
  properties: [
28
+ // ── Resource ────────────────────────────────────────────────────────
29
+ {
30
+ displayName: 'Resource',
31
+ name: 'resource',
32
+ type: 'options',
33
+ noDataExpression: true,
34
+ options: [
35
+ {
36
+ name: 'Knowledge',
37
+ value: 'knowledge',
38
+ },
39
+ ],
40
+ default: 'knowledge',
41
+ },
42
+ // ── Operations ──────────────────────────────────────────────────────
43
+ {
44
+ displayName: 'Operation',
45
+ name: 'operation',
46
+ type: 'options',
47
+ noDataExpression: true,
48
+ displayOptions: {
49
+ show: { resource: ['knowledge'] },
50
+ },
51
+ options: [
52
+ {
53
+ name: 'Search',
54
+ value: 'search',
55
+ action: 'Search knowledge',
56
+ description: 'Answer natural language questions with sourced, researched content',
57
+ },
58
+ {
59
+ name: 'Query',
60
+ value: 'query',
61
+ action: 'Query knowledge',
62
+ description: 'Filter entities by attributes using structured dot-notation syntax',
63
+ },
64
+ {
65
+ name: 'Search Entities',
66
+ value: 'searchEntities',
67
+ action: 'Search entities',
68
+ description: 'Find entities by name with fuzzy matching',
69
+ },
70
+ {
71
+ name: 'Get Entity',
72
+ value: 'getEntity',
73
+ action: 'Get an entity',
74
+ description: 'Get the full profile of an entity by its numeric ID',
75
+ },
76
+ ],
77
+ default: 'search',
78
+ },
79
+ // ── Knowledge › Search ──────────────────────────────────────────────
26
80
  {
27
81
  displayName: 'Query',
28
82
  name: 'query',
29
83
  type: 'string',
30
84
  required: true,
31
85
  default: '',
32
- placeholder: "i.e. What were Toyota's total sales in 2023?",
33
- description: 'The search query to find knowledge',
86
+ placeholder: "e.g. What were Toyota's total sales in 2023?",
87
+ description: 'Natural language question to search knowledge for',
88
+ displayOptions: {
89
+ show: { resource: ['knowledge'], operation: ['search'] },
90
+ },
91
+ },
92
+ // ── Knowledge › Query ───────────────────────────────────────────────
93
+ {
94
+ displayName: 'Query',
95
+ name: 'query',
96
+ type: 'string',
97
+ required: true,
98
+ default: '',
99
+ placeholder: 'e.g. startups.location=Spain.funding>10M',
100
+ description: 'Structured dot-notation query to filter entities by attributes',
101
+ displayOptions: {
102
+ show: { resource: ['knowledge'], operation: ['query'] },
103
+ },
104
+ },
105
+ // ── Knowledge › Search Entities ─────────────────────────────────────
106
+ {
107
+ displayName: 'Name',
108
+ name: 'name',
109
+ type: 'string',
110
+ required: true,
111
+ default: '',
112
+ placeholder: 'e.g. OpenAI',
113
+ description: 'Entity name to search for (supports fuzzy matching)',
114
+ displayOptions: {
115
+ show: { resource: ['knowledge'], operation: ['searchEntities'] },
116
+ },
117
+ },
118
+ {
119
+ displayName: 'Limit',
120
+ name: 'limit',
121
+ type: 'number',
122
+ default: 20,
123
+ description: 'Maximum number of results to return',
124
+ typeOptions: { minValue: 1, maxValue: 100 },
125
+ displayOptions: {
126
+ show: { resource: ['knowledge'], operation: ['searchEntities'] },
127
+ },
128
+ },
129
+ // ── Knowledge › Get Entity ──────────────────────────────────────────
130
+ {
131
+ displayName: 'Entity ID',
132
+ name: 'entityId',
133
+ type: 'number',
134
+ required: true,
135
+ default: 0,
136
+ description: 'The numeric ID of the entity to retrieve',
137
+ displayOptions: {
138
+ show: { resource: ['knowledge'], operation: ['getEntity'] },
139
+ },
34
140
  },
35
141
  ],
36
142
  };
@@ -40,23 +146,62 @@ class Cala {
40
146
  const returnData = [];
41
147
  const credentials = await this.getCredentials('calaApi');
42
148
  const apiKey = credentials.apiKey;
149
+ const headers = { 'Content-Type': 'application/json' };
150
+ if (apiKey) {
151
+ headers['X-API-KEY'] = apiKey;
152
+ }
153
+ const resource = this.getNodeParameter('resource', 0);
154
+ const operation = this.getNodeParameter('operation', 0);
43
155
  for (let i = 0; i < items.length; i++) {
44
- const query = this.getNodeParameter('query', i);
45
- const headers = {
46
- 'Content-Type': 'application/json',
47
- };
48
- if (apiKey) {
49
- headers['X-API-KEY'] = apiKey;
156
+ let response;
157
+ if (resource === 'knowledge') {
158
+ if (operation === 'search') {
159
+ const query = this.getNodeParameter('query', i);
160
+ response = await this.helpers.httpRequest({
161
+ method: 'POST',
162
+ url: `${BASE_URL}/v1/knowledge/search`,
163
+ headers,
164
+ body: { input: query },
165
+ json: true,
166
+ });
167
+ }
168
+ else if (operation === 'query') {
169
+ const query = this.getNodeParameter('query', i);
170
+ response = await this.helpers.httpRequest({
171
+ method: 'POST',
172
+ url: `${BASE_URL}/v1/knowledge/query`,
173
+ headers,
174
+ body: { input: query },
175
+ json: true,
176
+ });
177
+ }
178
+ else if (operation === 'searchEntities') {
179
+ const name = this.getNodeParameter('name', i);
180
+ const limit = this.getNodeParameter('limit', i);
181
+ response = await this.helpers.httpRequest({
182
+ method: 'GET',
183
+ url: `${BASE_URL}/v1/knowledge/entities`,
184
+ headers,
185
+ qs: { name, limit },
186
+ json: true,
187
+ });
188
+ }
189
+ else if (operation === 'getEntity') {
190
+ const entityId = this.getNodeParameter('entityId', i);
191
+ response = await this.helpers.httpRequest({
192
+ method: 'GET',
193
+ url: `${BASE_URL}/v1/knowledge/entities/${entityId}`,
194
+ headers,
195
+ json: true,
196
+ });
197
+ }
198
+ else {
199
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`);
200
+ }
201
+ }
202
+ else {
203
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown resource: ${resource}`);
50
204
  }
51
- const response = await this.helpers.httpRequest({
52
- method: 'POST',
53
- url: 'https://api.cala.ai/v1/knowledge/search',
54
- headers,
55
- body: {
56
- input: query,
57
- },
58
- json: true,
59
- });
60
205
  returnData.push({
61
206
  json: response,
62
207
  pairedItem: { item: i },
@@ -0,0 +1,16 @@
1
+ {
2
+ "node": "n8n-nodes-cala.cala",
3
+ "nodeVersion": "1.0",
4
+ "codexVersion": "1.0",
5
+ "categories": ["AI", "Data & Storage"],
6
+ "subcategories": {
7
+ "AI": ["Tools"]
8
+ },
9
+ "resources": {
10
+ "primaryDocumentation": [
11
+ {
12
+ "url": "https://docs.cala.ai"
13
+ }
14
+ ]
15
+ }
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-cala",
3
- "version": "0.3.3",
3
+ "version": "0.4.1",
4
4
  "description": "n8n nodes for Cala AI knowledge search",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
@@ -49,10 +49,10 @@
49
49
  "typescript-eslint": "^8.53.1"
50
50
  },
51
51
  "peerDependencies": {
52
- "n8n-workflow": "*"
52
+ "n8n-workflow": ">=1.0.0"
53
53
  },
54
54
  "engines": {
55
- "node": ">=22",
55
+ "node": ">=18",
56
56
  "pnpm": ">=10"
57
57
  },
58
58
  "volta": {