n8n-nodes-intersystems-iris 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.md +21 -0
- package/README.md +78 -0
- package/dist/credentials/IrisPgwireApi.credentials.d.ts +8 -0
- package/dist/credentials/IrisPgwireApi.credentials.js +89 -0
- package/dist/credentials/IrisPgwireApi.credentials.js.map +1 -0
- package/dist/nodes/MemoryIrisChat/IrisChatMessageHistory.d.ts +21 -0
- package/dist/nodes/MemoryIrisChat/IrisChatMessageHistory.js +75 -0
- package/dist/nodes/MemoryIrisChat/IrisChatMessageHistory.js.map +1 -0
- package/dist/nodes/MemoryIrisChat/MemoryIrisChat.node.d.ts +11 -0
- package/dist/nodes/MemoryIrisChat/MemoryIrisChat.node.js +146 -0
- package/dist/nodes/MemoryIrisChat/MemoryIrisChat.node.js.map +1 -0
- package/dist/nodes/MemoryIrisChat/descriptions.d.ts +6 -0
- package/dist/nodes/MemoryIrisChat/descriptions.js +68 -0
- package/dist/nodes/MemoryIrisChat/descriptions.js.map +1 -0
- package/dist/nodes/MemoryIrisChat/helpers.d.ts +2 -0
- package/dist/nodes/MemoryIrisChat/helpers.js +40 -0
- package/dist/nodes/MemoryIrisChat/helpers.js.map +1 -0
- package/dist/nodes/MemoryIrisChat/iris.svg +4 -0
- package/dist/package.json +72 -0
- package/package.json +72 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 InterSystems Community
|
|
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,78 @@
|
|
|
1
|
+
# n8n-nodes-intersystems-iris
|
|
2
|
+
|
|
3
|
+
An [n8n](https://n8n.io) community node that stores AI agent **chat memory** in
|
|
4
|
+
[InterSystems IRIS](https://www.intersystems.com/products/intersystems-iris/),
|
|
5
|
+
using IRIS's PostgreSQL wire-protocol endpoint
|
|
6
|
+
([iris-pgwire](https://github.com/intersystems-community/iris-pgwire)).
|
|
7
|
+
|
|
8
|
+
The table schema, message inserts, and reads all live in IRIS. The PostgreSQL
|
|
9
|
+
client library is only used as the transport.
|
|
10
|
+
|
|
11
|
+
## Nodes
|
|
12
|
+
|
|
13
|
+
- **IRIS Chat Memory** — a Memory sub-node for the AI Agent. Persists the
|
|
14
|
+
conversation history to an IRIS table, keyed by session, with a configurable
|
|
15
|
+
context window.
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
- An InterSystems IRIS instance reachable over
|
|
20
|
+
[iris-pgwire](https://github.com/intersystems-community/iris-pgwire).
|
|
21
|
+
- n8n `1.x` or later with community nodes enabled.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
Follow the
|
|
26
|
+
[community node installation guide](https://docs.n8n.io/integrations/community-nodes/installation/),
|
|
27
|
+
or in n8n go to **Settings → Community Nodes → Install** and enter:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
n8n-nodes-intersystems-iris
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Credential: IRIS Pgwire API
|
|
34
|
+
|
|
35
|
+
| Field | Notes |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| Host | IRIS host running iris-pgwire |
|
|
38
|
+
| Namespace | IRIS namespace (maps to the Postgres "database" concept), e.g. `USER` |
|
|
39
|
+
| User | e.g. `_SYSTEM` |
|
|
40
|
+
| Password | |
|
|
41
|
+
| Port | iris-pgwire listener port (commonly `5432`) |
|
|
42
|
+
| SSL | `disable` / `allow` / `require` |
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
1. Add an **AI Agent** node with a **Chat Trigger**.
|
|
47
|
+
2. On the Agent's **Memory** input, add **IRIS Chat Memory**.
|
|
48
|
+
3. Select (or create) an **IRIS Pgwire API** credential.
|
|
49
|
+
4. Optionally set the **Table Name** (default `n8n_chat_histories`) and
|
|
50
|
+
**Context Window Length**.
|
|
51
|
+
|
|
52
|
+
The table is created automatically on first use.
|
|
53
|
+
|
|
54
|
+
## How it differs from the Postgres Chat Memory node
|
|
55
|
+
|
|
56
|
+
IRIS pgwire speaks the PostgreSQL protocol, but IRIS is a different database
|
|
57
|
+
underneath. This node handles two protocol differences:
|
|
58
|
+
|
|
59
|
+
- **No `JSON`/`JSONB` column type.** The stock LangChain Postgres history stores
|
|
60
|
+
its message column as `JSONB`, which IRIS rejects. This node stores the
|
|
61
|
+
serialized message in a wide `VARCHAR` and (de)serializes the JSON in
|
|
62
|
+
JavaScript. `LONGVARCHAR` is avoided because over pgwire it reads back as a
|
|
63
|
+
stream reference rather than inline text.
|
|
64
|
+
- **Zero-row `DELETE`.** IRIS pgwire raises an error when a `DELETE` matches no
|
|
65
|
+
rows; clearing an empty session is treated as a valid no-op.
|
|
66
|
+
|
|
67
|
+
## Development
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm install
|
|
71
|
+
npm run build # n8n-node build
|
|
72
|
+
npm run lint # n8n-node lint
|
|
73
|
+
npm test # vitest
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
[MIT](LICENSE.md)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare class IrisPgwireApi implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
icon: "file:../nodes/MemoryIrisChat/iris.svg";
|
|
6
|
+
documentationUrl: string;
|
|
7
|
+
properties: INodeProperties[];
|
|
8
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IrisPgwireApi = void 0;
|
|
4
|
+
class IrisPgwireApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'irisPgwireApi';
|
|
7
|
+
this.displayName = 'IRIS Pgwire API';
|
|
8
|
+
this.icon = 'file:../nodes/MemoryIrisChat/iris.svg';
|
|
9
|
+
this.documentationUrl = 'https://github.com/intersystems-community/iris-pgwire';
|
|
10
|
+
this.properties = [
|
|
11
|
+
{
|
|
12
|
+
displayName: 'Host',
|
|
13
|
+
name: 'host',
|
|
14
|
+
type: 'string',
|
|
15
|
+
default: 'localhost',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
displayName: 'Namespace',
|
|
19
|
+
name: 'database',
|
|
20
|
+
type: 'string',
|
|
21
|
+
default: 'USER',
|
|
22
|
+
description: 'The IRIS namespace to connect to (mapped to the Postgres "database" concept)',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
displayName: 'User',
|
|
26
|
+
name: 'user',
|
|
27
|
+
type: 'string',
|
|
28
|
+
default: '_SYSTEM',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
displayName: 'Password',
|
|
32
|
+
name: 'password',
|
|
33
|
+
type: 'string',
|
|
34
|
+
typeOptions: {
|
|
35
|
+
password: true,
|
|
36
|
+
},
|
|
37
|
+
default: '',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
displayName: 'Maximum Number of Connections',
|
|
41
|
+
name: 'maxConnections',
|
|
42
|
+
type: 'number',
|
|
43
|
+
default: 100,
|
|
44
|
+
description: 'Make sure this value times the number of workers you have is lower than the maximum number of connections your IRIS instance allows.',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
displayName: 'Ignore SSL Issues (Insecure)',
|
|
48
|
+
name: 'allowUnauthorizedCerts',
|
|
49
|
+
type: 'boolean',
|
|
50
|
+
default: false,
|
|
51
|
+
description: 'Whether to connect even if SSL certificate validation is not possible',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
displayName: 'SSL',
|
|
55
|
+
name: 'ssl',
|
|
56
|
+
type: 'options',
|
|
57
|
+
displayOptions: {
|
|
58
|
+
show: {
|
|
59
|
+
allowUnauthorizedCerts: [false],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
options: [
|
|
63
|
+
{
|
|
64
|
+
name: 'Allow',
|
|
65
|
+
value: 'allow',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'Disable',
|
|
69
|
+
value: 'disable',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: 'Require',
|
|
73
|
+
value: 'require',
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
default: 'disable',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
displayName: 'Port',
|
|
80
|
+
name: 'port',
|
|
81
|
+
type: 'number',
|
|
82
|
+
default: 5432,
|
|
83
|
+
description: 'The iris-pgwire listener port',
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.IrisPgwireApi = IrisPgwireApi;
|
|
89
|
+
//# sourceMappingURL=IrisPgwireApi.credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IrisPgwireApi.credentials.js","sourceRoot":"","sources":["../../credentials/IrisPgwireApi.credentials.ts"],"names":[],"mappings":";;;AAYA,MAAa,aAAa;IAA1B;QACC,SAAI,GAAG,eAAe,CAAC;QAEvB,gBAAW,GAAG,iBAAiB,CAAC;QAEhC,SAAI,GAAG,uCAAgD,CAAC;QAExD,qBAAgB,GAAG,uDAAuD,CAAC;QAE3E,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,MAAM;gBACnB,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,WAAW;aACpB;YACD;gBACC,WAAW,EAAE,WAAW;gBACxB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,MAAM;gBACf,WAAW,EAAE,8EAA8E;aAC3F;YACD;gBACC,WAAW,EAAE,MAAM;gBACnB,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,SAAS;aAClB;YACD;gBACC,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE;oBACZ,QAAQ,EAAE,IAAI;iBACd;gBACD,OAAO,EAAE,EAAE;aACX;YACD;gBACC,WAAW,EAAE,+BAA+B;gBAC5C,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,GAAG;gBACZ,WAAW,EACV,sIAAsI;aACvI;YAGD;gBACC,WAAW,EAAE,8BAA8B;gBAC3C,IAAI,EAAE,wBAAwB;gBAC9B,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,KAAK;gBACd,WAAW,EAAE,uEAAuE;aACpF;YACD;gBACC,WAAW,EAAE,KAAK;gBAClB,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,SAAS;gBACf,cAAc,EAAE;oBACf,IAAI,EAAE;wBACL,sBAAsB,EAAE,CAAC,KAAK,CAAC;qBAC/B;iBACD;gBACD,OAAO,EAAE;oBACR;wBACC,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE,OAAO;qBACd;oBACD;wBACC,IAAI,EAAE,SAAS;wBACf,KAAK,EAAE,SAAS;qBAChB;oBACD;wBACC,IAAI,EAAE,SAAS;wBACf,KAAK,EAAE,SAAS;qBAChB;iBACD;gBACD,OAAO,EAAE,SAAS;aAClB;YACD;gBACC,WAAW,EAAE,MAAM;gBACnB,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,IAAI;gBACb,WAAW,EAAE,+BAA+B;aAC5C;SACD,CAAC;IACH,CAAC;CAAA;AAxFD,sCAwFC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseListChatMessageHistory } from '@langchain/core/chat_history';
|
|
2
|
+
import type { BaseMessage } from '@langchain/core/messages';
|
|
3
|
+
import type pg from 'pg';
|
|
4
|
+
export interface IrisChatMessageHistoryInput {
|
|
5
|
+
pool: pg.Pool;
|
|
6
|
+
sessionId: string;
|
|
7
|
+
tableName?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class IrisChatMessageHistory extends BaseListChatMessageHistory {
|
|
10
|
+
lc_namespace: string[];
|
|
11
|
+
private pool;
|
|
12
|
+
private tableName;
|
|
13
|
+
private sessionId;
|
|
14
|
+
private initialized;
|
|
15
|
+
private static readonly MESSAGE_COLUMN_LENGTH;
|
|
16
|
+
constructor(fields: IrisChatMessageHistoryInput);
|
|
17
|
+
private ensureTable;
|
|
18
|
+
getMessages(): Promise<BaseMessage[]>;
|
|
19
|
+
addMessage(message: BaseMessage): Promise<void>;
|
|
20
|
+
clear(): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IrisChatMessageHistory = void 0;
|
|
4
|
+
const chat_history_1 = require("@langchain/core/chat_history");
|
|
5
|
+
const messages_1 = require("@langchain/core/messages");
|
|
6
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
7
|
+
class IrisChatMessageHistory extends chat_history_1.BaseListChatMessageHistory {
|
|
8
|
+
constructor(fields) {
|
|
9
|
+
var _a;
|
|
10
|
+
super();
|
|
11
|
+
this.lc_namespace = ['langchain', 'stores', 'message', 'iris'];
|
|
12
|
+
this.initialized = false;
|
|
13
|
+
this.pool = fields.pool;
|
|
14
|
+
this.sessionId = fields.sessionId;
|
|
15
|
+
this.tableName = (_a = fields.tableName) !== null && _a !== void 0 ? _a : 'n8n_chat_histories';
|
|
16
|
+
}
|
|
17
|
+
async ensureTable() {
|
|
18
|
+
if (this.initialized)
|
|
19
|
+
return;
|
|
20
|
+
const query = `
|
|
21
|
+
CREATE TABLE IF NOT EXISTS ${this.tableName} (
|
|
22
|
+
id SERIAL PRIMARY KEY,
|
|
23
|
+
session_id VARCHAR(255) NOT NULL,
|
|
24
|
+
message VARCHAR(${IrisChatMessageHistory.MESSAGE_COLUMN_LENGTH}) NOT NULL
|
|
25
|
+
)`;
|
|
26
|
+
try {
|
|
27
|
+
await this.pool.query(query);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (typeof error !== 'object' ||
|
|
31
|
+
error === null ||
|
|
32
|
+
!('code' in error) ||
|
|
33
|
+
error.code !== '23505') {
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
this.initialized = true;
|
|
38
|
+
}
|
|
39
|
+
async getMessages() {
|
|
40
|
+
await this.ensureTable();
|
|
41
|
+
const query = `SELECT message FROM ${this.tableName} WHERE session_id = $1 ORDER BY id`;
|
|
42
|
+
const result = await this.pool.query(query, [this.sessionId]);
|
|
43
|
+
const storedMessages = result.rows.map((row) => {
|
|
44
|
+
const parsed = (0, n8n_workflow_1.jsonParse)(row.message);
|
|
45
|
+
const { type, ...data } = parsed;
|
|
46
|
+
return { type, data };
|
|
47
|
+
});
|
|
48
|
+
return (0, messages_1.mapStoredMessagesToChatMessages)(storedMessages);
|
|
49
|
+
}
|
|
50
|
+
async addMessage(message) {
|
|
51
|
+
await this.ensureTable();
|
|
52
|
+
const { data, type } = (0, messages_1.mapChatMessagesToStoredMessages)([message])[0];
|
|
53
|
+
const serialized = JSON.stringify({ ...data, type });
|
|
54
|
+
const query = `INSERT INTO ${this.tableName} (session_id, message) VALUES ($1, $2)`;
|
|
55
|
+
await this.pool.query(query, [this.sessionId, serialized]);
|
|
56
|
+
}
|
|
57
|
+
async clear() {
|
|
58
|
+
await this.ensureTable();
|
|
59
|
+
const query = `DELETE FROM ${this.tableName} WHERE session_id = $1`;
|
|
60
|
+
try {
|
|
61
|
+
await this.pool.query(query, [this.sessionId]);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (typeof error !== 'object' ||
|
|
65
|
+
error === null ||
|
|
66
|
+
!('code' in error) ||
|
|
67
|
+
error.code !== 'XX000') {
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.IrisChatMessageHistory = IrisChatMessageHistory;
|
|
74
|
+
IrisChatMessageHistory.MESSAGE_COLUMN_LENGTH = 1000000;
|
|
75
|
+
//# sourceMappingURL=IrisChatMessageHistory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IrisChatMessageHistory.js","sourceRoot":"","sources":["../../../nodes/MemoryIrisChat/IrisChatMessageHistory.ts"],"names":[],"mappings":";;;AAAA,+DAA0E;AAE1E,uDAGkC;AAClC,+CAAyC;AAqBzC,MAAa,sBAAuB,SAAQ,yCAA0B;IAerE,YAAY,MAAmC;;QAC9C,KAAK,EAAE,CAAC;QAfT,iBAAY,GAAG,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAQlD,gBAAW,GAAG,KAAK,CAAC;QAQ3B,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,MAAA,MAAM,CAAC,SAAS,mCAAI,oBAAoB,CAAC;IAC3D,CAAC;IAEO,KAAK,CAAC,WAAW;QACxB,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO;QAE7B,MAAM,KAAK,GAAG;gCACgB,IAAI,CAAC,SAAS;;;sBAGxB,sBAAsB,CAAC,qBAAqB;KAC7D,CAAC;QAEJ,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAEhB,IACC,OAAO,KAAK,KAAK,QAAQ;gBACzB,KAAK,KAAK,IAAI;gBACd,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;gBACjB,KAA2B,CAAC,IAAI,KAAK,OAAO,EAC5C,CAAC;gBAKF,MAAM,KAAK,CAAC;YACb,CAAC;QACF,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,WAAW;QAChB,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAEzB,MAAM,KAAK,GAAG,uBAAuB,IAAI,CAAC,SAAS,oCAAoC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAsB,KAAK,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QAEnF,MAAM,cAAc,GAAoB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC/D,MAAM,MAAM,GAAG,IAAA,wBAAS,EAA2C,GAAG,CAAC,OAAO,CAAC,CAAC;YAChF,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;YACjC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAmB,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,OAAO,IAAA,0CAA+B,EAAC,cAAc,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAoB;QACpC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAEzB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAA,0CAA+B,EAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrE,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAErD,MAAM,KAAK,GAAG,eAAe,IAAI,CAAC,SAAS,wCAAwC,CAAC;QACpF,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,KAAK;QACV,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAEzB,MAAM,KAAK,GAAG,eAAe,IAAI,CAAC,SAAS,wBAAwB,CAAC;QACpE,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAIhB,IACC,OAAO,KAAK,KAAK,QAAQ;gBACzB,KAAK,KAAK,IAAI;gBACd,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;gBACjB,KAA2B,CAAC,IAAI,KAAK,OAAO,EAC5C,CAAC;gBAGF,MAAM,KAAK,CAAC;YACb,CAAC;QACF,CAAC;IACF,CAAC;;AAnGF,wDAoGC;AAvFwB,4CAAqB,GAAG,OAAO,AAAV,CAAW"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ICredentialsDecrypted, ICredentialTestFunctions, INodeCredentialTestResult, ISupplyDataFunctions, INodeType, INodeTypeDescription, SupplyData } from 'n8n-workflow';
|
|
2
|
+
export declare function irisPgwireConnectionTest(this: ICredentialTestFunctions, credential: ICredentialsDecrypted): Promise<INodeCredentialTestResult>;
|
|
3
|
+
export declare class MemoryIrisChat implements INodeType {
|
|
4
|
+
description: INodeTypeDescription;
|
|
5
|
+
methods: {
|
|
6
|
+
credentialTest: {
|
|
7
|
+
irisPgwireConnectionTest: typeof irisPgwireConnectionTest;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MemoryIrisChat = void 0;
|
|
7
|
+
exports.irisPgwireConnectionTest = irisPgwireConnectionTest;
|
|
8
|
+
const memory_1 = require("@langchain/classic/memory");
|
|
9
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
10
|
+
const pg_1 = __importDefault(require("pg"));
|
|
11
|
+
const descriptions_1 = require("./descriptions");
|
|
12
|
+
const helpers_1 = require("./helpers");
|
|
13
|
+
const IrisChatMessageHistory_1 = require("./IrisChatMessageHistory");
|
|
14
|
+
function createPool(credentials) {
|
|
15
|
+
var _a;
|
|
16
|
+
const config = {
|
|
17
|
+
host: credentials.host,
|
|
18
|
+
port: credentials.port,
|
|
19
|
+
database: credentials.database,
|
|
20
|
+
user: credentials.user,
|
|
21
|
+
password: credentials.password,
|
|
22
|
+
max: (_a = credentials.maxConnections) !== null && _a !== void 0 ? _a : 100,
|
|
23
|
+
keepAlive: true,
|
|
24
|
+
};
|
|
25
|
+
if (credentials.allowUnauthorizedCerts) {
|
|
26
|
+
config.ssl = { rejectUnauthorized: false };
|
|
27
|
+
}
|
|
28
|
+
else if (credentials.ssl && credentials.ssl !== 'disable') {
|
|
29
|
+
config.ssl = true;
|
|
30
|
+
}
|
|
31
|
+
return new pg_1.default.Pool(config);
|
|
32
|
+
}
|
|
33
|
+
async function irisPgwireConnectionTest(credential) {
|
|
34
|
+
const credentials = credential.data;
|
|
35
|
+
const pool = createPool(credentials);
|
|
36
|
+
try {
|
|
37
|
+
const client = await pool.connect();
|
|
38
|
+
client.release();
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
let message = error.message;
|
|
42
|
+
if (message.includes('ECONNREFUSED')) {
|
|
43
|
+
message = 'Connection refused — is iris-pgwire running on that host/port?';
|
|
44
|
+
}
|
|
45
|
+
else if (message.includes('ENOTFOUND')) {
|
|
46
|
+
message = 'Host not found, please check your host name';
|
|
47
|
+
}
|
|
48
|
+
else if (message.includes('ETIMEDOUT')) {
|
|
49
|
+
message = 'Connection timed out';
|
|
50
|
+
}
|
|
51
|
+
return { status: 'Error', message };
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
await pool.end();
|
|
55
|
+
}
|
|
56
|
+
return { status: 'OK', message: 'Connection successful!' };
|
|
57
|
+
}
|
|
58
|
+
class MemoryIrisChat {
|
|
59
|
+
constructor() {
|
|
60
|
+
this.description = {
|
|
61
|
+
displayName: 'IRIS Chat Memory',
|
|
62
|
+
name: 'memoryIrisChat',
|
|
63
|
+
icon: 'file:iris.svg',
|
|
64
|
+
group: ['transform'],
|
|
65
|
+
version: [1],
|
|
66
|
+
description: 'Stores the chat history in an InterSystems IRIS table over pgwire',
|
|
67
|
+
subtitle: '={{ $parameter["tableName"] }}',
|
|
68
|
+
defaults: {
|
|
69
|
+
name: 'IRIS Chat Memory',
|
|
70
|
+
},
|
|
71
|
+
credentials: [
|
|
72
|
+
{
|
|
73
|
+
name: 'irisPgwireApi',
|
|
74
|
+
required: true,
|
|
75
|
+
testedBy: 'irisPgwireConnectionTest',
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
codex: {
|
|
79
|
+
categories: ['AI'],
|
|
80
|
+
subcategories: {
|
|
81
|
+
AI: ['Memory'],
|
|
82
|
+
Memory: ['Other memories'],
|
|
83
|
+
},
|
|
84
|
+
resources: {
|
|
85
|
+
primaryDocumentation: [
|
|
86
|
+
{
|
|
87
|
+
url: 'https://github.com/intersystems-community/n8n-nodes-intersystems-iris',
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
inputs: [],
|
|
93
|
+
outputs: [n8n_workflow_1.NodeConnectionTypes.AiMemory],
|
|
94
|
+
outputNames: ['Memory'],
|
|
95
|
+
properties: [
|
|
96
|
+
{
|
|
97
|
+
displayName: "This node must be connected to an AI Agent's <b>Memory</b> input. <a data-action='openSelectiveNodeCreator' data-action-parameter-creatorview='AiMemory'>Insert one</a>",
|
|
98
|
+
name: 'notice',
|
|
99
|
+
type: 'notice',
|
|
100
|
+
default: '',
|
|
101
|
+
},
|
|
102
|
+
descriptions_1.sessionIdOption,
|
|
103
|
+
(0, descriptions_1.expressionSessionKeyProperty)(1),
|
|
104
|
+
(0, descriptions_1.scopedSessionHint)(1),
|
|
105
|
+
descriptions_1.sessionKeyProperty,
|
|
106
|
+
{
|
|
107
|
+
displayName: 'Table Name',
|
|
108
|
+
name: 'tableName',
|
|
109
|
+
type: 'string',
|
|
110
|
+
default: 'n8n_chat_histories',
|
|
111
|
+
description: 'The table name to store the chat history in. If table does not exist, it will be created.',
|
|
112
|
+
},
|
|
113
|
+
descriptions_1.contextWindowLengthProperty,
|
|
114
|
+
],
|
|
115
|
+
};
|
|
116
|
+
this.methods = {
|
|
117
|
+
credentialTest: {
|
|
118
|
+
irisPgwireConnectionTest,
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async supplyData(itemIndex) {
|
|
123
|
+
const credentials = (await this.getCredentials('irisPgwireApi'));
|
|
124
|
+
const tableName = this.getNodeParameter('tableName', itemIndex, 'n8n_chat_histories');
|
|
125
|
+
const sessionId = (0, helpers_1.getSessionId)(this, itemIndex);
|
|
126
|
+
const pool = createPool(credentials);
|
|
127
|
+
const irisChatHistory = new IrisChatMessageHistory_1.IrisChatMessageHistory({
|
|
128
|
+
pool,
|
|
129
|
+
sessionId,
|
|
130
|
+
tableName,
|
|
131
|
+
});
|
|
132
|
+
const memory = new memory_1.BufferWindowMemory({
|
|
133
|
+
memoryKey: 'chat_history',
|
|
134
|
+
chatHistory: irisChatHistory,
|
|
135
|
+
returnMessages: true,
|
|
136
|
+
inputKey: 'input',
|
|
137
|
+
outputKey: 'output',
|
|
138
|
+
k: this.getNodeParameter('contextWindowLength', itemIndex),
|
|
139
|
+
});
|
|
140
|
+
return {
|
|
141
|
+
response: memory,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
exports.MemoryIrisChat = MemoryIrisChat;
|
|
146
|
+
//# sourceMappingURL=MemoryIrisChat.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryIrisChat.node.js","sourceRoot":"","sources":["../../../nodes/MemoryIrisChat/MemoryIrisChat.node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare const sessionIdOption: INodeProperties;
|
|
3
|
+
export declare const expressionSessionKeyProperty: (fromVersion: number) => INodeProperties;
|
|
4
|
+
export declare const sessionKeyProperty: INodeProperties;
|
|
5
|
+
export declare const contextWindowLengthProperty: INodeProperties;
|
|
6
|
+
export declare const scopedSessionHint: (minVersion: number) => INodeProperties;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scopedSessionHint = exports.contextWindowLengthProperty = exports.sessionKeyProperty = exports.expressionSessionKeyProperty = exports.sessionIdOption = void 0;
|
|
4
|
+
exports.sessionIdOption = {
|
|
5
|
+
displayName: 'Session ID',
|
|
6
|
+
name: 'sessionIdType',
|
|
7
|
+
type: 'options',
|
|
8
|
+
options: [
|
|
9
|
+
{
|
|
10
|
+
name: 'Connected Chat Trigger Node',
|
|
11
|
+
value: 'fromInput',
|
|
12
|
+
description: "Looks for an input field called 'sessionId' that is coming from a directly connected Chat Trigger",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'Define below',
|
|
16
|
+
value: 'customKey',
|
|
17
|
+
description: 'Use an expression to reference data in previous nodes or enter static text',
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
default: 'fromInput',
|
|
21
|
+
};
|
|
22
|
+
const expressionSessionKeyProperty = (fromVersion) => ({
|
|
23
|
+
displayName: 'Session Key From Previous Node',
|
|
24
|
+
name: 'sessionKey',
|
|
25
|
+
type: 'string',
|
|
26
|
+
default: '={{ $json.sessionId }}',
|
|
27
|
+
disabledOptions: { show: { sessionIdType: ['fromInput'] } },
|
|
28
|
+
displayOptions: {
|
|
29
|
+
show: {
|
|
30
|
+
sessionIdType: ['fromInput'],
|
|
31
|
+
'@version': [{ _cnd: { gte: fromVersion } }],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
exports.expressionSessionKeyProperty = expressionSessionKeyProperty;
|
|
36
|
+
exports.sessionKeyProperty = {
|
|
37
|
+
displayName: 'Key',
|
|
38
|
+
name: 'sessionKey',
|
|
39
|
+
type: 'string',
|
|
40
|
+
default: '',
|
|
41
|
+
description: 'The key to use to store session ID in the memory',
|
|
42
|
+
displayOptions: {
|
|
43
|
+
show: {
|
|
44
|
+
sessionIdType: ['customKey'],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
exports.contextWindowLengthProperty = {
|
|
49
|
+
displayName: 'Context Window Length',
|
|
50
|
+
name: 'contextWindowLength',
|
|
51
|
+
type: 'number',
|
|
52
|
+
default: 5,
|
|
53
|
+
hint: 'How many past interactions the model receives as context',
|
|
54
|
+
};
|
|
55
|
+
const scopedSessionHint = (minVersion) => ({
|
|
56
|
+
displayName: 'Session is automatically scoped only to this memory node. To share a session between different memory nodes, switch "Session ID" to "Define below" and use the same key in each node.',
|
|
57
|
+
name: 'scopedSessionHintNotice',
|
|
58
|
+
type: 'notice',
|
|
59
|
+
default: '',
|
|
60
|
+
displayOptions: {
|
|
61
|
+
show: {
|
|
62
|
+
'@version': [{ _cnd: { gte: minVersion } }],
|
|
63
|
+
sessionIdType: ['fromInput'],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
exports.scopedSessionHint = scopedSessionHint;
|
|
68
|
+
//# sourceMappingURL=descriptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descriptions.js","sourceRoot":"","sources":["../../../nodes/MemoryIrisChat/descriptions.ts"],"names":[],"mappings":";;;AASa,QAAA,eAAe,GAAoB;IAC/C,WAAW,EAAE,YAAY;IACzB,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,SAAS;IACf,OAAO,EAAE;QACR;YACC,IAAI,EAAE,6BAA6B;YACnC,KAAK,EAAE,WAAW;YAClB,WAAW,EACV,mGAAmG;SACpG;QACD;YAEC,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE,WAAW;YAClB,WAAW,EAAE,4EAA4E;SACzF;KACD;IACD,OAAO,EAAE,WAAW;CACpB,CAAC;AAEK,MAAM,4BAA4B,GAAG,CAAC,WAAmB,EAAmB,EAAE,CAAC,CAAC;IACtF,WAAW,EAAE,gCAAgC;IAC7C,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,wBAAwB;IACjC,eAAe,EAAE,EAAE,IAAI,EAAE,EAAE,aAAa,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE;IAC3D,cAAc,EAAE;QACf,IAAI,EAAE;YACL,aAAa,EAAE,CAAC,WAAW,CAAC;YAC5B,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC;SAC5C;KACD;CACD,CAAC,CAAC;AAZU,QAAA,4BAA4B,gCAYtC;AAEU,QAAA,kBAAkB,GAAoB;IAClD,WAAW,EAAE,KAAK;IAClB,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,EAAE;IACX,WAAW,EAAE,kDAAkD;IAC/D,cAAc,EAAE;QACf,IAAI,EAAE;YACL,aAAa,EAAE,CAAC,WAAW,CAAC;SAC5B;KACD;CACD,CAAC;AAEW,QAAA,2BAA2B,GAAoB;IAC3D,WAAW,EAAE,uBAAuB;IACpC,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,0DAA0D;CAChE,CAAC;AAEK,MAAM,iBAAiB,GAAG,CAAC,UAAkB,EAAmB,EAAE,CAAC,CAAC;IAC1E,WAAW,EACV,uLAAuL;IACxL,IAAI,EAAE,yBAAyB;IAC/B,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,EAAE;IACX,cAAc,EAAE;QACf,IAAI,EAAE;YACL,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,CAAC;YAC3C,aAAa,EAAE,CAAC,WAAW,CAAC;SAC5B;KACD;CACD,CAAC,CAAC;AAZU,QAAA,iBAAiB,qBAY3B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSessionId = getSessionId;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
function getSessionId(ctx, itemIndex) {
|
|
6
|
+
var _a, _b;
|
|
7
|
+
const selectorType = ctx.getNodeParameter('sessionIdType', itemIndex);
|
|
8
|
+
if (selectorType === 'fromInput') {
|
|
9
|
+
let sessionId = (_a = ctx.evaluateExpression('{{ $json.sessionId }}', itemIndex)) !== null && _a !== void 0 ? _a : '';
|
|
10
|
+
if (!sessionId) {
|
|
11
|
+
try {
|
|
12
|
+
const chatTrigger = ctx.getChatTrigger();
|
|
13
|
+
if (chatTrigger) {
|
|
14
|
+
sessionId = ctx.evaluateExpression(`{{ $('${chatTrigger.name}').first().json.sessionId }}`, itemIndex);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (!sessionId) {
|
|
21
|
+
throw new n8n_workflow_1.NodeOperationError(ctx.getNode(), 'No session ID found', {
|
|
22
|
+
description: "Expected to find the session ID in an input field called 'sessionId' (this is what the Chat Trigger node outputs). To use something else, change the 'Session ID' parameter.",
|
|
23
|
+
itemIndex,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return `${sessionId}__${sanitizeForSessionKey(ctx.getNode().name)}`;
|
|
27
|
+
}
|
|
28
|
+
const customKey = (_b = ctx.getNodeParameter('sessionKey', itemIndex, '')) !== null && _b !== void 0 ? _b : '';
|
|
29
|
+
if (!customKey) {
|
|
30
|
+
throw new n8n_workflow_1.NodeOperationError(ctx.getNode(), 'Key parameter is empty', {
|
|
31
|
+
description: "Provide a key to use as session ID in the 'Key' parameter, or use the 'Connected Chat Trigger Node' option to use the session ID from your Chat Trigger.",
|
|
32
|
+
itemIndex,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return customKey;
|
|
36
|
+
}
|
|
37
|
+
function sanitizeForSessionKey(value) {
|
|
38
|
+
return value.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../nodes/MemoryIrisChat/helpers.ts"],"names":[],"mappings":";;AAaA,oCAyCC;AArDD,+CAAkD;AAYlD,SAAgB,YAAY,CAAC,GAAyB,EAAE,SAAiB;;IACxE,MAAM,YAAY,GAAG,GAAG,CAAC,gBAAgB,CAAC,eAAe,EAAE,SAAS,CAAW,CAAC;IAEhF,IAAI,YAAY,KAAK,WAAW,EAAE,CAAC;QAClC,IAAI,SAAS,GAAG,MAAC,GAAG,CAAC,kBAAkB,CAAC,uBAAuB,EAAE,SAAS,CAAY,mCAAI,EAAE,CAAC;QAE7F,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,IAAI,CAAC;gBACJ,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;gBACzC,IAAI,WAAW,EAAE,CAAC;oBACjB,SAAS,GAAG,GAAG,CAAC,kBAAkB,CACjC,SAAS,WAAW,CAAC,IAAI,8BAA8B,EACvD,SAAS,CACC,CAAC;gBACb,CAAC;YACF,CAAC;YAAC,MAAM,CAAC;YAET,CAAC;QACF,CAAC;QAED,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,MAAM,IAAI,iCAAkB,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,qBAAqB,EAAE;gBAClE,WAAW,EACV,8KAA8K;gBAC/K,SAAS;aACT,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,GAAG,SAAS,KAAK,qBAAqB,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;IACrE,CAAC;IAED,MAAM,SAAS,GAAG,MAAC,GAAG,CAAC,gBAAgB,CAAC,YAAY,EAAE,SAAS,EAAE,EAAE,CAAY,mCAAI,EAAE,CAAC;IACtF,IAAI,CAAC,SAAS,EAAE,CAAC;QAChB,MAAM,IAAI,iCAAkB,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,wBAAwB,EAAE;YACrE,WAAW,EACV,0JAA0J;YAC3J,SAAS;SACT,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAa;IAC3C,OAAO,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "n8n-nodes-intersystems-iris",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "n8n community node to store AI agent chat memory in InterSystems IRIS over its Postgres wire protocol (iris-pgwire)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/intersystems-community/n8n-nodes-intersystems-iris",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"n8n-community-node-package",
|
|
9
|
+
"n8n",
|
|
10
|
+
"intersystems",
|
|
11
|
+
"iris",
|
|
12
|
+
"memory",
|
|
13
|
+
"chat-memory",
|
|
14
|
+
"pgwire",
|
|
15
|
+
"langchain",
|
|
16
|
+
"ai"
|
|
17
|
+
],
|
|
18
|
+
"author": {
|
|
19
|
+
"name": "InterSystems Community",
|
|
20
|
+
"email": "thomas.dyar@intersystems.com"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/intersystems-community/n8n-nodes-intersystems-iris.git"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "n8n-node build",
|
|
28
|
+
"build:watch": "tsc --watch",
|
|
29
|
+
"dev": "n8n-node dev",
|
|
30
|
+
"lint": "n8n-node lint",
|
|
31
|
+
"lint:fix": "n8n-node lint --fix",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:watch": "vitest",
|
|
34
|
+
"release": "n8n-node release",
|
|
35
|
+
"prepublishOnly": "n8n-node prerelease"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"n8n": {
|
|
44
|
+
"n8nNodesApiVersion": 1,
|
|
45
|
+
"strict": false,
|
|
46
|
+
"credentials": [
|
|
47
|
+
"dist/credentials/IrisPgwireApi.credentials.js"
|
|
48
|
+
],
|
|
49
|
+
"nodes": [
|
|
50
|
+
"dist/nodes/MemoryIrisChat/MemoryIrisChat.node.js"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"pg": "^8.13.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@langchain/classic": "^1.0.0",
|
|
58
|
+
"@langchain/core": "^1.0.0",
|
|
59
|
+
"@n8n/node-cli": "*",
|
|
60
|
+
"@types/pg": "^8.11.0",
|
|
61
|
+
"eslint": "9.39.4",
|
|
62
|
+
"prettier": "3.8.3",
|
|
63
|
+
"release-it": "20.2.0",
|
|
64
|
+
"typescript": "5.9.3",
|
|
65
|
+
"vitest": "^3.0.0"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"@langchain/classic": "*",
|
|
69
|
+
"@langchain/core": "*",
|
|
70
|
+
"n8n-workflow": "*"
|
|
71
|
+
}
|
|
72
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "n8n-nodes-intersystems-iris",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "n8n community node to store AI agent chat memory in InterSystems IRIS over its Postgres wire protocol (iris-pgwire)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/intersystems-community/n8n-nodes-intersystems-iris",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"n8n-community-node-package",
|
|
9
|
+
"n8n",
|
|
10
|
+
"intersystems",
|
|
11
|
+
"iris",
|
|
12
|
+
"memory",
|
|
13
|
+
"chat-memory",
|
|
14
|
+
"pgwire",
|
|
15
|
+
"langchain",
|
|
16
|
+
"ai"
|
|
17
|
+
],
|
|
18
|
+
"author": {
|
|
19
|
+
"name": "InterSystems Community",
|
|
20
|
+
"email": "thomas.dyar@intersystems.com"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/intersystems-community/n8n-nodes-intersystems-iris.git"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "n8n-node build",
|
|
28
|
+
"build:watch": "tsc --watch",
|
|
29
|
+
"dev": "n8n-node dev",
|
|
30
|
+
"lint": "n8n-node lint",
|
|
31
|
+
"lint:fix": "n8n-node lint --fix",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:watch": "vitest",
|
|
34
|
+
"release": "n8n-node release",
|
|
35
|
+
"prepublishOnly": "n8n-node prerelease"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"n8n": {
|
|
44
|
+
"n8nNodesApiVersion": 1,
|
|
45
|
+
"strict": false,
|
|
46
|
+
"credentials": [
|
|
47
|
+
"dist/credentials/IrisPgwireApi.credentials.js"
|
|
48
|
+
],
|
|
49
|
+
"nodes": [
|
|
50
|
+
"dist/nodes/MemoryIrisChat/MemoryIrisChat.node.js"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"pg": "^8.13.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@langchain/classic": "^1.0.0",
|
|
58
|
+
"@langchain/core": "^1.0.0",
|
|
59
|
+
"@n8n/node-cli": "*",
|
|
60
|
+
"@types/pg": "^8.11.0",
|
|
61
|
+
"eslint": "9.39.4",
|
|
62
|
+
"prettier": "3.8.3",
|
|
63
|
+
"release-it": "20.2.0",
|
|
64
|
+
"typescript": "5.9.3",
|
|
65
|
+
"vitest": "^3.0.0"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"@langchain/classic": "*",
|
|
69
|
+
"@langchain/core": "*",
|
|
70
|
+
"n8n-workflow": "*"
|
|
71
|
+
}
|
|
72
|
+
}
|