n8n-nodes-tembory 1.0.0 → 1.0.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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Node de memoria operacional da Tembory para agentes de IA no n8n.
4
4
 
5
- Versao atual: `1.0.0`.
5
+ Versao atual: `1.0.1`.
6
6
 
7
7
  O Tembory entrega contexto rico para o AI Agent sem depender apenas do historico textual da conversa. Ele combina memoria semantica, working memory, decision state, fatos estaveis do lead, historico de tools, estado operacional, action ledger, timeline de entidades, compressao de memoria, grafo, mensagens recentes e diagnosticos.
8
8
 
@@ -19,7 +19,7 @@ O smoke simula 12 trocas com tools de agenda, valida tool history, working memor
19
19
  ## Principais recursos
20
20
 
21
21
  - Porta `ai_memory` para conectar direto no AI Agent do n8n.
22
- - Campo `Projeto` para isolar memórias por cliente/workspace mesmo quando a origem repete o mesmo ID de conversa.
22
+ - Campo `Projeto` para isolar memórias por cliente/workspace mesmo quando a origem repete o mesmo ID de conversa. Ele e um namespace operacional do workflow; nao e o Project ID da credencial.
23
23
  - Entradas opcionais `ai_languageModel` e `ai_embedding` para usar os modelos conectados pelo cliente no proprio n8n.
24
24
  - Profile facts: nome, empresa, email, telefone, preferencias e contexto comercial.
25
25
  - Tool history: quais tools foram chamadas, quando, com qual status e resultado.
@@ -36,6 +36,10 @@ O smoke simula 12 trocas com tools de agenda, valida tool history, working memor
36
36
 
37
37
  O node nao fornece LLM nem embedding gerenciados pela Tembory. Todo uso de LLM e embedding deve vir dos nodes/modelos conectados no cluster do n8n do cliente. O backend do Tembory armazena e consulta os vetores recebidos prontos.
38
38
 
39
+ ## Credencial
40
+
41
+ Use apenas a credencial `Tembory API` com a API key gerada no SaaS. A API key ja identifica a conta e o projeto comercial no Tembory; por isso o node nao pede Organization ID, Project ID nem URL self-hosted.
42
+
39
43
  ## Presets operacionais
40
44
 
41
45
  O campo avancado `Preset Operacional` preenche defaults sem sobrescrever valores configurados manualmente:
