n8n-nodes-cala 0.4.15 → 0.4.16

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
@@ -28,14 +28,15 @@ You need a Cala API key to use this node:
28
28
 
29
29
  ## Operations
30
30
 
31
- The node exposes a **Knowledge** resource with four operations:
31
+ The node exposes a **Knowledge** resource with five operations:
32
32
 
33
33
  | Operation | Description |
34
34
  |-----------|-------------|
35
35
  | **Search** | Answer natural language questions with sourced, researched content |
36
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 |
37
+ | **Search Entities** | Find entities by name with fuzzy matching, optionally filtered by type |
38
+ | **Get Entity** | Get the full profile of an entity by its UUID, with optional field selection |
39
+ | **Get Entity Fields** | Discover which properties, relationships, and observations are available for an entity |
39
40
 
40
41
  ### Search
41
42
 
@@ -106,6 +107,11 @@ Filter entities by attributes using dot-notation syntax.
106
107
 
107
108
  Find entities by name (supports fuzzy matching). Returns a list of matches with IDs.
108
109
 
110
+ **Parameters:**
111
+ - `Name` (required) — entity name to search for
112
+ - `Entity Types` (optional) — filter by one or more types: Company, Person, GPE, Country, Organization, and more
113
+ - `Limit` (optional, default 20) — max results, up to 100
114
+
109
115
  **Input:** `"OpenAI"` with limit `3`
110
116
 
111
117
  **Output:**
@@ -119,27 +125,55 @@ Find entities by name (supports fuzzy matching). Returns a list of matches with
119
125
  }
120
126
  ```
121
127
 
128
+ ### Get Entity Fields
129
+
130
+ Discover which properties, relationships, and numerical observations are available for a specific entity before querying it. Run this first, then use the results to fill in the **Get Entity** optional fields.
131
+
132
+ **Input:** Entity UUID `"c6772802-bdbc-4778-91e9-cd3d27d008d5"`
133
+
134
+ **Output:**
135
+ ```json
136
+ {
137
+ "properties": ["name", "aliases", "legal_name", "employee_count", "founding_date", "headquarters_address"],
138
+ "relationships": {
139
+ "outgoing": ["IS_REGISTERED_IN", "HAS_HEADQUARTERS_IN", "OPERATES_IN_INDUSTRY"],
140
+ "incoming": ["IS_CEO_OF", "IS_CFO_OF", "IS_BOARD_MEMBER_OF", "IS_SUBSIDIARY_OF"]
141
+ },
142
+ "numerical_observations": {
143
+ "FinancialMetric": [
144
+ { "id": "1d3eae40-0ba8-5baf-9907-6a4823b067bb", "name": "Cash and Cash Equivalents", "unit": "USD" }
145
+ ]
146
+ }
147
+ }
148
+ ```
149
+
122
150
  ### Get Entity
123
151
 
124
- Get the full profile of an entity by its ID (from Search or Search Entities results).
152
+ Get the full profile of an entity by its UUID. By default returns a standard set of properties. Use the optional **Additional Fields** to select exactly which properties, relationships, and numerical observations to include — run **Get Entity Fields** first to discover what's available.
125
153
 
126
- **Input:** `"932ba22a-5310-4b21-bbb7-6b91741c8bb3"`
154
+ **Parameters:**
155
+ - `Entity ID` (required) — UUID from Search Entities, Search, or Query results
156
+ - `Additional Fields > Properties` — list of property names to return (e.g. `name`, `employee_count`, `founding_date`)
157
+ - `Additional Fields > Relationships` — relationships to include, each with direction (Outgoing/Incoming), type name, and optional limit/offset
158
+ - `Additional Fields > Numerical Observations` — JSON object mapping observation type to UUID array (e.g. `{"FinancialMetric": ["uuid1"]}`)
159
+
160
+ **Input:** Entity UUID `"c6772802-bdbc-4778-91e9-cd3d27d008d5"` with properties `["name", "employee_count"]` and incoming relationship `IS_CEO_OF`
127
161
 
128
162
  **Output:**
129
163
  ```json
