@ariaflowagents/postgres-store 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/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # @ariaflowagents/postgres-store
2
+
3
+ PostgreSQL-backed SessionStore for AriaFlow.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @ariaflowagents/postgres-store pg
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { Pool } from 'pg';
15
+ import { PostgresSessionStore } from '@ariaflowagents/postgres-store';
16
+
17
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL });
18
+ const sessionStore = new PostgresSessionStore({ client: pool });
19
+ ```
20
+
21
+ ## Options
22
+
23
+ - `tableName` (default: `ariaflow_sessions`)
24
+ - `autoMigrate` (default: true) creates the table on first use
25
+ ```
@@ -0,0 +1,24 @@
1
+ import type { Session, SessionStore } from '@ariaflowagents/core';
2
+ import type { QueryResult } from 'pg';
3
+ type PostgresClient = {
4
+ query: (text: string, params?: unknown[]) => Promise<QueryResult>;
5
+ };
6
+ export type PostgresStoreOptions = {
7
+ client: PostgresClient;
8
+ tableName?: string;
9
+ autoMigrate?: boolean;
10
+ };
11
+ export declare class PostgresSessionStore implements SessionStore {
12
+ private client;
13
+ private table;
14
+ private ready;
15
+ constructor(options: PostgresStoreOptions);
16
+ private init;
17
+ get(id: string): Promise<Session | null>;
18
+ save(session: Session): Promise<void>;
19
+ delete(id: string): Promise<void>;
20
+ list(userId?: string): Promise<Session[]>;
21
+ cleanup(maxAgeMs: number): Promise<number>;
22
+ }
23
+ export {};
24
+ //# sourceMappingURL=PostgresSessionStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresSessionStore.d.ts","sourceRoot":"","sources":["../src/PostgresSessionStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAEtC,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AA2CF,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,KAAK,CAAgB;gBAEjB,OAAO,EAAE,oBAAoB;YAO3B,IAAI;IAWZ,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAqBxC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAcrC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAkBzC,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CASjD"}
@@ -0,0 +1,108 @@
1
+ const defaultTable = 'ariaflow_sessions';
2
+ const reviveSession = (raw) => {
3
+ const session = { ...raw };
4
+ session.createdAt = new Date(session.createdAt);
5
+ session.updatedAt = new Date(session.updatedAt);
6
+ session.handoffHistory = (session.handoffHistory ?? []).map(record => ({
7
+ ...record,
8
+ timestamp: new Date(record.timestamp),
9
+ }));
10
+ if (session.metadata) {
11
+ session.metadata = {
12
+ ...session.metadata,
13
+ createdAt: new Date(session.metadata.createdAt),
14
+ lastActiveAt: new Date(session.metadata.lastActiveAt),
15
+ handoffHistory: (session.metadata.handoffHistory ?? []).map(record => ({
16
+ ...record,
17
+ timestamp: new Date(record.timestamp),
18
+ })),
19
+ };
20
+ }
21
+ session.agentStates = Object.fromEntries(Object.entries(session.agentStates ?? {}).map(([agentId, state]) => [
22
+ agentId,
23
+ {
24
+ ...state,
25
+ lastActive: new Date(state.lastActive),
26
+ },
27
+ ]));
28
+ return session;
29
+ };
30
+ const normalizeTableName = (tableName) => {
31
+ const table = tableName ?? defaultTable;
32
+ if (!/^[a-zA-Z0-9_.]+$/.test(table)) {
33
+ throw new Error(`Invalid table name: ${table}`);
34
+ }
35
+ return table;
36
+ };
37
+ export class PostgresSessionStore {
38
+ client;
39
+ table;
40
+ ready;
41
+ constructor(options) {
42
+ this.client = options.client;
43
+ this.table = normalizeTableName(options.tableName);
44
+ const autoMigrate = options.autoMigrate ?? true;
45
+ this.ready = autoMigrate ? this.init() : Promise.resolve();
46
+ }
47
+ async init() {
48
+ await this.client.query(`CREATE TABLE IF NOT EXISTS ${this.table} (
49
+ id TEXT PRIMARY KEY,
50
+ user_id TEXT,
51
+ data JSONB NOT NULL,
52
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
53
+ )`);
54
+ }
55
+ async get(id) {
56
+ await this.ready;
57
+ const result = await this.client.query(`SELECT data FROM ${this.table} WHERE id = $1`, [id]);
58
+ if (!result.rows.length) {
59
+ return null;
60
+ }
61
+ const raw = result.rows[0]?.data;
62
+ try {
63
+ const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
64
+ return reviveSession(parsed);
65
+ }
66
+ catch (error) {
67
+ console.error('Failed to parse session data from Postgres', error);
68
+ return null;
69
+ }
70
+ }
71
+ async save(session) {
72
+ await this.ready;
73
+ session.updatedAt = new Date();
74
+ const data = JSON.stringify(session);
75
+ await this.client.query(`INSERT INTO ${this.table} (id, user_id, data, updated_at)
76
+ VALUES ($1, $2, $3::jsonb, NOW())
77
+ ON CONFLICT (id)
78
+ DO UPDATE SET data = EXCLUDED.data, user_id = EXCLUDED.user_id, updated_at = NOW()`, [session.id, session.userId ?? null, data]);
79
+ }
80
+ async delete(id) {
81
+ await this.ready;
82
+ await this.client.query(`DELETE FROM ${this.table} WHERE id = $1`, [id]);
83
+ }
84
+ async list(userId) {
85
+ await this.ready;
86
+ const result = userId
87
+ ? await this.client.query(`SELECT data FROM ${this.table} WHERE user_id = $1`, [userId])
88
+ : await this.client.query(`SELECT data FROM ${this.table}`);
89
+ return result.rows
90
+ .map((row) => {
91
+ try {
92
+ const parsed = typeof row.data === 'string' ? JSON.parse(row.data) : row.data;
93
+ return reviveSession(parsed);
94
+ }
95
+ catch {
96
+ return null;
97
+ }
98
+ })
99
+ .filter((session) => session !== null);
100
+ }
101
+ async cleanup(maxAgeMs) {
102
+ await this.ready;
103
+ const cutoff = new Date(Date.now() - maxAgeMs);
104
+ const result = await this.client.query(`DELETE FROM ${this.table} WHERE updated_at < $1`, [cutoff]);
105
+ return result.rowCount ?? 0;
106
+ }
107
+ }
108
+ //# sourceMappingURL=PostgresSessionStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresSessionStore.js","sourceRoot":"","sources":["../src/PostgresSessionStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { PostgresSessionStore } from './PostgresSessionStore.js';
2
+ export type { PostgresStoreOptions } from './PostgresSessionStore.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { PostgresSessionStore } from './PostgresSessionStore.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@ariaflowagents/postgres-store",
3
+ "version": "0.1.0",
4
+ "description": "PostgreSQL-backed SessionStore for AriaFlow",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "peerDependencies": {
15
+ "@ariaflowagents/core": "^0.1.0",
16
+ "pg": "^8.0.0"
17
+ },
18
+ "devDependencies": {
19
+ "@ariaflowagents/core": "file:../ariaflow-core",
20
+ "@types/node": "^20.11.0",
21
+ "@types/pg": "^8.11.0",
22
+ "pg": "^8.11.0",
23
+ "typescript": "^5.3.0"
24
+ },
25
+ "scripts": {
26
+ "build": "tsc -p tsconfig.json",
27
+ "clean": "rm -rf dist",
28
+ "prepublishOnly": "npm run build"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "README.md"
36
+ ]
37
+ }