@@ -4,7 +4,7 @@ exports.Mem0Api = void 0;
4
4
  class Mem0Api {
5
5
  constructor() {
6
6
  this.name = 'mem0Api';
7
- this.displayName = 'Tembory Cloud API';
7
+ this.displayName = 'Tembory API';
8
8
  this.documentationUrl = 'https://tembory.com';
9
9
  this.properties = [
10
10
  {
@@ -14,39 +14,24 @@ class Mem0Api {
14
14
  typeOptions: { password: true },
15
15
  default: '',
16
16
  required: true,
17
- description: 'API key for the managed Tembory memory backend.',
18
- },
19
- {
20
- displayName: 'Organization ID',
21
- name: 'orgId',
22
- type: 'string',
23
- default: '',
24
- description: 'Optional: Organization ID',
25
- },
26
- {
27
- displayName: 'Project ID',
28
- name: 'projectId',
29
- type: 'string',
30
- default: '',
31
- description: 'Optional: Project ID',
17
+ description: 'API key generated in the Tembory SaaS dashboard. It already identifies the account and project.',
32
18
  },
33
19
  ];
34
20
  this.authenticate = {
35
21
  type: 'generic',
36
22
  properties: {
37
23
  headers: {
38
- 'Authorization': '=Token {{$credentials.apiKey}}',
24
+ 'x-tembory-api-key': '={{$credentials.apiKey}}',
39
25
  },
40
26
  },
41
27
  };
42
28
  this.test = {
43
29
  request: {
44
- baseURL: 'https://api.mem0.ai',
45
- url: '/v1/entities/',
30
+ baseURL: 'https://api.tembory.com',
31
+ url: '/healthz',
46
32
  method: 'GET',
47
33
  },
48
34
  };
49
35
  }
50
36
  }
51
37
  exports.Mem0Api = Mem0Api;
52
-
@@ -3,46 +3,47 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mem0ApiRequest = mem0ApiRequest;
4
4
  const n8n_workflow_1 = require("n8n-workflow");
5
5
  async function mem0ApiRequest(method, endpoint, body = {}, qs = {}) {
6
- // Support both Portuguese parameter name used in CRUD node and English used in Memory node
7
- let authenticationType;
8
- try {
9
- authenticationType = this.getNodeParameter('tipoAutenticacao', 0);
10
- }
11
- catch (e) {
12
- authenticationType = this.getNodeParameter('authType', 0) || 'nuvem';
13
- // Map to legacy values used below
14
- if (authenticationType === 'cloud')
15
- authenticationType = 'nuvem';
16
- if (authenticationType === 'selfHosted')
17
- authenticationType = 'selfHosted';
18
- }
19
- let credentials;
20
- let baseUrl;
21
- if (authenticationType === 'nuvem') {
22
- credentials = await this.getCredentials('mem0Api');
23
- baseUrl = 'https://api.mem0.ai';
24
- }
25
- else {
26
- credentials = await this.getCredentials('mem0SelfHostedApi');
27
- baseUrl = credentials.baseUrl.replace(/\/$/, ''); // Remove trailing slash
28
- }
6
+ const credentials = await this.getCredentials('mem0Api');
7
+ const baseUrl = 'https://api.tembory.com';
8
+ const operation = resolveGatewayOperation(method, endpoint);
9
+ const payload = {
10
+ ...(qs && typeof qs === 'object' ? qs : {}),
11
+ ...(body && typeof body === 'object' ? body : {}),
12
+ operation,
13
+ };
29
14
  const options = {
30
- method,
31
- body,
32
- qs,
33
- url: `${baseUrl}${endpoint}`,
15
+ method: 'POST',
16
+ body: payload,
17
+ url: `${baseUrl}/api/tembory/memory`,
34
18
  json: true,
35
19
  };
36
20
  if (credentials.apiKey) {
37
21
  options.headers = {
38
- 'Authorization': `Token ${credentials.apiKey}`,
22
+ 'x-tembory-api-key': credentials.apiKey,
39
23
  };
40
24
  }
41
25
  try {
42
- return await this.helpers.request(options);
26
+ const response = await this.helpers.request(options);
27
+ return unwrapGatewayResponse(response);
43
28
  }
44
29
  catch (error) {
45
30
  throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
46
31
  }
47
32
  }
48
-
33
+ function resolveGatewayOperation(method, endpoint) {
34
+ const normalizedMethod = String(method || '').toUpperCase();
35
+ const path = String(endpoint || '').toLowerCase();
36
+ if (path.includes('search') || normalizedMethod === 'GET')
37
+ return 'memory.search';
38
+ if (path.includes('delete'))
39
+ return 'memory.delete';
40
+ if (path.includes('relation'))
41
+ return 'memory.search';
42
+ return 'memory.add';
43
+ }
44
+ function unwrapGatewayResponse(response) {
45
+ if (response && typeof response === 'object' && response.memoryCore && typeof response.memoryCore === 'object' && 'response' in response.memoryCore) {
46
+ return response.memoryCore.response;
47
+ }
48
+ return response;
49
+ }
@@ -1512,20 +1512,6 @@ class Mem0Memory {
1512
1512
  {
1513
1513
  name: 'mem0Api',
1514
1514
  required: true,
1515
- displayOptions: {
1516
- show: {
1517
- authType: ['cloud'],
1518
- },
1519
- },
1520
- },
1521
- {
1522
- name: 'mem0SelfHostedApi',
1523
- required: true,
1524
- displayOptions: {
1525
- show: {
1526
- authType: ['selfHosted'],
1527
- },
1528
- },
1529
1515
  },
1530
1516
  ],
1531
1517
  codex: {
@@ -1536,16 +1522,6 @@ class Mem0Memory {
1536
1522
  },
1537
1523
  },
1538
1524
  properties: [
1539
- {
1540
- displayName: 'Autenticação',
1541
- name: 'authType',
1542
- type: 'options',
1543
- options: [
1544
- { name: 'Tembory Cloud', value: 'cloud' },
1545
- { name: 'Self-hosted', value: 'selfHosted' },
1546
- ],
1547
- default: 'cloud',
1548
- },
1549
1525
  {
1550
1526
  displayName: 'ID da Thread',
1551
1527
  name: 'threadId',
@@ -1558,7 +1534,7 @@ class Mem0Memory {
1558
1534
  name: 'project',
1559
1535
  type: 'string',
1560
1536
  default: '={{ $json.project || $json.projectId || $json.accountId || $json.body?.account?.id || "" }}',
1561
- description: 'Namespace estável do cliente/projeto. Quando preenchido, isola memórias mesmo que duas conversas usem o mesmo ID.',
1537
+ description: 'Namespace operacional do workflow para separar clientes/workspaces. Nao e o Project ID da credencial; a API key do Tembory ja identifica o projeto comercial.',
1562
1538
  },
1563
1539
  {
1564
1540
  displayName: 'Modo de Recuperação de Contexto',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Tembory node for n8n AI Agents with profile, tools, timeline, graph and semantic memory",
5
5
  "license": "MIT",
6
6
  "homepage": "https://tembory.com",
@@ -36,8 +36,7 @@
36
36
  "n8n": {
37
37
  "n8nNodesApiVersion": 1,
38
38
  "credentials": [
39
- "dist/credentials/Mem0Api.credentials.js",
40
- "dist/credentials/Mem0SelfHostedApi.credentials.js"
39
+ "dist/credentials/Mem0Api.credentials.js"
41
40
  ],
42
41
  "nodes": [
43
42
  "dist/nodes/Mem0/Mem0Memory.node.js"
@@ -1,10 +0,0 @@
1
- import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
- export declare class Mem0SelfHostedApi implements ICredentialType {
3
- name: string;
4
- displayName: string;
5
- documentationUrl: string;
6
- properties: INodeProperties[];
7
- authenticate: IAuthenticateGeneric;
8
- test: ICredentialTestRequest;
9
- }
10
-
@@ -1,45 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Mem0SelfHostedApi = void 0;
4
- class Mem0SelfHostedApi {
5
- constructor() {
6
- this.name = 'mem0SelfHostedApi';
7
- this.displayName = 'Tembory Self-Hosted API';
8
- this.documentationUrl = 'https://tembory.com';
9
- this.properties = [
10
- {
11
- displayName: 'Base URL',
12
- name: 'baseUrl',
13
- type: 'string',
14
- default: 'http://localhost:8000',
15
- required: true,
16
- description: 'The base URL of your self-hosted Tembory memory backend',
17
- },
18
- {
19
- displayName: 'API Key',
20
- name: 'apiKey',
21
- type: 'string',
22
- typeOptions: { password: true },
23
- default: '',
24
- description: 'API key if authentication enabled',
25
- },
26
- ];
27
- this.authenticate = {
28
- type: 'generic',
29
- properties: {
30
- headers: {
31
- 'Authorization': '={{$credentials.apiKey ? "Token " + $credentials.apiKey : ""}}',
32
- },
33
- },
34
- };
35
- this.test = {
36
- request: {
37
- baseURL: '={{$credentials.baseUrl}}',
38
- url: '/v1/entities/',
39
- method: 'GET',
40
- },
41
- };
42
- }
43
- }
44
- exports.Mem0SelfHostedApi = Mem0SelfHostedApi;
45
-