130
164
  {
165
+ "id": "c6772802-bdbc-4778-91e9-cd3d27d008d5",
166
+ "name": "Apple Inc",
167
+ "entity_type": "Company",
131
168
  "properties": {
132
- "name": {
133
- "value": "Hydnum Steel",
134
- "sources": [{ "name": "Cala AI", "document": "", "date": "2026-03-05" }]
135
- },
136
- "registered_address": {
137
- "value": "Calle Serrano North 45, Madrid, Spain",
138
- "sources": [{ "name": "CB Insights", "document": "https://www.cbinsights.com/company/hydnum-steel", "date": "2026-03-02" }]
169
+ "name": { "value": "APPLE INC", "sources": [{ "name": "SEC", "date": "2026-02-26" }] },
170
+ "employee_count": { "value": 164000, "sources": [{ "name": "Macrotrends", "date": "2026-03-01" }] }
171
+ },
172
+ "relationships": {
173
+ "incoming": {
174
+ "IS_CEO_OF": [{ "id": "...", "name": "Tim Cook", "entity_type": "Person" }]
139
175
  }
140
176
  },
141
- "id": { "value": "932ba22a-5310-4b21-bbb7-6b91741c8bb3", "sources": [] },
142
- "relationships": { "outgoing": {}, "incoming": {} },
143
177
  "numerical_observations": []
144
178
  }
145
179
  ```
@@ -31,7 +31,7 @@ class CalaApi {
31
31
  this.test = {
32
32
  request: {
33
33
  baseURL: 'https://api.cala.ai',
34
- url: '/v1/knowledge/entities',
34
+ url: '/v1/entities',
35
35
  method: 'GET',
36
36
  qs: {
37
37
  name: 'test',
@@ -54,7 +54,13 @@ class Cala {
54
54
  name: 'Get Entity',
55
55
  value: 'getEntity',
56
56
  action: 'Get knowledge entity',
57
- description: 'Get the full profile of an entity by its numeric ID.',
57
+ description: 'Get the full profile of an entity by its UUID.',
58
+ },
59
+ {
60
+ name: 'Get Entity Fields',
61
+ value: 'getEntityFields',
62
+ action: 'Get knowledge entity fields',
63
+ description: 'Get available properties, relationships, and numerical observations for an entity.',
58
64
  },
59
65
  {
60
66
  name: 'Query',
@@ -116,6 +122,35 @@ class Cala {
116
122
  show: { resource: ['knowledge'], operation: ['searchEntities'] },
117
123
  },
118
124
  },
125
+ {
126
+ displayName: 'Entity Types',
127
+ name: 'entity_types',
128
+ type: 'multiOptions',
129
+ default: [],
130
+ description: 'Filter results by entity type. Leave empty to return all types.',
131
+ options: [
132
+ { name: 'Company', value: 'Company' },
133
+ { name: 'Corporate Event', value: 'CorporateEvent' },
134
+ { name: 'Country', value: 'Country' },
135
+ { name: 'Country Region', value: 'CountryRegion' },
136
+ { name: 'Educational Institution', value: 'EducationalInstitution' },
137
+ { name: 'Entity', value: 'Entity' },
138
+ { name: 'Facility', value: 'Facility' },
139
+ { name: 'Financial Metric', value: 'FinancialMetric' },
140
+ { name: 'GPE', value: 'GPE' },
141
+ { name: 'Industry', value: 'Industry' },
142
+ { name: 'Language', value: 'Language' },
143
+ { name: 'Law', value: 'Law' },
144
+ { name: 'Location', value: 'Location' },
145
+ { name: 'Organization', value: 'Organization' },
146
+ { name: 'Person', value: 'Person' },
147
+ { name: 'Product', value: 'Product' },
148
+ { name: 'Work of Art', value: 'WorkOfArt' },
149
+ ],
150
+ displayOptions: {
151
+ show: { resource: ['knowledge'], operation: ['searchEntities'] },
152
+ },
153
+ },
119
154
  {
120
155
  displayName: 'Limit',
121
156
  name: 'limit',
@@ -127,30 +162,111 @@ class Cala {
127
162
  show: { resource: ['knowledge'], operation: ['searchEntities'] },
128
163
  },
129
164
  },
130
- // ── Knowledge › Get Entity ──────────────────────────────────────────
165
+ // ── Knowledge › Get Entity / Get Entity Fields ──────────────────────
131
166
  {
132
167
  displayName: 'Entity ID',
133
168
  name: 'entityId',
134
- type: 'number',
169
+ type: 'string',
135
170
  required: true,
136
- default: 0,
137
- description: 'Numeric ID of the entity to retrieve.',
171
+ default: '',
172
+ placeholder: 'e.g. c6772802-bdbc-4778-91e9-cd3d27d008d5',
173
+ description: 'UUID of the entity.',
174
+ displayOptions: {
175
+ show: { resource: ['knowledge'], operation: ['getEntity', 'getEntityFields'] },
176
+ },
177
+ },
178
+ {
179
+ displayName: 'Additional Fields',
180
+ name: 'additionalFields',
181
+ type: 'collection',
182
+ placeholder: 'Add Field',
183
+ default: {},
138
184
  displayOptions: {
139
185
  show: { resource: ['knowledge'], operation: ['getEntity'] },
140
186
  },
187
+ options: [
188
+ {
189
+ displayName: 'Properties',
190
+ name: 'properties',
191
+ type: 'string',
192
+ typeOptions: { multipleValues: true },
193
+ default: [],
194
+ placeholder: 'e.g. name',
195
+ description: 'List of property names to return (e.g. name, employee_count, founding_date). Run Get Entity Fields first to discover available properties.',
196
+ },
197
+ {
198
+ displayName: 'Relationships',
199
+ name: 'relationships',
200
+ type: 'fixedCollection',
201
+ typeOptions: { multipleValues: true },
202
+ default: {},
203
+ description: 'Relationships to include in the response. Run Get Entity Fields first to discover available relationship types.',
204
+ options: [
205
+ {
206
+ name: 'items',
207
+ displayName: 'Relationship',
208
+ values: [
209
+ {
210
+ displayName: 'Direction',
211
+ name: 'direction',
212
+ type: 'options',
213
+ default: 'outgoing',
214
+ options: [
215
+ { name: 'Outgoing', value: 'outgoing' },
216
+ { name: 'Incoming', value: 'incoming' },
217
+ ],
218
+ },
219
+ {
220
+ displayName: 'Relationship Type',
221
+ name: 'relationshipType',
222
+ type: 'string',
223
+ default: '',
224
+ placeholder: 'e.g. IS_CEO_OF',
225
+ description: 'Relationship type name as returned by Get Entity Fields.',
226
+ },
227
+ {
228
+ displayName: 'Limit',
229
+ name: 'limit',
230
+ type: 'number',
231
+ default: 10,
232
+ typeOptions: { minValue: 1 },
233
+ description: 'Maximum number of related entities to return.',
234
+ },
235
+ {
236
+ displayName: 'Offset',
237
+ name: 'offset',
238
+ type: 'number',
239
+ default: 0,
240
+ typeOptions: { minValue: 0 },
241
+ description: 'Number of related entities to skip (for pagination).',
242
+ },
243
+ ],
244
+ },
245
+ ],
246
+ },
247
+ {
248
+ displayName: 'Numerical Observations',
249
+ name: 'numericalObservations',
250
+ type: 'string',
251
+ default: '',
252
+ placeholder: '{"FinancialMetric": ["uuid1", "uuid2"]}',
253
+ description: 'JSON object mapping observation type names to arrays of observation UUIDs. Run Get Entity Fields first to discover available types and UUIDs.',
254
+ },
255
+ ],
141
256
  },
142
257
  ],
143
258
  };
144
259
  }
145
260
  async execute() {
261
+ var _a, _b, _c, _d;
146
262
  const items = this.getInputData();
147
263
  const returnData = [];
148
264
  const resource = this.getNodeParameter('resource', 0);
149
- const operation = this.getNodeParameter('operation', 0);
150
265
  for (let i = 0; i < items.length; i++) {
151
266
  try {
152
267
  let response;
153
268
  if (resource === 'knowledge') {
269
+ const operation = this.getNodeParameter('operation', i);
154
270
  if (operation === 'search') {
155
271
  const query = this.getNodeParameter('query', i);
156
272
  response = await this.helpers.httpRequestWithAuthentication.call(this, 'calaApi', {
@@ -172,18 +288,66 @@ class Cala {
172
288
  else if (operation === 'searchEntities') {
173
289
  const name = this.getNodeParameter('name', i);
174
290
  const limit = this.getNodeParameter('limit', i);
291
+ const entityTypes = this.getNodeParameter('entity_types', i);
175
292
  response = await this.helpers.httpRequestWithAuthentication.call(this, 'calaApi', {
176
293
  method: 'GET',
177
- url: `${BASE_URL}/v1/knowledge/entities`,
178
- qs: { name, limit },
294
+ url: `${BASE_URL}/v1/entities`,
295
+ qs: {
296
+ name,
297
+ limit,
298
+ ...(entityTypes.length ? { entity_types: entityTypes } : {}),
299
+ },
179
300
  json: true,
180
301
  });
181
302
  }
182
303
  else if (operation === 'getEntity') {
304
+ const entityId = this.getNodeParameter('entityId', i);
305
+ const additionalFields = this.getNodeParameter('additionalFields', i);
306
+ const body = {};
307
+ if ((_a = additionalFields.properties) === null || _a === void 0 ? void 0 : _a.length) {
308
+ body.properties = additionalFields.properties;
309
+ }
310
+ const relationshipItems = (_c = (_b = additionalFields.relationships) === null || _b === void 0 ? void 0 : _b.items) !== null && _c !== void 0 ? _c : [];
311
+ if (relationshipItems.length) {
312
+ const outgoing = {};
313
+ const incoming = {};
314
+ for (const item of relationshipItems) {
315
+ if (!((_d = item.relationshipType) === null || _d === void 0 ? void 0 : _d.trim()))
316
+ continue;
317
+ const rel = {};
318
+ if (item.limit != null)
319
+ rel.limit = item.limit;
320
+ if (item.offset != null)
321
+ rel.offset = item.offset;
322
+ (item.direction === 'outgoing' ? outgoing : incoming)[item.relationshipType] = rel;
323
+ }
324
+ const rel = {};
325
+ if (Object.keys(outgoing).length)
326
+ rel.outgoing = outgoing;
327
+ if (Object.keys(incoming).length)
328
+ rel.incoming = incoming;
329
+ body.relationships = rel;
330
+ }
331
+ if (additionalFields.numericalObservations) {
332
+ try {
333
+ body.numerical_observations = JSON.parse(additionalFields.numericalObservations);
334
+ }
335
+ catch {
336
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Numerical Observations must be a valid JSON object (e.g. {"FinancialMetric": ["uuid1"]})', { itemIndex: i });
337
+ }
338
+ }
339
+ response = await this.helpers.httpRequestWithAuthentication.call(this, 'calaApi', {
340
+ method: 'POST',
341
+ url: `${BASE_URL}/v1/entities/${entityId}`,
342
+ body,
343
+ json: true,
344
+ });
345
+ }
346
+ else if (operation === 'getEntityFields') {
183
347
  const entityId = this.getNodeParameter('entityId', i);
184
348
  response = await this.helpers.httpRequestWithAuthentication.call(this, 'calaApi', {
185
349
  method: 'GET',
186
- url: `${BASE_URL}/v1/knowledge/entities/${entityId}`,
350
+ url: `${BASE_URL}/v1/entities/${entityId}/introspection`,
187
351
  json: true,
188
352
  });
189
353
  }
@@ -200,6 +364,8 @@ class Cala {
200
364
  });
201
365
  }
202
366
  catch (error) {
367
+ if (error instanceof n8n_workflow_1.NodeOperationError)
368
+ throw error;
203
369
  if (this.continueOnFail()) {
204
370
  returnData.push({
205
371
  json: { error: new n8n_workflow_1.NodeApiError(this.getNode(), error).message },
@@ -207,7 +373,7 @@ class Cala {
207
373
  });
208
374
  continue;
209
375
  }
210
- throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
376
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error, { itemIndex: i });
211
377
  }
212
378
  }
213
379
  return [returnData];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-cala",
3
- "version": "0.4.15",
3
+ "version": "0.4.16",
4
4
  "description": "n8n nodes for Cala AI knowledge search",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",